@vercel/python-analysis 0.9.1 → 0.10.1
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.
- package/dist/index.cjs +281 -561
- package/dist/index.d.ts +4 -2
- package/dist/index.js +254 -536
- package/dist/manifest/package.d.ts +2 -0
- package/dist/manifest/pep508.d.ts +19 -0
- package/dist/manifest/pyproject/schema.zod.d.ts +46 -4
- package/dist/manifest/pyproject/types.d.ts +12 -2
- package/dist/manifest/python-specifiers.d.ts +2 -0
- package/dist/manifest/requirements-txt-parser.d.ts +18 -29
- package/dist/manifest/uv-config/schema.zod.d.ts +3 -0
- package/dist/manifest/uv-config/types.d.ts +5 -0
- package/dist/manifest/uv-lock-parser.d.ts +10 -0
- package/dist/manifest/wheel-compat.d.ts +16 -0
- package/dist/wasm/host-utils.d.ts +23 -0
- package/dist/wasm/interfaces/vercel-python-analysis-host-utils.d.ts +4 -0
- package/dist/wasm/interfaces/wasi-clocks-wall-clock.d.ts +5 -0
- package/dist/wasm/interfaces/wasi-filesystem-preopens.d.ts +3 -0
- package/dist/wasm/interfaces/wasi-filesystem-types.d.ts +142 -0
- package/dist/wasm/vercel_python_analysis.core.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.core2.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.core3.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.d.ts +35 -0
- package/dist/wasm/vercel_python_analysis.js +3604 -748
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -2,6 +2,84 @@
|
|
|
2
2
|
import { readFile } from "fs/promises";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
import { dirname, join } from "path";
|
|
5
|
+
|
|
6
|
+
// src/wasm/host-utils.ts
|
|
7
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
8
|
+
import { normalize } from "path/posix";
|
|
9
|
+
import { domainToUnicode as nodeDomainToUnicode } from "url";
|
|
10
|
+
var readFileStorage = new AsyncLocalStorage();
|
|
11
|
+
var WitResultError = class extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.payload = message;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
function createHostUtils() {
|
|
18
|
+
return {
|
|
19
|
+
readFile(path4) {
|
|
20
|
+
const ctx = readFileStorage.getStore();
|
|
21
|
+
if (ctx?.readFile) {
|
|
22
|
+
const relative2 = stripWorkingDir(path4, ctx.workingDir);
|
|
23
|
+
if (relative2 != null) {
|
|
24
|
+
const result = ctx.readFile(relative2);
|
|
25
|
+
if (result != null)
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
throw new WitResultError(`File not found: ${path4}`);
|
|
30
|
+
},
|
|
31
|
+
domainToAscii(domain) {
|
|
32
|
+
try {
|
|
33
|
+
if (/[:#?/@[\]%\\\t\n\r]/.test(domain)) {
|
|
34
|
+
throw new Error("domain contains invalid characters");
|
|
35
|
+
}
|
|
36
|
+
const url = new URL(`http://${domain}/`);
|
|
37
|
+
if (url.hostname === "" && domain !== "") {
|
|
38
|
+
throw new Error("domain resolved to empty hostname");
|
|
39
|
+
}
|
|
40
|
+
return url.hostname;
|
|
41
|
+
} catch {
|
|
42
|
+
throw { payload: `Invalid domain: ${domain}` };
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
domainToUnicode(domain) {
|
|
46
|
+
const result = nodeDomainToUnicode(domain);
|
|
47
|
+
if (result !== "" || domain === "") {
|
|
48
|
+
return [result, true];
|
|
49
|
+
}
|
|
50
|
+
return [domain, false];
|
|
51
|
+
},
|
|
52
|
+
nfcNormalize(s) {
|
|
53
|
+
return s.normalize("NFC");
|
|
54
|
+
},
|
|
55
|
+
nfdNormalize(s) {
|
|
56
|
+
return s.normalize("NFD");
|
|
57
|
+
},
|
|
58
|
+
nfkcNormalize(s) {
|
|
59
|
+
return s.normalize("NFKC");
|
|
60
|
+
},
|
|
61
|
+
nfkdNormalize(s) {
|
|
62
|
+
return s.normalize("NFKD");
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function stripWorkingDir(path4, workingDir) {
|
|
67
|
+
const normalized = normalize(path4);
|
|
68
|
+
if (!workingDir) {
|
|
69
|
+
return normalized;
|
|
70
|
+
}
|
|
71
|
+
const normalizedDir = normalize(workingDir);
|
|
72
|
+
const prefix = normalizedDir.endsWith("/") ? normalizedDir : normalizedDir + "/";
|
|
73
|
+
if (normalized.startsWith(prefix)) {
|
|
74
|
+
return normalized.slice(prefix.length);
|
|
75
|
+
}
|
|
76
|
+
if (normalized === normalizedDir) {
|
|
77
|
+
return "";
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/wasm/load.ts
|
|
5
83
|
var WASI_SHIM_PATH = "@bytecodealliance/preview2-shim/instantiation";
|
|
6
84
|
var WASM_MODULE_PATH = "#wasm/vercel_python_analysis.js";
|
|
7
85
|
var wasmInstance = null;
|
|
@@ -29,7 +107,10 @@ async function importWasmModule() {
|
|
|
29
107
|
const wasiShimModule = await import(WASI_SHIM_PATH);
|
|
30
108
|
const WASIShim = wasiShimModule.WASIShim;
|
|
31
109
|
const wasmModule = await import(WASM_MODULE_PATH);
|
|
32
|
-
const imports =
|
|
110
|
+
const imports = {
|
|
111
|
+
...new WASIShim().getImportObject(),
|
|
112
|
+
"vercel:python-analysis/host-utils": createHostUtils()
|
|
113
|
+
};
|
|
33
114
|
const instance = await wasmModule.instantiate(getCoreModule, imports);
|
|
34
115
|
wasmInstance = instance;
|
|
35
116
|
return instance;
|
|
@@ -102,6 +183,41 @@ function mergeExtras(existing, additional) {
|
|
|
102
183
|
}
|
|
103
184
|
return result.size > 0 ? Array.from(result) : void 0;
|
|
104
185
|
}
|
|
186
|
+
function wasmEntryToRequirement(entry) {
|
|
187
|
+
const req = {
|
|
188
|
+
name: entry.name || ""
|
|
189
|
+
};
|
|
190
|
+
if (entry.versionSpec) {
|
|
191
|
+
req.version = entry.versionSpec;
|
|
192
|
+
}
|
|
193
|
+
if (entry.extras.length > 0) {
|
|
194
|
+
req.extras = entry.extras;
|
|
195
|
+
}
|
|
196
|
+
if (entry.markers) {
|
|
197
|
+
req.markers = entry.markers;
|
|
198
|
+
}
|
|
199
|
+
if (entry.url) {
|
|
200
|
+
req.url = entry.url;
|
|
201
|
+
}
|
|
202
|
+
return req;
|
|
203
|
+
}
|
|
204
|
+
async function parsePep508(depOrDeps) {
|
|
205
|
+
const wasm = await importWasmModule();
|
|
206
|
+
if (Array.isArray(depOrDeps)) {
|
|
207
|
+
return depOrDeps.map((dep) => {
|
|
208
|
+
try {
|
|
209
|
+
return wasmEntryToRequirement(wasm.parsePep508(dep));
|
|
210
|
+
} catch {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
return wasmEntryToRequirement(wasm.parsePep508(depOrDeps));
|
|
217
|
+
} catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
105
221
|
|
|
106
222
|
// src/manifest/dist-metadata.ts
|
|
107
223
|
async function readDistInfoFile(distInfoDir, filename) {
|
|
@@ -759,7 +875,8 @@ var uvIndexEntrySchema = z3.object({
|
|
|
759
875
|
var uvConfigSchema = z3.object({
|
|
760
876
|
sources: z3.record(z3.union([dependencySourceSchema, z3.array(dependencySourceSchema)])).optional(),
|
|
761
877
|
index: z3.array(uvIndexEntrySchema).optional(),
|
|
762
|
-
workspace: uvConfigWorkspaceSchema.optional()
|
|
878
|
+
workspace: uvConfigWorkspaceSchema.optional(),
|
|
879
|
+
"dev-dependencies": z3.array(z3.string()).optional()
|
|
763
880
|
});
|
|
764
881
|
|
|
765
882
|
// src/manifest/pyproject/schema.zod.ts
|
|
@@ -800,7 +917,16 @@ var pyProjectProjectSchema = z4.object({
|
|
|
800
917
|
scripts: z4.record(z4.string()).optional(),
|
|
801
918
|
entry_points: z4.record(z4.record(z4.string())).optional()
|
|
802
919
|
});
|
|
803
|
-
var
|
|
920
|
+
var dependencyGroupIncludeSchema = z4.object({
|
|
921
|
+
"include-group": z4.string()
|
|
922
|
+
});
|
|
923
|
+
var dependencyGroupEntrySchema = z4.union([
|
|
924
|
+
z4.string(),
|
|
925
|
+
dependencyGroupIncludeSchema
|
|
926
|
+
]);
|
|
927
|
+
var pyProjectDependencyGroupsSchema = z4.record(
|
|
928
|
+
z4.array(dependencyGroupEntrySchema)
|
|
929
|
+
);
|
|
804
930
|
var pyProjectToolSectionSchema = z4.object({
|
|
805
931
|
uv: uvConfigSchema.optional()
|
|
806
932
|
});
|
|
@@ -824,356 +950,98 @@ var PyProjectToolSectionSchema = pyProjectToolSectionSchema.passthrough();
|
|
|
824
950
|
var PyProjectTomlSchema = pyProjectTomlSchema.passthrough();
|
|
825
951
|
|
|
826
952
|
// src/manifest/requirements-txt-parser.ts
|
|
827
|
-
import {
|
|
828
|
-
import { parsePipRequirementsFile } from "pip-requirements-js";
|
|
953
|
+
import { isAbsolute, join as join3, relative } from "path/posix";
|
|
829
954
|
var PRIMARY_INDEX_NAME = "primary";
|
|
830
955
|
var EXTRA_INDEX_PREFIX = "extra-";
|
|
831
956
|
var FIND_LINKS_PREFIX = "find-links-";
|
|
832
|
-
function
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
const fragment = remaining.slice(fragmentIdx + 1);
|
|
841
|
-
remaining = remaining.slice(0, fragmentIdx);
|
|
842
|
-
for (const part of fragment.split("&")) {
|
|
843
|
-
const [key, value] = part.split("=");
|
|
844
|
-
if (key === "egg" && value) {
|
|
845
|
-
egg = value;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
let ref;
|
|
850
|
-
const lastSlashIdx = remaining.lastIndexOf("/");
|
|
851
|
-
const atIdx = remaining.indexOf("@", lastSlashIdx > 0 ? lastSlashIdx : 0);
|
|
852
|
-
if (atIdx !== -1 && atIdx > remaining.indexOf("://")) {
|
|
853
|
-
ref = remaining.slice(atIdx + 1);
|
|
854
|
-
remaining = remaining.slice(0, atIdx);
|
|
957
|
+
async function parseWithWasm(content, readFile4, workingDir) {
|
|
958
|
+
const wasm = await importWasmModule();
|
|
959
|
+
const resolvedDir = workingDir ?? "/";
|
|
960
|
+
if (readFile4) {
|
|
961
|
+
return readFileStorage.run(
|
|
962
|
+
{ readFile: readFile4, workingDir: resolvedDir },
|
|
963
|
+
() => wasm.parseRequirementsTxt(content, resolvedDir, void 0)
|
|
964
|
+
);
|
|
855
965
|
}
|
|
856
|
-
return
|
|
857
|
-
url: remaining,
|
|
858
|
-
ref,
|
|
859
|
-
egg
|
|
860
|
-
};
|
|
966
|
+
return wasm.parseRequirementsTxt(content, workingDir ?? void 0, void 0);
|
|
861
967
|
}
|
|
862
|
-
function
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
extraIndexUrls: []
|
|
870
|
-
};
|
|
871
|
-
const lines = fileContent.split(/\r?\n/);
|
|
872
|
-
const cleanedLines = [];
|
|
873
|
-
const pathRequirements = [];
|
|
874
|
-
const editableRequirements = [];
|
|
875
|
-
for (let i = 0; i < lines.length; i++) {
|
|
876
|
-
const line = lines[i];
|
|
877
|
-
const trimmed = line.trim();
|
|
878
|
-
if (trimmed === "" || trimmed.startsWith("#")) {
|
|
879
|
-
cleanedLines.push(line);
|
|
880
|
-
continue;
|
|
881
|
-
}
|
|
882
|
-
let fullLine = trimmed;
|
|
883
|
-
let linesConsumed = 0;
|
|
884
|
-
while (fullLine.endsWith("\\") && i + linesConsumed + 1 < lines.length) {
|
|
885
|
-
linesConsumed++;
|
|
886
|
-
fullLine = fullLine.slice(0, -1) + lines[i + linesConsumed].trim();
|
|
887
|
-
}
|
|
888
|
-
const extracted = tryExtractPipArgument(fullLine, options);
|
|
889
|
-
if (extracted === true) {
|
|
890
|
-
i += linesConsumed;
|
|
891
|
-
} else if (typeof extracted === "object" && extracted.editable) {
|
|
892
|
-
editableRequirements.push(extracted.editable);
|
|
893
|
-
i += linesConsumed;
|
|
894
|
-
} else {
|
|
895
|
-
if (/^-[a-zA-Z]/.test(fullLine) && !fullLine.startsWith("-r") && !fullLine.startsWith("-c")) {
|
|
896
|
-
i += linesConsumed;
|
|
897
|
-
continue;
|
|
898
|
-
}
|
|
899
|
-
const strippedLine = stripInlineHashes(fullLine);
|
|
900
|
-
const effectiveLine = (strippedLine !== fullLine ? strippedLine : fullLine).trim();
|
|
901
|
-
if (isPathOrUrlRequirement(effectiveLine)) {
|
|
902
|
-
pathRequirements.push(effectiveLine);
|
|
903
|
-
} else if (strippedLine !== fullLine) {
|
|
904
|
-
cleanedLines.push(strippedLine);
|
|
905
|
-
} else {
|
|
906
|
-
cleanedLines.push(line);
|
|
907
|
-
for (let j = 1; j <= linesConsumed; j++) {
|
|
908
|
-
cleanedLines.push(lines[i + j]);
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
i += linesConsumed;
|
|
968
|
+
function wasmEntryToNormalized(entry, editable) {
|
|
969
|
+
let name = entry.name || "";
|
|
970
|
+
if (!name && entry.url) {
|
|
971
|
+
const urlPath = entry.url.replace(/^file:\/\//, "");
|
|
972
|
+
const basename = urlPath.replace(/\/$/, "").split("/").pop();
|
|
973
|
+
if (basename && !basename.includes(".")) {
|
|
974
|
+
name = basename;
|
|
912
975
|
}
|
|
913
976
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
options,
|
|
917
|
-
pathRequirements,
|
|
918
|
-
editableRequirements
|
|
977
|
+
const req = {
|
|
978
|
+
name
|
|
919
979
|
};
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
if (line.startsWith("--requirement")) {
|
|
923
|
-
const path4 = extractArgValue(line, "--requirement");
|
|
924
|
-
if (path4) {
|
|
925
|
-
options.requirementFiles.push(path4);
|
|
926
|
-
return true;
|
|
927
|
-
}
|
|
980
|
+
if (entry.versionSpec) {
|
|
981
|
+
req.version = entry.versionSpec;
|
|
928
982
|
}
|
|
929
|
-
if (
|
|
930
|
-
|
|
931
|
-
if (path4) {
|
|
932
|
-
options.constraintFiles.push(path4);
|
|
933
|
-
return true;
|
|
934
|
-
}
|
|
983
|
+
if (entry.extras.length > 0) {
|
|
984
|
+
req.extras = entry.extras;
|
|
935
985
|
}
|
|
936
|
-
if (
|
|
937
|
-
|
|
938
|
-
if (url) {
|
|
939
|
-
options.indexUrl = url;
|
|
940
|
-
return true;
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
if (line.startsWith("-i ") || line === "-i") {
|
|
944
|
-
const match = line.match(/^-i\s+(\S+)/);
|
|
945
|
-
if (match) {
|
|
946
|
-
options.indexUrl = match[1];
|
|
947
|
-
return true;
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
if (line.startsWith("--extra-index-url")) {
|
|
951
|
-
const url = extractArgValue(line, "--extra-index-url");
|
|
952
|
-
if (url) {
|
|
953
|
-
options.extraIndexUrls.push(url);
|
|
954
|
-
return true;
|
|
955
|
-
}
|
|
986
|
+
if (entry.markers) {
|
|
987
|
+
req.markers = entry.markers;
|
|
956
988
|
}
|
|
957
|
-
if (
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
if (line.startsWith("-e ") || line.startsWith("-e ")) {
|
|
964
|
-
const path4 = line.slice(2).trim();
|
|
965
|
-
if (path4) {
|
|
966
|
-
return { editable: path4 };
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
if (line.startsWith("--find-links")) {
|
|
970
|
-
const url = extractArgValue(line, "--find-links");
|
|
971
|
-
if (url) {
|
|
972
|
-
if (!options.findLinks)
|
|
973
|
-
options.findLinks = [];
|
|
974
|
-
options.findLinks.push(url);
|
|
975
|
-
return true;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
if (line.startsWith("-f ") || line.startsWith("-f ")) {
|
|
979
|
-
const match = line.match(/^-f\s+(\S+)/);
|
|
980
|
-
if (match) {
|
|
981
|
-
if (!options.findLinks)
|
|
982
|
-
options.findLinks = [];
|
|
983
|
-
options.findLinks.push(match[1]);
|
|
984
|
-
return true;
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
if (line === "--no-index" || line.startsWith("--no-index ")) {
|
|
988
|
-
options.noIndex = true;
|
|
989
|
-
return true;
|
|
990
|
-
}
|
|
991
|
-
if (line.startsWith("--no-binary") || line.startsWith("--only-binary")) {
|
|
992
|
-
return true;
|
|
993
|
-
}
|
|
994
|
-
if (line.startsWith("--")) {
|
|
995
|
-
return true;
|
|
996
|
-
}
|
|
997
|
-
return false;
|
|
998
|
-
}
|
|
999
|
-
function stripInlineHashes(line) {
|
|
1000
|
-
return line.replace(/\s+--hash=\S+/g, "").trim();
|
|
1001
|
-
}
|
|
1002
|
-
function extractInlineHashes(line) {
|
|
1003
|
-
const hashes = [];
|
|
1004
|
-
const hashRegex = /--hash=(\S+)/g;
|
|
1005
|
-
let match;
|
|
1006
|
-
while ((match = hashRegex.exec(line)) != null) {
|
|
1007
|
-
hashes.push(match[1]);
|
|
1008
|
-
}
|
|
1009
|
-
return hashes;
|
|
1010
|
-
}
|
|
1011
|
-
function extractArgValue(line, option) {
|
|
1012
|
-
let value = null;
|
|
1013
|
-
if (line.startsWith(`${option}=`)) {
|
|
1014
|
-
value = line.slice(option.length + 1).trim();
|
|
1015
|
-
} else if (line.startsWith(`${option} `) || line.startsWith(`${option} `)) {
|
|
1016
|
-
value = line.slice(option.length).trim();
|
|
1017
|
-
}
|
|
1018
|
-
if (!value)
|
|
1019
|
-
return null;
|
|
1020
|
-
const commentIdx = value.indexOf(" #");
|
|
1021
|
-
if (commentIdx !== -1) {
|
|
1022
|
-
value = value.slice(0, commentIdx).trim();
|
|
1023
|
-
}
|
|
1024
|
-
return value || null;
|
|
1025
|
-
}
|
|
1026
|
-
function isPathOrUrlRequirement(line) {
|
|
1027
|
-
if (line.startsWith("./") || line.startsWith("../"))
|
|
1028
|
-
return true;
|
|
1029
|
-
if (line.startsWith("/"))
|
|
1030
|
-
return true;
|
|
1031
|
-
if (line.startsWith("~/"))
|
|
1032
|
-
return true;
|
|
1033
|
-
if (/^(https?|ftp|file):\/\//i.test(line))
|
|
1034
|
-
return true;
|
|
1035
|
-
if (isBareArchiveFilename(line))
|
|
1036
|
-
return true;
|
|
1037
|
-
return false;
|
|
1038
|
-
}
|
|
1039
|
-
function isBareArchiveFilename(line) {
|
|
1040
|
-
if (line.includes(" @ "))
|
|
1041
|
-
return false;
|
|
1042
|
-
let check = line;
|
|
1043
|
-
const commentIdx = check.indexOf(" #");
|
|
1044
|
-
if (commentIdx !== -1)
|
|
1045
|
-
check = check.slice(0, commentIdx);
|
|
1046
|
-
const markerIdx = check.indexOf(" ;");
|
|
1047
|
-
if (markerIdx !== -1)
|
|
1048
|
-
check = check.slice(0, markerIdx);
|
|
1049
|
-
const extrasIdx = check.indexOf("[");
|
|
1050
|
-
if (extrasIdx !== -1)
|
|
1051
|
-
check = check.slice(0, extrasIdx);
|
|
1052
|
-
check = check.trim();
|
|
1053
|
-
return /\.(whl|tar\.gz|tar\.bz2|tar\.xz|zip)$/i.test(check);
|
|
1054
|
-
}
|
|
1055
|
-
function parseWheelFilename(filename) {
|
|
1056
|
-
if (!filename.endsWith(".whl"))
|
|
1057
|
-
return null;
|
|
1058
|
-
const stem = filename.slice(0, -4);
|
|
1059
|
-
const parts = stem.split("-");
|
|
1060
|
-
if (parts.length < 5 || parts.length > 6)
|
|
1061
|
-
return null;
|
|
1062
|
-
const name = parts[0];
|
|
1063
|
-
const version = parts[1];
|
|
1064
|
-
if (!name || !version)
|
|
1065
|
-
return null;
|
|
1066
|
-
return {
|
|
1067
|
-
name: name.replace(/_/g, "-"),
|
|
1068
|
-
version
|
|
1069
|
-
};
|
|
1070
|
-
}
|
|
1071
|
-
function parseSdistFilename(filename) {
|
|
1072
|
-
let stem = filename;
|
|
1073
|
-
for (const ext of [".tar.gz", ".tar.bz2", ".tar.xz", ".zip"]) {
|
|
1074
|
-
if (stem.endsWith(ext)) {
|
|
1075
|
-
stem = stem.slice(0, -ext.length);
|
|
1076
|
-
break;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
if (stem === filename)
|
|
1080
|
-
return null;
|
|
1081
|
-
const parts = stem.split("-");
|
|
1082
|
-
let versionIdx = -1;
|
|
1083
|
-
for (let i = 1; i < parts.length; i++) {
|
|
1084
|
-
if (/^\d/.test(parts[i])) {
|
|
1085
|
-
versionIdx = i;
|
|
1086
|
-
break;
|
|
989
|
+
if (entry.vcs) {
|
|
990
|
+
const source = {
|
|
991
|
+
git: entry.vcs.url
|
|
992
|
+
};
|
|
993
|
+
if (entry.vcs.rev) {
|
|
994
|
+
source.rev = entry.vcs.rev;
|
|
1087
995
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
return null;
|
|
1091
|
-
return {
|
|
1092
|
-
name: parts.slice(0, versionIdx).join("-"),
|
|
1093
|
-
version: parts.slice(versionIdx).join("-")
|
|
1094
|
-
};
|
|
1095
|
-
}
|
|
1096
|
-
function normalizePathRequirement(rawLine) {
|
|
1097
|
-
let line = rawLine;
|
|
1098
|
-
const commentIdx = line.indexOf(" #");
|
|
1099
|
-
if (commentIdx !== -1) {
|
|
1100
|
-
line = line.slice(0, commentIdx).trim();
|
|
1101
|
-
}
|
|
1102
|
-
let markers;
|
|
1103
|
-
const markerIdx = line.indexOf(" ;");
|
|
1104
|
-
if (markerIdx !== -1) {
|
|
1105
|
-
markers = line.slice(markerIdx + 2).trim();
|
|
1106
|
-
line = line.slice(0, markerIdx).trim();
|
|
1107
|
-
}
|
|
1108
|
-
let extras;
|
|
1109
|
-
const extrasMatch = line.match(/\[([^\]]+)\]$/);
|
|
1110
|
-
if (extrasMatch) {
|
|
1111
|
-
extras = extrasMatch[1].split(",").map((e) => e.trim());
|
|
1112
|
-
line = line.slice(0, extrasMatch.index).trim();
|
|
1113
|
-
}
|
|
1114
|
-
const isUrl = /^(https?|ftp|file):\/\//i.test(line);
|
|
1115
|
-
let filename;
|
|
1116
|
-
if (isUrl) {
|
|
1117
|
-
try {
|
|
1118
|
-
const url = new URL(line);
|
|
1119
|
-
filename = url.pathname.split("/").pop() || "";
|
|
1120
|
-
} catch {
|
|
1121
|
-
return null;
|
|
996
|
+
if (editable) {
|
|
997
|
+
source.editable = true;
|
|
1122
998
|
}
|
|
1123
|
-
|
|
1124
|
-
const cleanPath = line.replace(/\/+$/, "");
|
|
1125
|
-
filename = cleanPath.split("/").pop() || "";
|
|
1126
|
-
}
|
|
1127
|
-
if (!filename)
|
|
1128
|
-
return null;
|
|
1129
|
-
let name;
|
|
1130
|
-
let version;
|
|
1131
|
-
const wheelParsed = parseWheelFilename(filename);
|
|
1132
|
-
if (wheelParsed) {
|
|
1133
|
-
name = wheelParsed.name;
|
|
1134
|
-
version = wheelParsed.version;
|
|
999
|
+
req.source = source;
|
|
1135
1000
|
}
|
|
1136
|
-
if (
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1001
|
+
if (entry.url) {
|
|
1002
|
+
if (entry.url.startsWith("file://") && !entry.vcs) {
|
|
1003
|
+
const given = entry.givenUrl ?? entry.url;
|
|
1004
|
+
const path4 = given.startsWith("file://") ? given.slice("file://".length) : given;
|
|
1005
|
+
req.source = { path: path4, ...editable ? { editable: true } : {} };
|
|
1006
|
+
} else {
|
|
1007
|
+
req.url = entry.url;
|
|
1141
1008
|
}
|
|
1142
1009
|
}
|
|
1143
|
-
if (
|
|
1144
|
-
|
|
1145
|
-
}
|
|
1146
|
-
if (!name)
|
|
1147
|
-
return null;
|
|
1148
|
-
const req = { name };
|
|
1149
|
-
if (version) {
|
|
1150
|
-
req.version = `==${version}`;
|
|
1151
|
-
}
|
|
1152
|
-
if (extras && extras.length > 0) {
|
|
1153
|
-
req.extras = extras;
|
|
1154
|
-
}
|
|
1155
|
-
if (markers) {
|
|
1156
|
-
req.markers = markers;
|
|
1157
|
-
}
|
|
1158
|
-
if (isUrl) {
|
|
1159
|
-
req.url = line;
|
|
1160
|
-
} else {
|
|
1161
|
-
req.source = { path: line };
|
|
1010
|
+
if (entry.hashes.length > 0) {
|
|
1011
|
+
req.hashes = entry.hashes;
|
|
1162
1012
|
}
|
|
1163
1013
|
return req;
|
|
1164
1014
|
}
|
|
1165
|
-
function
|
|
1015
|
+
function rebasePath(p, workingDir, packageRoot) {
|
|
1016
|
+
if (!workingDir || !packageRoot || workingDir === packageRoot)
|
|
1017
|
+
return p;
|
|
1018
|
+
if (isAbsolute(p))
|
|
1019
|
+
return p;
|
|
1020
|
+
const abs = join3(workingDir, p);
|
|
1021
|
+
const rel = relative(packageRoot, abs);
|
|
1022
|
+
if (isAbsolute(rel))
|
|
1023
|
+
return rel;
|
|
1024
|
+
if (rel.startsWith(".."))
|
|
1025
|
+
return rel;
|
|
1026
|
+
return "./" + rel;
|
|
1027
|
+
}
|
|
1028
|
+
async function convertRequirementsToPyprojectToml(fileContent, options) {
|
|
1166
1029
|
const pyproject = {};
|
|
1167
|
-
const parsed = parseRequirementsFile(fileContent,
|
|
1030
|
+
const parsed = await parseRequirementsFile(fileContent, options);
|
|
1168
1031
|
const deps = [];
|
|
1169
1032
|
const sources = {};
|
|
1033
|
+
const { workingDir, packageRoot } = options ?? {};
|
|
1170
1034
|
for (const req of parsed.requirements) {
|
|
1171
1035
|
deps.push(formatPep508(req));
|
|
1172
1036
|
if (req.source) {
|
|
1037
|
+
const source = { ...req.source };
|
|
1038
|
+
if (source.path) {
|
|
1039
|
+
source.path = rebasePath(source.path, workingDir, packageRoot);
|
|
1040
|
+
}
|
|
1173
1041
|
if (Object.prototype.hasOwnProperty.call(sources, req.name)) {
|
|
1174
|
-
sources[req.name].push(
|
|
1042
|
+
sources[req.name].push(source);
|
|
1175
1043
|
} else {
|
|
1176
|
-
sources[req.name] = [
|
|
1044
|
+
sources[req.name] = [source];
|
|
1177
1045
|
}
|
|
1178
1046
|
}
|
|
1179
1047
|
}
|
|
@@ -1223,217 +1091,39 @@ function buildIndexEntries(pipOptions) {
|
|
|
1223
1091
|
}
|
|
1224
1092
|
return indexes;
|
|
1225
1093
|
}
|
|
1226
|
-
function parseRequirementsFile(fileContent,
|
|
1227
|
-
const
|
|
1228
|
-
|
|
1094
|
+
async function parseRequirementsFile(fileContent, options) {
|
|
1095
|
+
const wasmResult = await parseWithWasm(
|
|
1096
|
+
fileContent,
|
|
1097
|
+
options?.readFile,
|
|
1098
|
+
options?.workingDir
|
|
1099
|
+
);
|
|
1100
|
+
return processWasmResult(wasmResult);
|
|
1229
1101
|
}
|
|
1230
|
-
function
|
|
1231
|
-
const { cleanedContent, options, pathRequirements, editableRequirements } = extractPipArguments(fileContent);
|
|
1232
|
-
const hashMap = buildHashMap(fileContent);
|
|
1233
|
-
const requirements = parsePipRequirementsFile(cleanedContent);
|
|
1102
|
+
function processWasmResult(wasmResult) {
|
|
1234
1103
|
const normalized = [];
|
|
1235
|
-
const
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1104
|
+
for (const entry of wasmResult.requirements) {
|
|
1105
|
+
normalized.push(wasmEntryToNormalized(entry, false));
|
|
1106
|
+
}
|
|
1107
|
+
for (const entry of wasmResult.editables) {
|
|
1108
|
+
const norm = wasmEntryToNormalized(entry, true);
|
|
1109
|
+
if (!norm.source && !entry.vcs) {
|
|
1110
|
+
norm.source = { path: entry.pep508, editable: true };
|
|
1111
|
+
} else if (norm.source && !norm.source.editable) {
|
|
1112
|
+
norm.source.editable = true;
|
|
1113
|
+
}
|
|
1114
|
+
normalized.push(norm);
|
|
1115
|
+
}
|
|
1116
|
+
const pipOptions = {
|
|
1117
|
+
indexUrl: wasmResult.indexUrl || void 0,
|
|
1118
|
+
extraIndexUrls: [...wasmResult.extraIndexUrls],
|
|
1119
|
+
findLinks: wasmResult.findLinks.length > 0 ? [...wasmResult.findLinks] : void 0,
|
|
1120
|
+
noIndex: wasmResult.noIndex || void 0
|
|
1242
1121
|
};
|
|
1243
|
-
for (const req of requirements) {
|
|
1244
|
-
if (req.type === "RequirementsFile") {
|
|
1245
|
-
mergedOptions.requirementFiles.push(req.path);
|
|
1246
|
-
continue;
|
|
1247
|
-
}
|
|
1248
|
-
if (req.type === "ConstraintsFile") {
|
|
1249
|
-
mergedOptions.constraintFiles.push(req.path);
|
|
1250
|
-
continue;
|
|
1251
|
-
}
|
|
1252
|
-
const norm = normalizeRequirement(req);
|
|
1253
|
-
if (norm != null) {
|
|
1254
|
-
const hashes = hashMap.get(norm.name.toLowerCase());
|
|
1255
|
-
if (hashes && hashes.length > 0) {
|
|
1256
|
-
norm.hashes = hashes;
|
|
1257
|
-
}
|
|
1258
|
-
normalized.push(norm);
|
|
1259
|
-
}
|
|
1260
|
-
}
|
|
1261
|
-
for (const rawPath of pathRequirements) {
|
|
1262
|
-
const norm = normalizePathRequirement(rawPath);
|
|
1263
|
-
if (norm != null) {
|
|
1264
|
-
normalized.push(norm);
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
for (const rawPath of editableRequirements) {
|
|
1268
|
-
const norm = normalizePathRequirement(rawPath);
|
|
1269
|
-
if (norm != null) {
|
|
1270
|
-
if (norm.source) {
|
|
1271
|
-
norm.source.editable = true;
|
|
1272
|
-
} else {
|
|
1273
|
-
norm.source = { path: rawPath, editable: true };
|
|
1274
|
-
}
|
|
1275
|
-
normalized.push(norm);
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
if (readFile4) {
|
|
1279
|
-
for (const refPath of mergedOptions.requirementFiles) {
|
|
1280
|
-
const refPathKey = normalize(refPath);
|
|
1281
|
-
if (visited.has(refPathKey)) {
|
|
1282
|
-
continue;
|
|
1283
|
-
}
|
|
1284
|
-
visited.add(refPathKey);
|
|
1285
|
-
const refContent = readFile4(refPath);
|
|
1286
|
-
if (refContent != null) {
|
|
1287
|
-
const refParsed = parseRequirementsFileInternal(
|
|
1288
|
-
refContent,
|
|
1289
|
-
readFile4,
|
|
1290
|
-
visited
|
|
1291
|
-
);
|
|
1292
|
-
const existingNames = new Set(
|
|
1293
|
-
normalized.map((r) => r.name.toLowerCase())
|
|
1294
|
-
);
|
|
1295
|
-
for (const req of refParsed.requirements) {
|
|
1296
|
-
if (!existingNames.has(req.name.toLowerCase())) {
|
|
1297
|
-
normalized.push(req);
|
|
1298
|
-
existingNames.add(req.name.toLowerCase());
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
if (refParsed.pipOptions.indexUrl) {
|
|
1302
|
-
mergedOptions.indexUrl = refParsed.pipOptions.indexUrl;
|
|
1303
|
-
}
|
|
1304
|
-
for (const url of refParsed.pipOptions.extraIndexUrls) {
|
|
1305
|
-
if (!mergedOptions.extraIndexUrls.includes(url)) {
|
|
1306
|
-
mergedOptions.extraIndexUrls.push(url);
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
for (const constraintPath of refParsed.pipOptions.constraintFiles) {
|
|
1310
|
-
if (!mergedOptions.constraintFiles.includes(constraintPath)) {
|
|
1311
|
-
mergedOptions.constraintFiles.push(constraintPath);
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
if (refParsed.pipOptions.findLinks) {
|
|
1315
|
-
if (!mergedOptions.findLinks)
|
|
1316
|
-
mergedOptions.findLinks = [];
|
|
1317
|
-
for (const fl of refParsed.pipOptions.findLinks) {
|
|
1318
|
-
if (!mergedOptions.findLinks.includes(fl)) {
|
|
1319
|
-
mergedOptions.findLinks.push(fl);
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
if (refParsed.pipOptions.noIndex) {
|
|
1324
|
-
mergedOptions.noIndex = true;
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
1122
|
return {
|
|
1330
1123
|
requirements: normalized,
|
|
1331
|
-
pipOptions
|
|
1124
|
+
pipOptions
|
|
1332
1125
|
};
|
|
1333
1126
|
}
|
|
1334
|
-
function buildHashMap(fileContent) {
|
|
1335
|
-
const hashMap = /* @__PURE__ */ new Map();
|
|
1336
|
-
const lines = fileContent.split(/\r?\n/);
|
|
1337
|
-
for (let i = 0; i < lines.length; i++) {
|
|
1338
|
-
let line = lines[i].trim();
|
|
1339
|
-
if (line === "" || line.startsWith("#") || line.startsWith("-")) {
|
|
1340
|
-
continue;
|
|
1341
|
-
}
|
|
1342
|
-
while (line.endsWith("\\") && i + 1 < lines.length) {
|
|
1343
|
-
i++;
|
|
1344
|
-
line = line.slice(0, -1) + lines[i].trim();
|
|
1345
|
-
}
|
|
1346
|
-
const hashes = extractInlineHashes(line);
|
|
1347
|
-
if (hashes.length === 0) {
|
|
1348
|
-
continue;
|
|
1349
|
-
}
|
|
1350
|
-
const packageMatch = line.match(/^([a-zA-Z0-9][-a-zA-Z0-9._]*)/);
|
|
1351
|
-
if (packageMatch) {
|
|
1352
|
-
const packageName = packageMatch[1].toLowerCase();
|
|
1353
|
-
hashMap.set(packageName, hashes);
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
return hashMap;
|
|
1357
|
-
}
|
|
1358
|
-
function normalizeRequirement(req) {
|
|
1359
|
-
if (req.type === "RequirementsFile" || req.type === "ConstraintsFile") {
|
|
1360
|
-
return null;
|
|
1361
|
-
}
|
|
1362
|
-
if (req.type === "ProjectURL") {
|
|
1363
|
-
return normalizeProjectURLRequirement(req);
|
|
1364
|
-
}
|
|
1365
|
-
if (req.type === "ProjectName") {
|
|
1366
|
-
return normalizeProjectNameRequirement(req);
|
|
1367
|
-
}
|
|
1368
|
-
return null;
|
|
1369
|
-
}
|
|
1370
|
-
function normalizeProjectNameRequirement(req) {
|
|
1371
|
-
const normalized = {
|
|
1372
|
-
name: req.name
|
|
1373
|
-
};
|
|
1374
|
-
if (req.extras && req.extras.length > 0) {
|
|
1375
|
-
normalized.extras = req.extras;
|
|
1376
|
-
}
|
|
1377
|
-
if (req.versionSpec && req.versionSpec.length > 0) {
|
|
1378
|
-
normalized.version = req.versionSpec.map((spec) => `${spec.operator}${spec.version}`).join(",");
|
|
1379
|
-
}
|
|
1380
|
-
if (req.environmentMarkerTree) {
|
|
1381
|
-
normalized.markers = formatEnvironmentMarkers(req.environmentMarkerTree);
|
|
1382
|
-
}
|
|
1383
|
-
return normalized;
|
|
1384
|
-
}
|
|
1385
|
-
function normalizeProjectURLRequirement(req) {
|
|
1386
|
-
const normalized = {
|
|
1387
|
-
name: req.name
|
|
1388
|
-
};
|
|
1389
|
-
if (req.extras && req.extras.length > 0) {
|
|
1390
|
-
normalized.extras = req.extras;
|
|
1391
|
-
}
|
|
1392
|
-
if (req.environmentMarkerTree) {
|
|
1393
|
-
normalized.markers = formatEnvironmentMarkers(req.environmentMarkerTree);
|
|
1394
|
-
}
|
|
1395
|
-
if (isGitUrl(req.url)) {
|
|
1396
|
-
const parsed = parseGitUrl(req.url);
|
|
1397
|
-
if (parsed) {
|
|
1398
|
-
const source = {
|
|
1399
|
-
git: parsed.url
|
|
1400
|
-
};
|
|
1401
|
-
if (parsed.ref) {
|
|
1402
|
-
source.rev = parsed.ref;
|
|
1403
|
-
}
|
|
1404
|
-
if (parsed.editable) {
|
|
1405
|
-
source.editable = true;
|
|
1406
|
-
}
|
|
1407
|
-
normalized.source = source;
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
normalized.url = req.url;
|
|
1411
|
-
return normalized;
|
|
1412
|
-
}
|
|
1413
|
-
function formatEnvironmentMarkers(marker) {
|
|
1414
|
-
if (isEnvironmentMarkerNode(marker)) {
|
|
1415
|
-
const left = formatEnvironmentMarkers(marker.left);
|
|
1416
|
-
const right = formatEnvironmentMarkers(marker.right);
|
|
1417
|
-
return `(${left}) ${marker.operator} (${right})`;
|
|
1418
|
-
}
|
|
1419
|
-
const leaf = marker;
|
|
1420
|
-
const leftStr = formatMarkerValue(leaf.left);
|
|
1421
|
-
const rightStr = formatMarkerValue(leaf.right);
|
|
1422
|
-
return `${leftStr} ${leaf.operator} ${rightStr}`;
|
|
1423
|
-
}
|
|
1424
|
-
function isEnvironmentMarkerNode(marker) {
|
|
1425
|
-
if (typeof marker !== "object" || marker == null) {
|
|
1426
|
-
return false;
|
|
1427
|
-
}
|
|
1428
|
-
const op = marker.operator;
|
|
1429
|
-
return op === "and" || op === "or";
|
|
1430
|
-
}
|
|
1431
|
-
function formatMarkerValue(value) {
|
|
1432
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
1433
|
-
return value;
|
|
1434
|
-
}
|
|
1435
|
-
return value;
|
|
1436
|
-
}
|
|
1437
1127
|
|
|
1438
1128
|
// src/manifest/uv-config/schema.ts
|
|
1439
1129
|
var UvConfigWorkspaceSchema = uvConfigWorkspaceSchema.passthrough();
|
|
@@ -1903,7 +1593,8 @@ function computeRequiresPython(manifest, workspaceManifest, configs) {
|
|
|
1903
1593
|
constraints.push({
|
|
1904
1594
|
request: pythonVersionConfig.data,
|
|
1905
1595
|
source: pythonVersionConfig.path,
|
|
1906
|
-
prettySource: pythonVersionConfig.path
|
|
1596
|
+
prettySource: pythonVersionConfig.path,
|
|
1597
|
+
specifier: pythonVersionConfig.specifier
|
|
1907
1598
|
});
|
|
1908
1599
|
hasPythonVersionFile = true;
|
|
1909
1600
|
break;
|
|
@@ -1918,7 +1609,8 @@ function computeRequiresPython(manifest, workspaceManifest, configs) {
|
|
|
1918
1609
|
constraints.push({
|
|
1919
1610
|
request: [request],
|
|
1920
1611
|
source: manifest.path,
|
|
1921
|
-
prettySource: `"requires-python" key in ${manifest.path}
|
|
1612
|
+
prettySource: `"requires-python" key in ${manifest.path}`,
|
|
1613
|
+
specifier: manifestRequiresPython
|
|
1922
1614
|
});
|
|
1923
1615
|
}
|
|
1924
1616
|
} else {
|
|
@@ -1930,7 +1622,8 @@ function computeRequiresPython(manifest, workspaceManifest, configs) {
|
|
|
1930
1622
|
constraints.push({
|
|
1931
1623
|
request: [request],
|
|
1932
1624
|
source: workspaceManifest.path,
|
|
1933
|
-
prettySource: `"requires-python" key in ${workspaceManifest.path}
|
|
1625
|
+
prettySource: `"requires-python" key in ${workspaceManifest.path}`,
|
|
1626
|
+
specifier: workspaceRequiresPython
|
|
1934
1627
|
});
|
|
1935
1628
|
}
|
|
1936
1629
|
}
|
|
@@ -2151,7 +1844,13 @@ async function maybeLoadRequirementsTxt(root, subdir, fileName) {
|
|
|
2151
1844
|
return null;
|
|
2152
1845
|
}
|
|
2153
1846
|
try {
|
|
2154
|
-
const pyproject = convertRequirementsToPyprojectToml(
|
|
1847
|
+
const pyproject = await convertRequirementsToPyprojectToml(
|
|
1848
|
+
requirementsContent,
|
|
1849
|
+
{
|
|
1850
|
+
workingDir: path3.join(root, subdir),
|
|
1851
|
+
packageRoot: root
|
|
1852
|
+
}
|
|
1853
|
+
);
|
|
2155
1854
|
return {
|
|
2156
1855
|
path: requirementsTxtRelPath,
|
|
2157
1856
|
data: pyproject,
|
|
@@ -2205,7 +1904,8 @@ async function maybeLoadPythonRequest(root, subdir) {
|
|
|
2205
1904
|
return {
|
|
2206
1905
|
kind: ".python-version" /* PythonVersion */,
|
|
2207
1906
|
path: dotPythonVersionRelPath,
|
|
2208
|
-
data: pyreq
|
|
1907
|
+
data: pyreq,
|
|
1908
|
+
specifier: data.trim()
|
|
2209
1909
|
};
|
|
2210
1910
|
}
|
|
2211
1911
|
|
|
@@ -2249,7 +1949,9 @@ function parseUvLock(content, path4) {
|
|
|
2249
1949
|
const packages = (parsed.package ?? []).filter((pkg) => pkg.name && pkg.version).map((pkg) => ({
|
|
2250
1950
|
name: pkg.name,
|
|
2251
1951
|
version: pkg.version,
|
|
2252
|
-
source: pkg.source
|
|
1952
|
+
source: pkg.source,
|
|
1953
|
+
wheels: (pkg.wheels ?? []).map((w) => ({ url: w.url })),
|
|
1954
|
+
...pkg.dependencies ? { dependencies: pkg.dependencies } : {}
|
|
2253
1955
|
}));
|
|
2254
1956
|
return { version: parsed.version, packages };
|
|
2255
1957
|
}
|
|
@@ -2305,6 +2007,20 @@ function classifyPackages(options) {
|
|
|
2305
2007
|
return { privatePackages, publicPackages, packageVersions };
|
|
2306
2008
|
}
|
|
2307
2009
|
|
|
2010
|
+
// src/manifest/wheel-compat.ts
|
|
2011
|
+
async function isWheelCompatible(wheelFilename, pythonMajor, pythonMinor, osName, archName, osMajor, osMinor) {
|
|
2012
|
+
const mod = await importWasmModule();
|
|
2013
|
+
return mod.isWheelCompatible(
|
|
2014
|
+
wheelFilename,
|
|
2015
|
+
pythonMajor,
|
|
2016
|
+
pythonMinor,
|
|
2017
|
+
osName,
|
|
2018
|
+
archName,
|
|
2019
|
+
osMajor,
|
|
2020
|
+
osMinor
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2308
2024
|
// src/manifest/python-selector.ts
|
|
2309
2025
|
function selectPython(constraints, available) {
|
|
2310
2026
|
const warnings = [];
|
|
@@ -2617,7 +2333,9 @@ export {
|
|
|
2617
2333
|
extendDistRecord,
|
|
2618
2334
|
getStringConstant,
|
|
2619
2335
|
isPrivatePackageSource,
|
|
2336
|
+
isWheelCompatible,
|
|
2620
2337
|
normalizePackageName2 as normalizePackageName,
|
|
2338
|
+
parsePep508,
|
|
2621
2339
|
parseUvLock,
|
|
2622
2340
|
scanDistributions,
|
|
2623
2341
|
selectPython,
|