@vercel/python-analysis 0.3.2 → 0.4.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 +332 -19
- package/dist/index.d.ts +3 -2
- package/dist/index.js +328 -18
- package/dist/manifest/package.d.ts +24 -0
- package/dist/manifest/pyproject/schema.zod.d.ts +16 -0
- package/dist/manifest/requirements-txt-parser.d.ts +4 -0
- package/dist/manifest/serialize.d.ts +22 -0
- package/dist/manifest/uv-config/schema.zod.d.ts +8 -0
- package/dist/manifest/uv-config/types.d.ts +2 -0
- package/dist/util/error.d.ts +7 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,6 +52,7 @@ __export(src_exports, {
|
|
|
52
52
|
PythonBuild: () => PythonBuild,
|
|
53
53
|
PythonConfigKind: () => PythonConfigKind,
|
|
54
54
|
PythonImplementation: () => PythonImplementation,
|
|
55
|
+
PythonLockFileKind: () => PythonLockFileKind,
|
|
55
56
|
PythonManifestConvertedKind: () => PythonManifestConvertedKind,
|
|
56
57
|
PythonManifestKind: () => PythonManifestKind,
|
|
57
58
|
PythonVariant: () => PythonVariant,
|
|
@@ -62,8 +63,10 @@ __export(src_exports, {
|
|
|
62
63
|
UvConfigWorkspaceSchema: () => UvConfigWorkspaceSchema,
|
|
63
64
|
UvIndexEntrySchema: () => UvIndexEntrySchema,
|
|
64
65
|
containsAppOrHandler: () => containsAppOrHandler,
|
|
66
|
+
createMinimalManifest: () => createMinimalManifest,
|
|
65
67
|
discoverPythonPackage: () => discoverPythonPackage,
|
|
66
|
-
selectPython: () => selectPython
|
|
68
|
+
selectPython: () => selectPython,
|
|
69
|
+
stringifyManifest: () => stringifyManifest
|
|
67
70
|
});
|
|
68
71
|
module.exports = __toCommonJS(src_exports);
|
|
69
72
|
|
|
@@ -135,7 +138,14 @@ var isErrnoException = (error, code = void 0) => {
|
|
|
135
138
|
return import_node_util.default.types.isNativeError(error) && "code" in error && (code === void 0 || error.code === code);
|
|
136
139
|
};
|
|
137
140
|
var PythonAnalysisError = class extends Error {
|
|
138
|
-
constructor({
|
|
141
|
+
constructor({
|
|
142
|
+
message,
|
|
143
|
+
code,
|
|
144
|
+
path: path4,
|
|
145
|
+
link,
|
|
146
|
+
action,
|
|
147
|
+
fileContent
|
|
148
|
+
}) {
|
|
139
149
|
super(message);
|
|
140
150
|
this.hideStackTrace = true;
|
|
141
151
|
this.name = "PythonAnalysisError";
|
|
@@ -143,6 +153,7 @@ var PythonAnalysisError = class extends Error {
|
|
|
143
153
|
this.path = path4;
|
|
144
154
|
this.link = link;
|
|
145
155
|
this.action = action;
|
|
156
|
+
this.fileContent = fileContent;
|
|
146
157
|
}
|
|
147
158
|
};
|
|
148
159
|
|
|
@@ -204,7 +215,8 @@ function parseRawConfig(content, filename, filetype = void 0) {
|
|
|
204
215
|
throw new PythonAnalysisError({
|
|
205
216
|
message: `Could not parse config file "${filename}": ${error.message}`,
|
|
206
217
|
code: "PYTHON_CONFIG_PARSE_ERROR",
|
|
207
|
-
path: filename
|
|
218
|
+
path: filename,
|
|
219
|
+
fileContent: content
|
|
208
220
|
});
|
|
209
221
|
}
|
|
210
222
|
throw error;
|
|
@@ -222,7 +234,8 @@ function parseConfig(content, filename, schema, filetype = void 0) {
|
|
|
222
234
|
message: `Invalid config in "${filename}":
|
|
223
235
|
${issues}`,
|
|
224
236
|
code: "PYTHON_CONFIG_VALIDATION_ERROR",
|
|
225
|
-
path: filename
|
|
237
|
+
path: filename,
|
|
238
|
+
fileContent: content
|
|
226
239
|
});
|
|
227
240
|
}
|
|
228
241
|
return result.data;
|
|
@@ -501,6 +514,8 @@ function convertPipfileToPyprojectToml(pipfile) {
|
|
|
501
514
|
}
|
|
502
515
|
if (deps.length > 0) {
|
|
503
516
|
pyproject.project = {
|
|
517
|
+
name: "app",
|
|
518
|
+
version: "0.1.0",
|
|
504
519
|
dependencies: deps
|
|
505
520
|
};
|
|
506
521
|
}
|
|
@@ -558,6 +573,8 @@ function convertPipfileLockToPyprojectToml(pipfileLock) {
|
|
|
558
573
|
}
|
|
559
574
|
if (deps.length > 0) {
|
|
560
575
|
pyproject.project = {
|
|
576
|
+
name: "app",
|
|
577
|
+
version: "0.1.0",
|
|
561
578
|
dependencies: deps
|
|
562
579
|
};
|
|
563
580
|
}
|
|
@@ -634,7 +651,8 @@ var uvIndexEntrySchema = import_zod3.z.object({
|
|
|
634
651
|
name: import_zod3.z.string(),
|
|
635
652
|
url: import_zod3.z.string(),
|
|
636
653
|
default: import_zod3.z.boolean().optional(),
|
|
637
|
-
explicit: import_zod3.z.boolean().optional()
|
|
654
|
+
explicit: import_zod3.z.boolean().optional(),
|
|
655
|
+
format: import_zod3.z.string().optional()
|
|
638
656
|
});
|
|
639
657
|
var uvConfigSchema = import_zod3.z.object({
|
|
640
658
|
sources: import_zod3.z.record(import_zod3.z.union([dependencySourceSchema, import_zod3.z.array(dependencySourceSchema)])).optional(),
|
|
@@ -708,6 +726,7 @@ var import_node_path4 = require("path");
|
|
|
708
726
|
var import_pip_requirements_js = require("pip-requirements-js");
|
|
709
727
|
var PRIMARY_INDEX_NAME = "primary";
|
|
710
728
|
var EXTRA_INDEX_PREFIX = "extra-";
|
|
729
|
+
var FIND_LINKS_PREFIX = "find-links-";
|
|
711
730
|
function parseGitUrl(url) {
|
|
712
731
|
if (!url.startsWith("git+")) {
|
|
713
732
|
return null;
|
|
@@ -749,6 +768,8 @@ function extractPipArguments(fileContent) {
|
|
|
749
768
|
};
|
|
750
769
|
const lines = fileContent.split(/\r?\n/);
|
|
751
770
|
const cleanedLines = [];
|
|
771
|
+
const pathRequirements = [];
|
|
772
|
+
const editableRequirements = [];
|
|
752
773
|
for (let i = 0; i < lines.length; i++) {
|
|
753
774
|
const line = lines[i];
|
|
754
775
|
const trimmed = line.trim();
|
|
@@ -763,11 +784,21 @@ function extractPipArguments(fileContent) {
|
|
|
763
784
|
fullLine = fullLine.slice(0, -1) + lines[i + linesConsumed].trim();
|
|
764
785
|
}
|
|
765
786
|
const extracted = tryExtractPipArgument(fullLine, options);
|
|
766
|
-
if (extracted) {
|
|
787
|
+
if (extracted === true) {
|
|
788
|
+
i += linesConsumed;
|
|
789
|
+
} else if (typeof extracted === "object" && extracted.editable) {
|
|
790
|
+
editableRequirements.push(extracted.editable);
|
|
767
791
|
i += linesConsumed;
|
|
768
792
|
} else {
|
|
793
|
+
if (/^-[a-zA-Z]/.test(fullLine) && !fullLine.startsWith("-r") && !fullLine.startsWith("-c")) {
|
|
794
|
+
i += linesConsumed;
|
|
795
|
+
continue;
|
|
796
|
+
}
|
|
769
797
|
const strippedLine = stripInlineHashes(fullLine);
|
|
770
|
-
|
|
798
|
+
const effectiveLine = (strippedLine !== fullLine ? strippedLine : fullLine).trim();
|
|
799
|
+
if (isPathOrUrlRequirement(effectiveLine)) {
|
|
800
|
+
pathRequirements.push(effectiveLine);
|
|
801
|
+
} else if (strippedLine !== fullLine) {
|
|
771
802
|
cleanedLines.push(strippedLine);
|
|
772
803
|
} else {
|
|
773
804
|
cleanedLines.push(line);
|
|
@@ -780,7 +811,9 @@ function extractPipArguments(fileContent) {
|
|
|
780
811
|
}
|
|
781
812
|
return {
|
|
782
813
|
cleanedContent: cleanedLines.join("\n"),
|
|
783
|
-
options
|
|
814
|
+
options,
|
|
815
|
+
pathRequirements,
|
|
816
|
+
editableRequirements
|
|
784
817
|
};
|
|
785
818
|
}
|
|
786
819
|
function tryExtractPipArgument(line, options) {
|
|
@@ -819,6 +852,46 @@ function tryExtractPipArgument(line, options) {
|
|
|
819
852
|
return true;
|
|
820
853
|
}
|
|
821
854
|
}
|
|
855
|
+
if (line.startsWith("--editable")) {
|
|
856
|
+
const path4 = extractArgValue(line, "--editable");
|
|
857
|
+
if (path4) {
|
|
858
|
+
return { editable: path4 };
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
if (line.startsWith("-e ") || line.startsWith("-e ")) {
|
|
862
|
+
const path4 = line.slice(2).trim();
|
|
863
|
+
if (path4) {
|
|
864
|
+
return { editable: path4 };
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
if (line.startsWith("--find-links")) {
|
|
868
|
+
const url = extractArgValue(line, "--find-links");
|
|
869
|
+
if (url) {
|
|
870
|
+
if (!options.findLinks)
|
|
871
|
+
options.findLinks = [];
|
|
872
|
+
options.findLinks.push(url);
|
|
873
|
+
return true;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
if (line.startsWith("-f ") || line.startsWith("-f ")) {
|
|
877
|
+
const match = line.match(/^-f\s+(\S+)/);
|
|
878
|
+
if (match) {
|
|
879
|
+
if (!options.findLinks)
|
|
880
|
+
options.findLinks = [];
|
|
881
|
+
options.findLinks.push(match[1]);
|
|
882
|
+
return true;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
if (line === "--no-index" || line.startsWith("--no-index ")) {
|
|
886
|
+
options.noIndex = true;
|
|
887
|
+
return true;
|
|
888
|
+
}
|
|
889
|
+
if (line.startsWith("--no-binary") || line.startsWith("--only-binary")) {
|
|
890
|
+
return true;
|
|
891
|
+
}
|
|
892
|
+
if (line.startsWith("--")) {
|
|
893
|
+
return true;
|
|
894
|
+
}
|
|
822
895
|
return false;
|
|
823
896
|
}
|
|
824
897
|
function stripInlineHashes(line) {
|
|
@@ -834,15 +907,158 @@ function extractInlineHashes(line) {
|
|
|
834
907
|
return hashes;
|
|
835
908
|
}
|
|
836
909
|
function extractArgValue(line, option) {
|
|
910
|
+
let value = null;
|
|
837
911
|
if (line.startsWith(`${option}=`)) {
|
|
838
|
-
|
|
839
|
-
|
|
912
|
+
value = line.slice(option.length + 1).trim();
|
|
913
|
+
} else if (line.startsWith(`${option} `) || line.startsWith(`${option} `)) {
|
|
914
|
+
value = line.slice(option.length).trim();
|
|
840
915
|
}
|
|
841
|
-
if (
|
|
842
|
-
|
|
843
|
-
|
|
916
|
+
if (!value)
|
|
917
|
+
return null;
|
|
918
|
+
const commentIdx = value.indexOf(" #");
|
|
919
|
+
if (commentIdx !== -1) {
|
|
920
|
+
value = value.slice(0, commentIdx).trim();
|
|
844
921
|
}
|
|
845
|
-
return null;
|
|
922
|
+
return value || null;
|
|
923
|
+
}
|
|
924
|
+
function isPathOrUrlRequirement(line) {
|
|
925
|
+
if (line.startsWith("./") || line.startsWith("../"))
|
|
926
|
+
return true;
|
|
927
|
+
if (line.startsWith("/"))
|
|
928
|
+
return true;
|
|
929
|
+
if (line.startsWith("~/"))
|
|
930
|
+
return true;
|
|
931
|
+
if (/^(https?|ftp|file):\/\//i.test(line))
|
|
932
|
+
return true;
|
|
933
|
+
if (isBareArchiveFilename(line))
|
|
934
|
+
return true;
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
937
|
+
function isBareArchiveFilename(line) {
|
|
938
|
+
if (line.includes(" @ "))
|
|
939
|
+
return false;
|
|
940
|
+
let check = line;
|
|
941
|
+
const commentIdx = check.indexOf(" #");
|
|
942
|
+
if (commentIdx !== -1)
|
|
943
|
+
check = check.slice(0, commentIdx);
|
|
944
|
+
const markerIdx = check.indexOf(" ;");
|
|
945
|
+
if (markerIdx !== -1)
|
|
946
|
+
check = check.slice(0, markerIdx);
|
|
947
|
+
const extrasIdx = check.indexOf("[");
|
|
948
|
+
if (extrasIdx !== -1)
|
|
949
|
+
check = check.slice(0, extrasIdx);
|
|
950
|
+
check = check.trim();
|
|
951
|
+
return /\.(whl|tar\.gz|tar\.bz2|tar\.xz|zip)$/i.test(check);
|
|
952
|
+
}
|
|
953
|
+
function parseWheelFilename(filename) {
|
|
954
|
+
if (!filename.endsWith(".whl"))
|
|
955
|
+
return null;
|
|
956
|
+
const stem = filename.slice(0, -4);
|
|
957
|
+
const parts = stem.split("-");
|
|
958
|
+
if (parts.length < 5 || parts.length > 6)
|
|
959
|
+
return null;
|
|
960
|
+
const name = parts[0];
|
|
961
|
+
const version = parts[1];
|
|
962
|
+
if (!name || !version)
|
|
963
|
+
return null;
|
|
964
|
+
return {
|
|
965
|
+
name: name.replace(/_/g, "-"),
|
|
966
|
+
version
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
function parseSdistFilename(filename) {
|
|
970
|
+
let stem = filename;
|
|
971
|
+
for (const ext of [".tar.gz", ".tar.bz2", ".tar.xz", ".zip"]) {
|
|
972
|
+
if (stem.endsWith(ext)) {
|
|
973
|
+
stem = stem.slice(0, -ext.length);
|
|
974
|
+
break;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
if (stem === filename)
|
|
978
|
+
return null;
|
|
979
|
+
const parts = stem.split("-");
|
|
980
|
+
let versionIdx = -1;
|
|
981
|
+
for (let i = 1; i < parts.length; i++) {
|
|
982
|
+
if (/^\d/.test(parts[i])) {
|
|
983
|
+
versionIdx = i;
|
|
984
|
+
break;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
if (versionIdx === -1)
|
|
988
|
+
return null;
|
|
989
|
+
return {
|
|
990
|
+
name: parts.slice(0, versionIdx).join("-"),
|
|
991
|
+
version: parts.slice(versionIdx).join("-")
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
function normalizePathRequirement(rawLine) {
|
|
995
|
+
let line = rawLine;
|
|
996
|
+
const commentIdx = line.indexOf(" #");
|
|
997
|
+
if (commentIdx !== -1) {
|
|
998
|
+
line = line.slice(0, commentIdx).trim();
|
|
999
|
+
}
|
|
1000
|
+
let markers;
|
|
1001
|
+
const markerIdx = line.indexOf(" ;");
|
|
1002
|
+
if (markerIdx !== -1) {
|
|
1003
|
+
markers = line.slice(markerIdx + 2).trim();
|
|
1004
|
+
line = line.slice(0, markerIdx).trim();
|
|
1005
|
+
}
|
|
1006
|
+
let extras;
|
|
1007
|
+
const extrasMatch = line.match(/\[([^\]]+)\]$/);
|
|
1008
|
+
if (extrasMatch) {
|
|
1009
|
+
extras = extrasMatch[1].split(",").map((e) => e.trim());
|
|
1010
|
+
line = line.slice(0, extrasMatch.index).trim();
|
|
1011
|
+
}
|
|
1012
|
+
const isUrl = /^(https?|ftp|file):\/\//i.test(line);
|
|
1013
|
+
let filename;
|
|
1014
|
+
if (isUrl) {
|
|
1015
|
+
try {
|
|
1016
|
+
const url = new URL(line);
|
|
1017
|
+
filename = url.pathname.split("/").pop() || "";
|
|
1018
|
+
} catch {
|
|
1019
|
+
return null;
|
|
1020
|
+
}
|
|
1021
|
+
} else {
|
|
1022
|
+
const cleanPath = line.replace(/\/+$/, "");
|
|
1023
|
+
filename = cleanPath.split("/").pop() || "";
|
|
1024
|
+
}
|
|
1025
|
+
if (!filename)
|
|
1026
|
+
return null;
|
|
1027
|
+
let name;
|
|
1028
|
+
let version;
|
|
1029
|
+
const wheelParsed = parseWheelFilename(filename);
|
|
1030
|
+
if (wheelParsed) {
|
|
1031
|
+
name = wheelParsed.name;
|
|
1032
|
+
version = wheelParsed.version;
|
|
1033
|
+
}
|
|
1034
|
+
if (!name) {
|
|
1035
|
+
const sdistParsed = parseSdistFilename(filename);
|
|
1036
|
+
if (sdistParsed) {
|
|
1037
|
+
name = sdistParsed.name;
|
|
1038
|
+
version = sdistParsed.version;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
if (!name) {
|
|
1042
|
+
name = filename.replace(/[-_.]+/g, "-").toLowerCase();
|
|
1043
|
+
}
|
|
1044
|
+
if (!name)
|
|
1045
|
+
return null;
|
|
1046
|
+
const req = { name };
|
|
1047
|
+
if (version) {
|
|
1048
|
+
req.version = `==${version}`;
|
|
1049
|
+
}
|
|
1050
|
+
if (extras && extras.length > 0) {
|
|
1051
|
+
req.extras = extras;
|
|
1052
|
+
}
|
|
1053
|
+
if (markers) {
|
|
1054
|
+
req.markers = markers;
|
|
1055
|
+
}
|
|
1056
|
+
if (isUrl) {
|
|
1057
|
+
req.url = line;
|
|
1058
|
+
} else {
|
|
1059
|
+
req.source = { path: line };
|
|
1060
|
+
}
|
|
1061
|
+
return req;
|
|
846
1062
|
}
|
|
847
1063
|
function convertRequirementsToPyprojectToml(fileContent, readFile3) {
|
|
848
1064
|
const pyproject = {};
|
|
@@ -861,6 +1077,8 @@ function convertRequirementsToPyprojectToml(fileContent, readFile3) {
|
|
|
861
1077
|
}
|
|
862
1078
|
if (deps.length > 0) {
|
|
863
1079
|
pyproject.project = {
|
|
1080
|
+
name: "app",
|
|
1081
|
+
version: "0.1.0",
|
|
864
1082
|
dependencies: deps
|
|
865
1083
|
};
|
|
866
1084
|
}
|
|
@@ -892,6 +1110,15 @@ function buildIndexEntries(pipOptions) {
|
|
|
892
1110
|
url: pipOptions.extraIndexUrls[i]
|
|
893
1111
|
});
|
|
894
1112
|
}
|
|
1113
|
+
if (pipOptions.findLinks) {
|
|
1114
|
+
for (let i = 0; i < pipOptions.findLinks.length; i++) {
|
|
1115
|
+
indexes.push({
|
|
1116
|
+
name: `${FIND_LINKS_PREFIX}${i + 1}`,
|
|
1117
|
+
url: pipOptions.findLinks[i],
|
|
1118
|
+
format: "flat"
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
895
1122
|
return indexes;
|
|
896
1123
|
}
|
|
897
1124
|
function parseRequirementsFile(fileContent, readFile3) {
|
|
@@ -899,7 +1126,7 @@ function parseRequirementsFile(fileContent, readFile3) {
|
|
|
899
1126
|
return parseRequirementsFileInternal(fileContent, readFile3, visited);
|
|
900
1127
|
}
|
|
901
1128
|
function parseRequirementsFileInternal(fileContent, readFile3, visited) {
|
|
902
|
-
const { cleanedContent, options } = extractPipArguments(fileContent);
|
|
1129
|
+
const { cleanedContent, options, pathRequirements, editableRequirements } = extractPipArguments(fileContent);
|
|
903
1130
|
const hashMap = buildHashMap(fileContent);
|
|
904
1131
|
const requirements = (0, import_pip_requirements_js.parsePipRequirementsFile)(cleanedContent);
|
|
905
1132
|
const normalized = [];
|
|
@@ -907,7 +1134,9 @@ function parseRequirementsFileInternal(fileContent, readFile3, visited) {
|
|
|
907
1134
|
requirementFiles: [...options.requirementFiles],
|
|
908
1135
|
constraintFiles: [...options.constraintFiles],
|
|
909
1136
|
indexUrl: options.indexUrl,
|
|
910
|
-
extraIndexUrls: [...options.extraIndexUrls]
|
|
1137
|
+
extraIndexUrls: [...options.extraIndexUrls],
|
|
1138
|
+
findLinks: options.findLinks ? [...options.findLinks] : void 0,
|
|
1139
|
+
noIndex: options.noIndex
|
|
911
1140
|
};
|
|
912
1141
|
for (const req of requirements) {
|
|
913
1142
|
if (req.type === "RequirementsFile") {
|
|
@@ -927,6 +1156,23 @@ function parseRequirementsFileInternal(fileContent, readFile3, visited) {
|
|
|
927
1156
|
normalized.push(norm);
|
|
928
1157
|
}
|
|
929
1158
|
}
|
|
1159
|
+
for (const rawPath of pathRequirements) {
|
|
1160
|
+
const norm = normalizePathRequirement(rawPath);
|
|
1161
|
+
if (norm != null) {
|
|
1162
|
+
normalized.push(norm);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
for (const rawPath of editableRequirements) {
|
|
1166
|
+
const norm = normalizePathRequirement(rawPath);
|
|
1167
|
+
if (norm != null) {
|
|
1168
|
+
if (norm.source) {
|
|
1169
|
+
norm.source.editable = true;
|
|
1170
|
+
} else {
|
|
1171
|
+
norm.source = { path: rawPath, editable: true };
|
|
1172
|
+
}
|
|
1173
|
+
normalized.push(norm);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
930
1176
|
if (readFile3) {
|
|
931
1177
|
for (const refPath of mergedOptions.requirementFiles) {
|
|
932
1178
|
const refPathKey = (0, import_node_path4.normalize)(refPath);
|
|
@@ -963,6 +1209,18 @@ function parseRequirementsFileInternal(fileContent, readFile3, visited) {
|
|
|
963
1209
|
mergedOptions.constraintFiles.push(constraintPath);
|
|
964
1210
|
}
|
|
965
1211
|
}
|
|
1212
|
+
if (refParsed.pipOptions.findLinks) {
|
|
1213
|
+
if (!mergedOptions.findLinks)
|
|
1214
|
+
mergedOptions.findLinks = [];
|
|
1215
|
+
for (const fl of refParsed.pipOptions.findLinks) {
|
|
1216
|
+
if (!mergedOptions.findLinks.includes(fl)) {
|
|
1217
|
+
mergedOptions.findLinks.push(fl);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
if (refParsed.pipOptions.noIndex) {
|
|
1222
|
+
mergedOptions.noIndex = true;
|
|
1223
|
+
}
|
|
966
1224
|
}
|
|
967
1225
|
}
|
|
968
1226
|
}
|
|
@@ -1451,6 +1709,11 @@ var PythonManifestKind = /* @__PURE__ */ ((PythonManifestKind2) => {
|
|
|
1451
1709
|
PythonManifestKind2["PyProjectToml"] = "pyproject.toml";
|
|
1452
1710
|
return PythonManifestKind2;
|
|
1453
1711
|
})(PythonManifestKind || {});
|
|
1712
|
+
var PythonLockFileKind = /* @__PURE__ */ ((PythonLockFileKind2) => {
|
|
1713
|
+
PythonLockFileKind2["UvLock"] = "uv.lock";
|
|
1714
|
+
PythonLockFileKind2["PylockToml"] = "pylock.toml";
|
|
1715
|
+
return PythonLockFileKind2;
|
|
1716
|
+
})(PythonLockFileKind || {});
|
|
1454
1717
|
var PythonManifestConvertedKind = /* @__PURE__ */ ((PythonManifestConvertedKind2) => {
|
|
1455
1718
|
PythonManifestConvertedKind2["Pipfile"] = "Pipfile";
|
|
1456
1719
|
PythonManifestConvertedKind2["PipfileLock"] = "Pipfile.lock";
|
|
@@ -1492,6 +1755,7 @@ async function discoverPythonPackage({
|
|
|
1492
1755
|
}
|
|
1493
1756
|
let entrypointManifest;
|
|
1494
1757
|
let workspaceManifest;
|
|
1758
|
+
let workspaceLockFile;
|
|
1495
1759
|
if (manifests.length === 0) {
|
|
1496
1760
|
return {
|
|
1497
1761
|
configs
|
|
@@ -1503,6 +1767,7 @@ async function discoverPythonPackage({
|
|
|
1503
1767
|
manifests
|
|
1504
1768
|
);
|
|
1505
1769
|
workspaceManifest = entrypointWorkspaceManifest;
|
|
1770
|
+
workspaceLockFile = entrypointWorkspaceManifest.lockFile;
|
|
1506
1771
|
configs = configs.filter(
|
|
1507
1772
|
(config) => Object.values(config).some(
|
|
1508
1773
|
(cfg) => cfg !== void 0 && isSubpath(
|
|
@@ -1520,6 +1785,7 @@ async function discoverPythonPackage({
|
|
|
1520
1785
|
return {
|
|
1521
1786
|
manifest: entrypointManifest,
|
|
1522
1787
|
workspaceManifest,
|
|
1788
|
+
workspaceLockFile,
|
|
1523
1789
|
configs,
|
|
1524
1790
|
requiresPython
|
|
1525
1791
|
};
|
|
@@ -1634,6 +1900,21 @@ async function loadPythonManifest(root, prefix) {
|
|
|
1634
1900
|
}
|
|
1635
1901
|
return manifest;
|
|
1636
1902
|
}
|
|
1903
|
+
async function maybeLoadLockFile(root, subdir) {
|
|
1904
|
+
const uvLockRelPath = import_node_path5.default.join(subdir, "uv.lock");
|
|
1905
|
+
const uvLockPath = import_node_path5.default.join(root, uvLockRelPath);
|
|
1906
|
+
const uvLockContent = await readFileTextIfExists(uvLockPath);
|
|
1907
|
+
if (uvLockContent != null) {
|
|
1908
|
+
return { path: uvLockRelPath, kind: "uv.lock" /* UvLock */ };
|
|
1909
|
+
}
|
|
1910
|
+
const pylockRelPath = import_node_path5.default.join(subdir, "pylock.toml");
|
|
1911
|
+
const pylockPath = import_node_path5.default.join(root, pylockRelPath);
|
|
1912
|
+
const pylockContent = await readFileTextIfExists(pylockPath);
|
|
1913
|
+
if (pylockContent != null) {
|
|
1914
|
+
return { path: pylockRelPath, kind: "pylock.toml" /* PylockToml */ };
|
|
1915
|
+
}
|
|
1916
|
+
return void 0;
|
|
1917
|
+
}
|
|
1637
1918
|
async function maybeLoadPyProjectToml(root, subdir) {
|
|
1638
1919
|
const pyprojectTomlRelPath = import_node_path5.default.join(subdir, "pyproject.toml");
|
|
1639
1920
|
const pyprojectTomlPath = import_node_path5.default.join(root, pyprojectTomlRelPath);
|
|
@@ -1680,9 +1961,11 @@ async function maybeLoadPyProjectToml(root, subdir) {
|
|
|
1680
1961
|
pyproject.tool.uv = uvToml;
|
|
1681
1962
|
}
|
|
1682
1963
|
}
|
|
1964
|
+
const lockFile = await maybeLoadLockFile(root, subdir);
|
|
1683
1965
|
return {
|
|
1684
1966
|
path: pyprojectTomlRelPath,
|
|
1685
|
-
data: pyproject
|
|
1967
|
+
data: pyproject,
|
|
1968
|
+
lockFile
|
|
1686
1969
|
};
|
|
1687
1970
|
}
|
|
1688
1971
|
async function maybeLoadPipfile(root, subdir) {
|
|
@@ -1769,12 +2052,16 @@ async function maybeLoadRequirementsTxt(root, subdir, fileName) {
|
|
|
1769
2052
|
} catch (error) {
|
|
1770
2053
|
if (error instanceof PythonAnalysisError) {
|
|
1771
2054
|
error.path = requirementsTxtRelPath;
|
|
2055
|
+
if (!error.fileContent) {
|
|
2056
|
+
error.fileContent = requirementsContent;
|
|
2057
|
+
}
|
|
1772
2058
|
throw error;
|
|
1773
2059
|
}
|
|
1774
2060
|
throw new PythonAnalysisError({
|
|
1775
2061
|
message: `could not parse ${fileName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1776
2062
|
code: "PYTHON_REQUIREMENTS_PARSE_ERROR",
|
|
1777
|
-
path: requirementsTxtRelPath
|
|
2063
|
+
path: requirementsTxtRelPath,
|
|
2064
|
+
fileContent: requirementsContent
|
|
1778
2065
|
});
|
|
1779
2066
|
}
|
|
1780
2067
|
}
|
|
@@ -1811,6 +2098,29 @@ async function maybeLoadPythonRequest(root, subdir) {
|
|
|
1811
2098
|
};
|
|
1812
2099
|
}
|
|
1813
2100
|
|
|
2101
|
+
// src/manifest/serialize.ts
|
|
2102
|
+
var import_smol_toml2 = __toESM(require("smol-toml"), 1);
|
|
2103
|
+
function stringifyManifest(data) {
|
|
2104
|
+
return import_smol_toml2.default.stringify(data);
|
|
2105
|
+
}
|
|
2106
|
+
function createMinimalManifest(options = {}) {
|
|
2107
|
+
const {
|
|
2108
|
+
name = "app",
|
|
2109
|
+
version = "0.1.0",
|
|
2110
|
+
requiresPython,
|
|
2111
|
+
dependencies = []
|
|
2112
|
+
} = options;
|
|
2113
|
+
return {
|
|
2114
|
+
project: {
|
|
2115
|
+
name,
|
|
2116
|
+
version,
|
|
2117
|
+
...requiresPython && { "requires-python": requiresPython },
|
|
2118
|
+
dependencies,
|
|
2119
|
+
classifiers: ["Private :: Do Not Upload"]
|
|
2120
|
+
}
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
|
|
1814
2124
|
// src/manifest/python-selector.ts
|
|
1815
2125
|
function selectPython(constraints, available) {
|
|
1816
2126
|
const warnings = [];
|
|
@@ -1984,6 +2294,7 @@ var HashDigestSchema = hashDigestSchema;
|
|
|
1984
2294
|
PythonBuild,
|
|
1985
2295
|
PythonConfigKind,
|
|
1986
2296
|
PythonImplementation,
|
|
2297
|
+
PythonLockFileKind,
|
|
1987
2298
|
PythonManifestConvertedKind,
|
|
1988
2299
|
PythonManifestKind,
|
|
1989
2300
|
PythonVariant,
|
|
@@ -1994,6 +2305,8 @@ var HashDigestSchema = hashDigestSchema;
|
|
|
1994
2305
|
UvConfigWorkspaceSchema,
|
|
1995
2306
|
UvIndexEntrySchema,
|
|
1996
2307
|
containsAppOrHandler,
|
|
2308
|
+
createMinimalManifest,
|
|
1997
2309
|
discoverPythonPackage,
|
|
1998
|
-
selectPython
|
|
2310
|
+
selectPython,
|
|
2311
|
+
stringifyManifest
|
|
1999
2312
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* @module @vercel/python-analysis
|
|
8
8
|
*/
|
|
9
9
|
export { containsAppOrHandler } from './semantic/entrypoints';
|
|
10
|
-
export type { PythonConfig, PythonConfigs, PythonManifest, PythonManifestOrigin, PythonPackage, PythonVersionConfig, } from './manifest/package';
|
|
11
|
-
export { discoverPythonPackage, PythonConfigKind, PythonManifestConvertedKind, PythonManifestKind, } from './manifest/package';
|
|
10
|
+
export type { PythonConfig, PythonConfigs, PythonLockFile, PythonManifest, PythonManifestOrigin, PythonPackage, PythonVersionConfig, } from './manifest/package';
|
|
11
|
+
export { discoverPythonPackage, PythonConfigKind, PythonLockFileKind, PythonManifestConvertedKind, PythonManifestKind, } from './manifest/package';
|
|
12
|
+
export { createMinimalManifest, stringifyManifest, type CreateMinimalManifestOptions, } from './manifest/serialize';
|
|
12
13
|
export type { PythonSelectionResult } from './manifest/python-selector';
|
|
13
14
|
export { selectPython } from './manifest/python-selector';
|
|
14
15
|
export { PythonAnalysisError } from './util/error';
|