@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.
Files changed (54) hide show
  1. package/LICENSE +202 -0
  2. package/dist/index.d.ts +22 -0
  3. package/dist/index.js +107 -0
  4. package/dist/manifest/package.d.ts +166 -0
  5. package/dist/manifest/package.js +422 -0
  6. package/dist/manifest/pep440.d.ts +6 -0
  7. package/dist/manifest/pep440.js +63 -0
  8. package/dist/manifest/pep508.d.ts +64 -0
  9. package/dist/manifest/pep508.js +70 -0
  10. package/dist/manifest/pipfile/schema.d.ts +40 -0
  11. package/dist/manifest/pipfile/schema.js +44 -0
  12. package/dist/manifest/pipfile/schema.zod.d.ts +606 -0
  13. package/dist/manifest/pipfile/schema.zod.js +97 -0
  14. package/dist/manifest/pipfile/types.d.ts +77 -0
  15. package/dist/manifest/pipfile/types.js +16 -0
  16. package/dist/manifest/pipfile-parser.d.ts +35 -0
  17. package/dist/manifest/pipfile-parser.js +262 -0
  18. package/dist/manifest/pyproject/schema.d.ts +50 -0
  19. package/dist/manifest/pyproject/schema.js +56 -0
  20. package/dist/manifest/pyproject/schema.zod.d.ts +767 -0
  21. package/dist/manifest/pyproject/schema.zod.js +94 -0
  22. package/dist/manifest/pyproject/types.d.ts +93 -0
  23. package/dist/manifest/pyproject/types.js +16 -0
  24. package/dist/manifest/python-selector.d.ts +123 -0
  25. package/dist/manifest/python-selector.js +185 -0
  26. package/dist/manifest/python-specifiers.d.ts +76 -0
  27. package/dist/manifest/python-specifiers.js +156 -0
  28. package/dist/manifest/requirement/schema.d.ts +28 -0
  29. package/dist/manifest/requirement/schema.js +35 -0
  30. package/dist/manifest/requirement/schema.zod.d.ts +76 -0
  31. package/dist/manifest/requirement/schema.zod.js +49 -0
  32. package/dist/manifest/requirement/types.d.ts +50 -0
  33. package/dist/manifest/requirement/types.js +16 -0
  34. package/dist/manifest/requirements-txt-parser.d.ts +55 -0
  35. package/dist/manifest/requirements-txt-parser.js +400 -0
  36. package/dist/manifest/uv-config/schema.d.ts +22 -0
  37. package/dist/manifest/uv-config/schema.js +35 -0
  38. package/dist/manifest/uv-config/schema.zod.d.ts +140 -0
  39. package/dist/manifest/uv-config/schema.zod.js +48 -0
  40. package/dist/manifest/uv-config/types.d.ts +48 -0
  41. package/dist/manifest/uv-config/types.js +16 -0
  42. package/dist/manifest/uv-python-version-parser.d.ts +28 -0
  43. package/dist/manifest/uv-python-version-parser.js +268 -0
  44. package/dist/types.d.ts +17 -0
  45. package/dist/types.js +16 -0
  46. package/dist/util/config.d.ts +20 -0
  47. package/dist/util/config.js +100 -0
  48. package/dist/util/error.d.ts +39 -0
  49. package/dist/util/error.js +54 -0
  50. package/dist/util/fs.d.ts +25 -0
  51. package/dist/util/fs.js +75 -0
  52. package/dist/util/type.d.ts +7 -0
  53. package/dist/util/type.js +30 -0
  54. 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>;