@vercel/python-analysis 0.1.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/LICENSE +202 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +107 -0
- package/dist/manifest/package.d.ts +166 -0
- package/dist/manifest/package.js +422 -0
- package/dist/manifest/pep440.d.ts +6 -0
- package/dist/manifest/pep440.js +63 -0
- package/dist/manifest/pep508.d.ts +64 -0
- package/dist/manifest/pep508.js +70 -0
- package/dist/manifest/pipfile/schema.d.ts +40 -0
- package/dist/manifest/pipfile/schema.js +44 -0
- package/dist/manifest/pipfile/schema.zod.d.ts +606 -0
- package/dist/manifest/pipfile/schema.zod.js +97 -0
- package/dist/manifest/pipfile/types.d.ts +77 -0
- package/dist/manifest/pipfile/types.js +16 -0
- package/dist/manifest/pipfile-parser.d.ts +35 -0
- package/dist/manifest/pipfile-parser.js +262 -0
- package/dist/manifest/pyproject/schema.d.ts +50 -0
- package/dist/manifest/pyproject/schema.js +56 -0
- package/dist/manifest/pyproject/schema.zod.d.ts +767 -0
- package/dist/manifest/pyproject/schema.zod.js +94 -0
- package/dist/manifest/pyproject/types.d.ts +93 -0
- package/dist/manifest/pyproject/types.js +16 -0
- package/dist/manifest/python-selector.d.ts +123 -0
- package/dist/manifest/python-selector.js +185 -0
- package/dist/manifest/python-specifiers.d.ts +76 -0
- package/dist/manifest/python-specifiers.js +156 -0
- package/dist/manifest/requirement/schema.d.ts +28 -0
- package/dist/manifest/requirement/schema.js +35 -0
- package/dist/manifest/requirement/schema.zod.d.ts +76 -0
- package/dist/manifest/requirement/schema.zod.js +49 -0
- package/dist/manifest/requirement/types.d.ts +50 -0
- package/dist/manifest/requirement/types.js +16 -0
- package/dist/manifest/requirements-txt-parser.d.ts +55 -0
- package/dist/manifest/requirements-txt-parser.js +400 -0
- package/dist/manifest/uv-config/schema.d.ts +22 -0
- package/dist/manifest/uv-config/schema.js +35 -0
- package/dist/manifest/uv-config/schema.zod.d.ts +140 -0
- package/dist/manifest/uv-config/schema.zod.js +48 -0
- package/dist/manifest/uv-config/types.d.ts +48 -0
- package/dist/manifest/uv-config/types.js +16 -0
- package/dist/manifest/uv-python-version-parser.d.ts +28 -0
- package/dist/manifest/uv-python-version-parser.js +268 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.js +16 -0
- package/dist/util/config.d.ts +20 -0
- package/dist/util/config.js +100 -0
- package/dist/util/error.d.ts +39 -0
- package/dist/util/error.js +54 -0
- package/dist/util/fs.d.ts +25 -0
- package/dist/util/fs.js +75 -0
- package/dist/util/type.d.ts +7 -0
- package/dist/util/type.js +30 -0
- package/package.json +43 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var package_exports = {};
|
|
30
|
+
__export(package_exports, {
|
|
31
|
+
PythonConfigKind: () => PythonConfigKind,
|
|
32
|
+
PythonManifestConvertedKind: () => PythonManifestConvertedKind,
|
|
33
|
+
PythonManifestKind: () => PythonManifestKind,
|
|
34
|
+
discoverPythonPackage: () => discoverPythonPackage
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(package_exports);
|
|
37
|
+
var import_node_path = __toESM(require("node:path"));
|
|
38
|
+
var import_minimatch = require("minimatch");
|
|
39
|
+
var import_config = require("../util/config");
|
|
40
|
+
var import_error = require("../util/error");
|
|
41
|
+
var import_fs = require("../util/fs");
|
|
42
|
+
var import_pep440 = require("./pep440");
|
|
43
|
+
var import_schema = require("./pipfile/schema");
|
|
44
|
+
var import_pipfile_parser = require("./pipfile-parser");
|
|
45
|
+
var import_schema2 = require("./pyproject/schema");
|
|
46
|
+
var import_requirements_txt_parser = require("./requirements-txt-parser");
|
|
47
|
+
var import_schema3 = require("./uv-config/schema");
|
|
48
|
+
var import_uv_python_version_parser = require("./uv-python-version-parser");
|
|
49
|
+
var PythonConfigKind = /* @__PURE__ */ ((PythonConfigKind2) => {
|
|
50
|
+
PythonConfigKind2["PythonVersion"] = ".python-version";
|
|
51
|
+
return PythonConfigKind2;
|
|
52
|
+
})(PythonConfigKind || {});
|
|
53
|
+
var PythonManifestKind = /* @__PURE__ */ ((PythonManifestKind2) => {
|
|
54
|
+
PythonManifestKind2["PyProjectToml"] = "pyproject.toml";
|
|
55
|
+
return PythonManifestKind2;
|
|
56
|
+
})(PythonManifestKind || {});
|
|
57
|
+
var PythonManifestConvertedKind = /* @__PURE__ */ ((PythonManifestConvertedKind2) => {
|
|
58
|
+
PythonManifestConvertedKind2["Pipfile"] = "Pipfile";
|
|
59
|
+
PythonManifestConvertedKind2["PipfileLock"] = "Pipfile.lock";
|
|
60
|
+
PythonManifestConvertedKind2["RequirementsIn"] = "requirements.in";
|
|
61
|
+
PythonManifestConvertedKind2["RequirementsTxt"] = "requirements.txt";
|
|
62
|
+
return PythonManifestConvertedKind2;
|
|
63
|
+
})(PythonManifestConvertedKind || {});
|
|
64
|
+
async function discoverPythonPackage({
|
|
65
|
+
entrypointDir,
|
|
66
|
+
rootDir
|
|
67
|
+
}) {
|
|
68
|
+
const entrypointPath = (0, import_fs.normalizePath)(entrypointDir);
|
|
69
|
+
const rootPath = (0, import_fs.normalizePath)(rootDir);
|
|
70
|
+
let prefix = import_node_path.default.relative(rootPath, entrypointPath);
|
|
71
|
+
if (prefix.startsWith("..")) {
|
|
72
|
+
throw new import_error.PythonAnalysisError({
|
|
73
|
+
message: "Entrypoint directory outside of repository root",
|
|
74
|
+
code: "PYTHON_INVALID_ENTRYPOINT_PATH"
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const manifests = [];
|
|
78
|
+
let configs = [];
|
|
79
|
+
for (; ; ) {
|
|
80
|
+
const prefixConfigs = await loadPythonConfigs(rootPath, prefix);
|
|
81
|
+
if (Object.keys(prefixConfigs).length !== 0) {
|
|
82
|
+
configs.push(prefixConfigs);
|
|
83
|
+
}
|
|
84
|
+
const prefixManifest = await loadPythonManifest(rootPath, prefix);
|
|
85
|
+
if (prefixManifest != null) {
|
|
86
|
+
manifests.push(prefixManifest);
|
|
87
|
+
if (prefixManifest.isRoot) {
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (prefix === "" || prefix === ".") {
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
prefix = import_node_path.default.dirname(prefix);
|
|
95
|
+
}
|
|
96
|
+
let entrypointManifest;
|
|
97
|
+
let workspaceManifest;
|
|
98
|
+
if (manifests.length === 0) {
|
|
99
|
+
return {
|
|
100
|
+
configs
|
|
101
|
+
};
|
|
102
|
+
} else {
|
|
103
|
+
entrypointManifest = manifests[0];
|
|
104
|
+
const entrypointWorkspaceManifest = findWorkspaceManifestFor(
|
|
105
|
+
entrypointManifest,
|
|
106
|
+
manifests
|
|
107
|
+
);
|
|
108
|
+
workspaceManifest = entrypointWorkspaceManifest;
|
|
109
|
+
configs = configs.filter(
|
|
110
|
+
(config) => Object.values(config).some(
|
|
111
|
+
(cfg) => cfg !== void 0 && (0, import_fs.isSubpath)(
|
|
112
|
+
import_node_path.default.dirname(cfg.path),
|
|
113
|
+
import_node_path.default.dirname(entrypointWorkspaceManifest.path)
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
const requiresPython = computeRequiresPython(
|
|
119
|
+
entrypointManifest,
|
|
120
|
+
workspaceManifest,
|
|
121
|
+
configs
|
|
122
|
+
);
|
|
123
|
+
return {
|
|
124
|
+
manifest: entrypointManifest,
|
|
125
|
+
workspaceManifest,
|
|
126
|
+
configs,
|
|
127
|
+
requiresPython
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function computeRequiresPython(manifest, workspaceManifest, configs) {
|
|
131
|
+
const constraints = [];
|
|
132
|
+
for (const configSet of configs) {
|
|
133
|
+
const pythonVersionConfig = configSet[".python-version" /* PythonVersion */];
|
|
134
|
+
if (pythonVersionConfig !== void 0) {
|
|
135
|
+
constraints.push({
|
|
136
|
+
request: pythonVersionConfig.data,
|
|
137
|
+
source: `${pythonVersionConfig.path}`
|
|
138
|
+
});
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const manifestRequiresPython = manifest?.data.project?.["requires-python"];
|
|
143
|
+
if (manifestRequiresPython) {
|
|
144
|
+
const parsed = (0, import_pep440.parsePep440Constraint)(manifestRequiresPython);
|
|
145
|
+
if (parsed?.length) {
|
|
146
|
+
const request = (0, import_uv_python_version_parser.pythonRequestFromConstraint)(parsed);
|
|
147
|
+
constraints.push({
|
|
148
|
+
request: [request],
|
|
149
|
+
source: `"requires-python" key in ${manifest.path}`
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
const workspaceRequiresPython = workspaceManifest?.data.project?.["requires-python"];
|
|
154
|
+
if (workspaceRequiresPython) {
|
|
155
|
+
const parsed = (0, import_pep440.parsePep440Constraint)(workspaceRequiresPython);
|
|
156
|
+
if (parsed?.length) {
|
|
157
|
+
const request = (0, import_uv_python_version_parser.pythonRequestFromConstraint)(parsed);
|
|
158
|
+
constraints.push({
|
|
159
|
+
request: [request],
|
|
160
|
+
source: `"requires-python" key in ${workspaceManifest.path}`
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return constraints;
|
|
166
|
+
}
|
|
167
|
+
function findWorkspaceManifestFor(manifest, manifestStack) {
|
|
168
|
+
if (manifest.isRoot) {
|
|
169
|
+
return manifest;
|
|
170
|
+
}
|
|
171
|
+
for (const parentManifest of manifestStack) {
|
|
172
|
+
if (parentManifest.path === manifest.path) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const workspace = parentManifest.data.tool?.uv?.workspace;
|
|
176
|
+
if (workspace !== void 0) {
|
|
177
|
+
let members = workspace.members ?? [];
|
|
178
|
+
if (!Array.isArray(members)) {
|
|
179
|
+
members = [];
|
|
180
|
+
}
|
|
181
|
+
let exclude = workspace.exclude ?? [];
|
|
182
|
+
if (!Array.isArray(exclude)) {
|
|
183
|
+
exclude = [];
|
|
184
|
+
}
|
|
185
|
+
const entrypointRelPath = import_node_path.default.relative(
|
|
186
|
+
import_node_path.default.dirname(parentManifest.path),
|
|
187
|
+
import_node_path.default.dirname(manifest.path)
|
|
188
|
+
);
|
|
189
|
+
if (members.length > 0 && members.some(
|
|
190
|
+
(pat) => (0, import_minimatch.match)([entrypointRelPath], pat).length > 0
|
|
191
|
+
) && !exclude.some(
|
|
192
|
+
(pat) => (0, import_minimatch.match)([entrypointRelPath], pat).length > 0
|
|
193
|
+
)) {
|
|
194
|
+
return parentManifest;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return manifest;
|
|
199
|
+
}
|
|
200
|
+
async function loadPythonManifest(root, prefix) {
|
|
201
|
+
let manifest = null;
|
|
202
|
+
const pyproject = await maybeLoadPyProjectToml(root, prefix);
|
|
203
|
+
if (pyproject != null) {
|
|
204
|
+
manifest = pyproject;
|
|
205
|
+
manifest.isRoot = pyproject.data.tool?.uv?.workspace !== void 0;
|
|
206
|
+
} else {
|
|
207
|
+
const pipfileLockPyProject = await maybeLoadPipfileLock(root, prefix);
|
|
208
|
+
if (pipfileLockPyProject != null) {
|
|
209
|
+
manifest = pipfileLockPyProject;
|
|
210
|
+
manifest.isRoot = true;
|
|
211
|
+
} else {
|
|
212
|
+
const pipfilePyProject = await maybeLoadPipfile(root, prefix);
|
|
213
|
+
if (pipfilePyProject != null) {
|
|
214
|
+
manifest = pipfilePyProject;
|
|
215
|
+
manifest.isRoot = true;
|
|
216
|
+
} else {
|
|
217
|
+
for (const fileName of [
|
|
218
|
+
"requirements.frozen.txt",
|
|
219
|
+
"requirements-frozen.txt",
|
|
220
|
+
"requirements.txt",
|
|
221
|
+
"requirements.in",
|
|
222
|
+
import_node_path.default.join("requirements", "prod.txt")
|
|
223
|
+
]) {
|
|
224
|
+
const requirementsTxtManifest = await maybeLoadRequirementsTxt(
|
|
225
|
+
root,
|
|
226
|
+
prefix,
|
|
227
|
+
fileName
|
|
228
|
+
);
|
|
229
|
+
if (requirementsTxtManifest != null) {
|
|
230
|
+
manifest = requirementsTxtManifest;
|
|
231
|
+
manifest.isRoot = true;
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return manifest;
|
|
239
|
+
}
|
|
240
|
+
async function maybeLoadPyProjectToml(root, subdir) {
|
|
241
|
+
const pyprojectTomlRelPath = import_node_path.default.join(subdir, "pyproject.toml");
|
|
242
|
+
const pyprojectTomlPath = import_node_path.default.join(root, pyprojectTomlRelPath);
|
|
243
|
+
let pyproject;
|
|
244
|
+
try {
|
|
245
|
+
pyproject = await (0, import_config.readConfigIfExists)(
|
|
246
|
+
pyprojectTomlPath,
|
|
247
|
+
import_schema2.PyProjectTomlSchema
|
|
248
|
+
);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if (error instanceof import_error.PythonAnalysisError) {
|
|
251
|
+
error.path = pyprojectTomlRelPath;
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
throw new import_error.PythonAnalysisError({
|
|
255
|
+
message: `could not parse pyproject.toml: ${error instanceof Error ? error.message : String(error)}`,
|
|
256
|
+
code: "PYTHON_PYPROJECT_PARSE_ERROR",
|
|
257
|
+
path: pyprojectTomlRelPath
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
if (pyproject == null) {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
const uvTomlRelPath = import_node_path.default.join(subdir, "uv.toml");
|
|
264
|
+
const uvTomlPath = import_node_path.default.join(root, uvTomlRelPath);
|
|
265
|
+
let uvToml;
|
|
266
|
+
try {
|
|
267
|
+
uvToml = await (0, import_config.readConfigIfExists)(uvTomlPath, import_schema3.UvConfigSchema);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
if (error instanceof import_error.PythonAnalysisError) {
|
|
270
|
+
error.path = uvTomlRelPath;
|
|
271
|
+
throw error;
|
|
272
|
+
}
|
|
273
|
+
throw new import_error.PythonAnalysisError({
|
|
274
|
+
message: `could not parse uv.toml: ${error instanceof Error ? error.message : String(error)}`,
|
|
275
|
+
code: "PYTHON_UV_CONFIG_PARSE_ERROR",
|
|
276
|
+
path: uvTomlRelPath
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
if (uvToml != null) {
|
|
280
|
+
if (pyproject.tool == null) {
|
|
281
|
+
pyproject.tool = { uv: uvToml };
|
|
282
|
+
} else {
|
|
283
|
+
pyproject.tool.uv = uvToml;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
path: pyprojectTomlRelPath,
|
|
288
|
+
data: pyproject
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
async function maybeLoadPipfile(root, subdir) {
|
|
292
|
+
const pipfileRelPath = import_node_path.default.join(subdir, "Pipfile");
|
|
293
|
+
const pipfilePath = import_node_path.default.join(root, pipfileRelPath);
|
|
294
|
+
let pipfile;
|
|
295
|
+
try {
|
|
296
|
+
pipfile = await (0, import_config.readConfigIfExists)(pipfilePath, import_schema.PipfileLikeSchema, ".toml");
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (error instanceof import_error.PythonAnalysisError) {
|
|
299
|
+
error.path = pipfileRelPath;
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
throw new import_error.PythonAnalysisError({
|
|
303
|
+
message: `could not parse Pipfile: ${error instanceof Error ? error.message : String(error)}`,
|
|
304
|
+
code: "PYTHON_PIPFILE_PARSE_ERROR",
|
|
305
|
+
path: pipfileRelPath
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
if (pipfile == null) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
const pyproject = (0, import_pipfile_parser.convertPipfileToPyprojectToml)(pipfile);
|
|
312
|
+
return {
|
|
313
|
+
path: pipfileRelPath,
|
|
314
|
+
data: pyproject,
|
|
315
|
+
origin: {
|
|
316
|
+
kind: "Pipfile" /* Pipfile */,
|
|
317
|
+
path: pipfileRelPath
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
async function maybeLoadPipfileLock(root, subdir) {
|
|
322
|
+
const pipfileLockRelPath = import_node_path.default.join(subdir, "Pipfile.lock");
|
|
323
|
+
const pipfileLockPath = import_node_path.default.join(root, pipfileLockRelPath);
|
|
324
|
+
let pipfileLock;
|
|
325
|
+
try {
|
|
326
|
+
pipfileLock = await (0, import_config.readConfigIfExists)(
|
|
327
|
+
pipfileLockPath,
|
|
328
|
+
import_schema.PipfileLockLikeSchema,
|
|
329
|
+
".json"
|
|
330
|
+
);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (error instanceof import_error.PythonAnalysisError) {
|
|
333
|
+
error.path = pipfileLockRelPath;
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
throw new import_error.PythonAnalysisError({
|
|
337
|
+
message: `could not parse Pipfile.lock: ${error instanceof Error ? error.message : String(error)}`,
|
|
338
|
+
code: "PYTHON_PIPFILE_LOCK_PARSE_ERROR",
|
|
339
|
+
path: pipfileLockRelPath
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
if (pipfileLock == null) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
const pyproject = (0, import_pipfile_parser.convertPipfileLockToPyprojectToml)(pipfileLock);
|
|
346
|
+
return {
|
|
347
|
+
path: pipfileLockRelPath,
|
|
348
|
+
data: pyproject,
|
|
349
|
+
origin: {
|
|
350
|
+
kind: "Pipfile.lock" /* PipfileLock */,
|
|
351
|
+
path: pipfileLockRelPath
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
async function maybeLoadRequirementsTxt(root, subdir, fileName) {
|
|
356
|
+
const requirementsTxtRelPath = import_node_path.default.join(subdir, fileName);
|
|
357
|
+
const requirementsTxtPath = import_node_path.default.join(root, requirementsTxtRelPath);
|
|
358
|
+
const requirementsContent = await (0, import_fs.readFileTextIfExists)(requirementsTxtPath);
|
|
359
|
+
if (requirementsContent == null) {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
try {
|
|
363
|
+
const pyproject = (0, import_requirements_txt_parser.convertRequirementsToPyprojectToml)(requirementsContent);
|
|
364
|
+
return {
|
|
365
|
+
path: requirementsTxtRelPath,
|
|
366
|
+
data: pyproject,
|
|
367
|
+
origin: {
|
|
368
|
+
kind: "requirements.txt" /* RequirementsTxt */,
|
|
369
|
+
path: requirementsTxtRelPath
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
} catch (error) {
|
|
373
|
+
if (error instanceof import_error.PythonAnalysisError) {
|
|
374
|
+
error.path = requirementsTxtRelPath;
|
|
375
|
+
throw error;
|
|
376
|
+
}
|
|
377
|
+
throw new import_error.PythonAnalysisError({
|
|
378
|
+
message: `could not parse ${fileName}: ${error instanceof Error ? error.message : String(error)}`,
|
|
379
|
+
code: "PYTHON_REQUIREMENTS_PARSE_ERROR",
|
|
380
|
+
path: requirementsTxtRelPath
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
async function loadPythonConfigs(root, prefix) {
|
|
385
|
+
const configs = {};
|
|
386
|
+
const pythonRequest = await maybeLoadPythonRequest(root, prefix);
|
|
387
|
+
if (pythonRequest != null) {
|
|
388
|
+
configs[".python-version" /* PythonVersion */] = pythonRequest;
|
|
389
|
+
}
|
|
390
|
+
return configs;
|
|
391
|
+
}
|
|
392
|
+
async function maybeLoadPythonRequest(root, subdir) {
|
|
393
|
+
const dotPythonVersionRelPath = import_node_path.default.join(subdir, ".python-version");
|
|
394
|
+
const dotPythonVersionPath = import_node_path.default.join(
|
|
395
|
+
root,
|
|
396
|
+
dotPythonVersionRelPath
|
|
397
|
+
);
|
|
398
|
+
const data = await (0, import_fs.readFileTextIfExists)(dotPythonVersionPath);
|
|
399
|
+
if (data == null) {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
const pyreq = (0, import_uv_python_version_parser.parsePythonVersionFile)(data);
|
|
403
|
+
if (pyreq == null) {
|
|
404
|
+
throw new import_error.PythonAnalysisError({
|
|
405
|
+
message: `could not parse .python-version file: no valid Python version requests found`,
|
|
406
|
+
code: "PYTHON_VERSION_FILE_PARSE_ERROR",
|
|
407
|
+
path: dotPythonVersionRelPath
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
kind: ".python-version" /* PythonVersion */,
|
|
412
|
+
path: dotPythonVersionRelPath,
|
|
413
|
+
data: pyreq
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
417
|
+
0 && (module.exports = {
|
|
418
|
+
PythonConfigKind,
|
|
419
|
+
PythonManifestConvertedKind,
|
|
420
|
+
PythonManifestKind,
|
|
421
|
+
discoverPythonPackage
|
|
422
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Pep440Version, Pep440Constraint } from '@renovatebot/pep440';
|
|
2
|
+
export type { Pep440Version, Pep440Constraint } from '@renovatebot/pep440';
|
|
3
|
+
export { parse as parsePep440Version } from '@renovatebot/pep440';
|
|
4
|
+
export { parse as parsePep440Constraint, satisfies as pep440Satisfies, } from '@renovatebot/pep440/lib/specifier';
|
|
5
|
+
export declare function pep440ConstraintFromVersion(v: Pep440Version): Pep440Constraint[];
|
|
6
|
+
export declare function unparsePep440Version(v: Pep440Version): string;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var pep440_exports = {};
|
|
30
|
+
__export(pep440_exports, {
|
|
31
|
+
parsePep440Constraint: () => import_specifier.parse,
|
|
32
|
+
parsePep440Version: () => import_pep440.parse,
|
|
33
|
+
pep440ConstraintFromVersion: () => pep440ConstraintFromVersion,
|
|
34
|
+
pep440Satisfies: () => import_specifier.satisfies,
|
|
35
|
+
unparsePep440Version: () => unparsePep440Version
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(pep440_exports);
|
|
38
|
+
var import_node_assert = __toESM(require("node:assert"));
|
|
39
|
+
var import_version = require("@renovatebot/pep440/lib/version");
|
|
40
|
+
var import_pep440 = require("@renovatebot/pep440");
|
|
41
|
+
var import_specifier = require("@renovatebot/pep440/lib/specifier");
|
|
42
|
+
function pep440ConstraintFromVersion(v) {
|
|
43
|
+
return [
|
|
44
|
+
{
|
|
45
|
+
operator: "==",
|
|
46
|
+
version: unparsePep440Version(v),
|
|
47
|
+
prefix: ""
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
function unparsePep440Version(v) {
|
|
52
|
+
const verstr = (0, import_version.stringify)(v);
|
|
53
|
+
(0, import_node_assert.default)(verstr != null, "pep440/lib/version:stringify returned null");
|
|
54
|
+
return verstr;
|
|
55
|
+
}
|
|
56
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
57
|
+
0 && (module.exports = {
|
|
58
|
+
parsePep440Constraint,
|
|
59
|
+
parsePep440Version,
|
|
60
|
+
pep440ConstraintFromVersion,
|
|
61
|
+
pep440Satisfies,
|
|
62
|
+
unparsePep440Version
|
|
63
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for PEP 508 dependency string formatting and normalization.
|
|
3
|
+
*
|
|
4
|
+
* PEP 508 defines the format for Python dependency specifiers:
|
|
5
|
+
* https://peps.python.org/pep-0508/
|
|
6
|
+
*
|
|
7
|
+
* Format: name[extras] (version) @ url ; markers
|
|
8
|
+
* Examples:
|
|
9
|
+
* - requests>=2.0
|
|
10
|
+
* - requests[security]>=2.0
|
|
11
|
+
* - mypackage @ https://example.com/pkg.zip
|
|
12
|
+
* - requests>=2.0 ; python_version >= "3.8"
|
|
13
|
+
*/
|
|
14
|
+
import type { NormalizedRequirement } from './requirement/types';
|
|
15
|
+
/**
|
|
16
|
+
* Split a package specification into name and extras.
|
|
17
|
+
*
|
|
18
|
+
* @param spec - Package specification that may include extras (e.g., "requests[security,socks]")
|
|
19
|
+
* @returns Tuple of [name, extras] where extras is undefined if not present
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* splitExtras("requests") // ["requests", undefined]
|
|
23
|
+
* splitExtras("requests[security]") // ["requests", ["security"]]
|
|
24
|
+
* splitExtras("requests[security,socks]") // ["requests", ["security", "socks"]]
|
|
25
|
+
*/
|
|
26
|
+
export declare function splitExtras(spec: string): [string, string[] | undefined];
|
|
27
|
+
/**
|
|
28
|
+
* Normalize a Python package name according to PEP 503.
|
|
29
|
+
*
|
|
30
|
+
* PEP 503 specifies that package names should be compared case-insensitively
|
|
31
|
+
* and with underscores, hyphens, and periods treated as equivalent.
|
|
32
|
+
*
|
|
33
|
+
* @param name - Package name to normalize
|
|
34
|
+
* @returns Lowercase name with separators normalized to hyphens
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* normalizePackageName("My_Package.Name") // "my-package-name"
|
|
38
|
+
*/
|
|
39
|
+
export declare function normalizePackageName(name: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Format a normalized requirement as a PEP 508 dependency string.
|
|
42
|
+
*
|
|
43
|
+
* @param req - Normalized requirement to format
|
|
44
|
+
* @returns PEP 508 formatted string
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* formatPep508({ name: "requests", version: ">=2.0" })
|
|
48
|
+
* // "requests>=2.0"
|
|
49
|
+
*
|
|
50
|
+
* formatPep508({ name: "mypackage", url: "https://example.com/pkg.zip" })
|
|
51
|
+
* // "mypackage @ https://example.com/pkg.zip"
|
|
52
|
+
*
|
|
53
|
+
* formatPep508({ name: "requests", version: ">=2.0", extras: ["security"], markers: "python_version >= '3.8'" })
|
|
54
|
+
* // "requests[security]>=2.0 ; python_version >= '3.8'"
|
|
55
|
+
*/
|
|
56
|
+
export declare function formatPep508(req: NormalizedRequirement): string;
|
|
57
|
+
/**
|
|
58
|
+
* Merge extras arrays, combining and deduplicating entries.
|
|
59
|
+
*
|
|
60
|
+
* @param existing - Existing extras array (may be undefined)
|
|
61
|
+
* @param additional - Additional extras to merge (may be undefined or a single string)
|
|
62
|
+
* @returns Merged extras array, or undefined if both inputs are empty/undefined
|
|
63
|
+
*/
|
|
64
|
+
export declare function mergeExtras(existing: string[] | undefined, additional: string[] | string | undefined): string[] | undefined;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var pep508_exports = {};
|
|
20
|
+
__export(pep508_exports, {
|
|
21
|
+
formatPep508: () => formatPep508,
|
|
22
|
+
mergeExtras: () => mergeExtras,
|
|
23
|
+
normalizePackageName: () => normalizePackageName,
|
|
24
|
+
splitExtras: () => splitExtras
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(pep508_exports);
|
|
27
|
+
const EXTRAS_REGEX = /^(.+)\[([^\]]+)\]$/;
|
|
28
|
+
function splitExtras(spec) {
|
|
29
|
+
const match = EXTRAS_REGEX.exec(spec);
|
|
30
|
+
if (!match) {
|
|
31
|
+
return [spec, void 0];
|
|
32
|
+
}
|
|
33
|
+
const extras = match[2].split(",").map((e) => e.trim());
|
|
34
|
+
return [match[1], extras];
|
|
35
|
+
}
|
|
36
|
+
function normalizePackageName(name) {
|
|
37
|
+
return name.toLowerCase().replace(/[-_.]+/g, "-");
|
|
38
|
+
}
|
|
39
|
+
function formatPep508(req) {
|
|
40
|
+
let result = req.name;
|
|
41
|
+
if (req.extras && req.extras.length > 0) {
|
|
42
|
+
result += `[${req.extras.join(",")}]`;
|
|
43
|
+
}
|
|
44
|
+
if (req.url) {
|
|
45
|
+
result += ` @ ${req.url}`;
|
|
46
|
+
} else if (req.version && req.version !== "*") {
|
|
47
|
+
result += req.version;
|
|
48
|
+
}
|
|
49
|
+
if (req.markers) {
|
|
50
|
+
result += ` ; ${req.markers}`;
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
function mergeExtras(existing, additional) {
|
|
55
|
+
const result = new Set(existing || []);
|
|
56
|
+
if (additional) {
|
|
57
|
+
const additionalArray = Array.isArray(additional) ? additional : [additional];
|
|
58
|
+
for (const extra of additionalArray) {
|
|
59
|
+
result.add(extra);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return result.size > 0 ? Array.from(result) : void 0;
|
|
63
|
+
}
|
|
64
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
65
|
+
0 && (module.exports = {
|
|
66
|
+
formatPep508,
|
|
67
|
+
mergeExtras,
|
|
68
|
+
normalizePackageName,
|
|
69
|
+
splitExtras
|
|
70
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for Pipfile and Pipfile.lock configuration types.
|
|
3
|
+
*
|
|
4
|
+
* Types are defined in types.ts (source of truth).
|
|
5
|
+
* Schemas are generated by ts-to-zod and re-exported here with proper typing.
|
|
6
|
+
*
|
|
7
|
+
* @module pipfile/schema
|
|
8
|
+
*/
|
|
9
|
+
import type { z } from 'zod';
|
|
10
|
+
import type { PipfileDependency, PipfileDependencyDetail, PipfileLike, PipfileLockLike, PipfileLockMeta, PipfileSource } from './types';
|
|
11
|
+
/**
|
|
12
|
+
* Schema for Pipfile dependency detail.
|
|
13
|
+
*/
|
|
14
|
+
export declare const PipfileDependencyDetailSchema: z.ZodType<PipfileDependencyDetail, z.ZodTypeDef, PipfileDependencyDetail>;
|
|
15
|
+
/**
|
|
16
|
+
* Schema for Pipfile dependency (string version specifier or detail object).
|
|
17
|
+
*/
|
|
18
|
+
export declare const PipfileDependencySchema: z.ZodType<PipfileDependency, z.ZodTypeDef, PipfileDependency>;
|
|
19
|
+
/**
|
|
20
|
+
* Schema for Pipfile source configuration.
|
|
21
|
+
*/
|
|
22
|
+
export declare const PipfileSourceSchema: z.ZodType<PipfileSource, z.ZodTypeDef, PipfileSource>;
|
|
23
|
+
/**
|
|
24
|
+
* Schema for Pipfile.
|
|
25
|
+
*
|
|
26
|
+
* Note: This is an intersection type (z.record().and(z.object())) so we don't
|
|
27
|
+
* call .passthrough() - the record part already allows additional keys.
|
|
28
|
+
*/
|
|
29
|
+
export declare const PipfileLikeSchema: z.ZodType<PipfileLike, z.ZodTypeDef, PipfileLike>;
|
|
30
|
+
/**
|
|
31
|
+
* Schema for Pipfile.lock _meta section.
|
|
32
|
+
*/
|
|
33
|
+
export declare const PipfileLockMetaSchema: z.ZodType<PipfileLockMeta, z.ZodTypeDef, PipfileLockMeta>;
|
|
34
|
+
/**
|
|
35
|
+
* Schema for Pipfile.lock.
|
|
36
|
+
*
|
|
37
|
+
* Note: This is an intersection type (z.record().and(z.object())) so we don't
|
|
38
|
+
* call .passthrough() - the record part already allows additional keys.
|
|
39
|
+
*/
|
|
40
|
+
export declare const PipfileLockLikeSchema: z.ZodType<PipfileLockLike, z.ZodTypeDef, PipfileLockLike>;
|