@vercel/python-analysis 0.7.0 → 0.8.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 +121 -40
- package/dist/index.d.ts +2 -2
- package/dist/index.js +119 -41
- package/dist/manifest/dist-metadata.d.ts +14 -0
- package/dist/semantic/entrypoints.d.ts +20 -0
- package/dist/wasm/vercel_python_analysis.core.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.d.ts +2 -0
- package/dist/wasm/vercel_python_analysis.js +107 -9
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -66,8 +66,11 @@ __export(src_exports, {
|
|
|
66
66
|
containsAppOrHandler: () => containsAppOrHandler,
|
|
67
67
|
createMinimalManifest: () => createMinimalManifest,
|
|
68
68
|
discoverPythonPackage: () => discoverPythonPackage,
|
|
69
|
+
extendDistRecord: () => extendDistRecord,
|
|
70
|
+
getStringConstant: () => getStringConstant,
|
|
69
71
|
isPrivatePackageSource: () => isPrivatePackageSource,
|
|
70
|
-
normalizePackageName: () =>
|
|
72
|
+
normalizePackageName: () => normalizePackageName2,
|
|
73
|
+
parseDjangoSettingsModule: () => parseDjangoSettingsModule,
|
|
71
74
|
parseUvLock: () => parseUvLock,
|
|
72
75
|
scanDistributions: () => scanDistributions,
|
|
73
76
|
selectPython: () => selectPython,
|
|
@@ -123,10 +126,65 @@ async function containsAppOrHandler(source) {
|
|
|
123
126
|
const mod = await importWasmModule();
|
|
124
127
|
return mod.containsAppOrHandler(source);
|
|
125
128
|
}
|
|
129
|
+
async function getStringConstant(source, name) {
|
|
130
|
+
const mod = await importWasmModule();
|
|
131
|
+
return mod.getStringConstant(source, name) ?? null;
|
|
132
|
+
}
|
|
133
|
+
var DJANGO_SETTINGS_MODULE_PATTERN_RE = /DJANGO_SETTINGS_MODULE/;
|
|
134
|
+
async function parseDjangoSettingsModule(content) {
|
|
135
|
+
if (!DJANGO_SETTINGS_MODULE_PATTERN_RE.test(content)) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const mod = await importWasmModule();
|
|
139
|
+
return mod.parseDjangoSettingsModule(content) ?? null;
|
|
140
|
+
}
|
|
126
141
|
|
|
127
142
|
// src/manifest/dist-metadata.ts
|
|
143
|
+
var import_node_crypto = require("crypto");
|
|
144
|
+
var import_node_fs = require("fs");
|
|
128
145
|
var import_promises2 = require("fs/promises");
|
|
129
146
|
var import_node_path2 = require("path");
|
|
147
|
+
|
|
148
|
+
// src/manifest/pep508.ts
|
|
149
|
+
var EXTRAS_REGEX = /^(.+)\[([^\]]+)\]$/;
|
|
150
|
+
function splitExtras(spec) {
|
|
151
|
+
const match = EXTRAS_REGEX.exec(spec);
|
|
152
|
+
if (!match) {
|
|
153
|
+
return [spec, void 0];
|
|
154
|
+
}
|
|
155
|
+
const extras = match[2].split(",").map((e) => e.trim());
|
|
156
|
+
return [match[1], extras];
|
|
157
|
+
}
|
|
158
|
+
function normalizePackageName(name) {
|
|
159
|
+
return name.toLowerCase().replace(/[-_.]+/g, "-");
|
|
160
|
+
}
|
|
161
|
+
function formatPep508(req) {
|
|
162
|
+
let result = req.name;
|
|
163
|
+
if (req.extras && req.extras.length > 0) {
|
|
164
|
+
result += `[${req.extras.join(",")}]`;
|
|
165
|
+
}
|
|
166
|
+
if (req.url) {
|
|
167
|
+
result += ` @ ${req.url}`;
|
|
168
|
+
} else if (req.version && req.version !== "*") {
|
|
169
|
+
result += req.version;
|
|
170
|
+
}
|
|
171
|
+
if (req.markers) {
|
|
172
|
+
result += ` ; ${req.markers}`;
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
function mergeExtras(existing, additional) {
|
|
177
|
+
const result = new Set(existing || []);
|
|
178
|
+
if (additional) {
|
|
179
|
+
const additionalArray = Array.isArray(additional) ? additional : [additional];
|
|
180
|
+
for (const extra of additionalArray) {
|
|
181
|
+
result.add(extra);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return result.size > 0 ? Array.from(result) : void 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/manifest/dist-metadata.ts
|
|
130
188
|
async function readDistInfoFile(distInfoDir, filename) {
|
|
131
189
|
try {
|
|
132
190
|
return await (0, import_promises2.readFile)((0, import_node_path2.join)(distInfoDir, filename), "utf-8");
|
|
@@ -213,6 +271,62 @@ async function scanDistributions(sitePackagesDir) {
|
|
|
213
271
|
}
|
|
214
272
|
return index;
|
|
215
273
|
}
|
|
274
|
+
function hashFile(filePath) {
|
|
275
|
+
return new Promise((resolve, reject) => {
|
|
276
|
+
const h = (0, import_node_crypto.createHash)("sha256");
|
|
277
|
+
let size = 0;
|
|
278
|
+
const stream = (0, import_node_fs.createReadStream)(filePath);
|
|
279
|
+
stream.on("data", (chunk) => {
|
|
280
|
+
size += chunk.length;
|
|
281
|
+
h.update(chunk);
|
|
282
|
+
});
|
|
283
|
+
stream.on("error", reject);
|
|
284
|
+
stream.on("end", () => {
|
|
285
|
+
resolve({ hash: h.digest("base64url"), size });
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
async function extendDistRecord(sitePackagesDir, packageName, paths) {
|
|
290
|
+
const normalizedTarget = normalizePackageName(packageName);
|
|
291
|
+
const entries = await (0, import_promises2.readdir)(sitePackagesDir);
|
|
292
|
+
const distInfoDirName = entries.find((e) => {
|
|
293
|
+
if (!e.endsWith(".dist-info"))
|
|
294
|
+
return false;
|
|
295
|
+
const withoutSuffix = e.slice(0, -".dist-info".length);
|
|
296
|
+
const lastHyphen = withoutSuffix.lastIndexOf("-");
|
|
297
|
+
if (lastHyphen === -1)
|
|
298
|
+
return false;
|
|
299
|
+
const dirName = withoutSuffix.slice(0, lastHyphen);
|
|
300
|
+
return normalizePackageName(dirName) === normalizedTarget;
|
|
301
|
+
});
|
|
302
|
+
if (!distInfoDirName) {
|
|
303
|
+
throw new Error(
|
|
304
|
+
`No .dist-info directory found for package "${packageName}" in ${sitePackagesDir}`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
const recordPath = (0, import_node_path2.join)(sitePackagesDir, distInfoDirName, "RECORD");
|
|
308
|
+
let existingRecord;
|
|
309
|
+
try {
|
|
310
|
+
existingRecord = await (0, import_promises2.readFile)(recordPath, "utf-8");
|
|
311
|
+
} catch {
|
|
312
|
+
throw new Error(`RECORD file not found in ${distInfoDirName}`);
|
|
313
|
+
}
|
|
314
|
+
const existingPaths = new Set(
|
|
315
|
+
existingRecord.split("\n").filter((line) => line.length > 0).map((line) => line.split(",")[0])
|
|
316
|
+
);
|
|
317
|
+
const newEntries = paths.filter((p) => !existingPaths.has(p));
|
|
318
|
+
if (newEntries.length > 0) {
|
|
319
|
+
const prefix = existingRecord.length > 0 && !existingRecord.endsWith("\n") ? "\n" : "";
|
|
320
|
+
const lines = [];
|
|
321
|
+
for (const p of newEntries) {
|
|
322
|
+
const fullPath = (0, import_node_path2.join)(sitePackagesDir, p);
|
|
323
|
+
const { hash, size } = await hashFile(fullPath);
|
|
324
|
+
lines.push(`${p},sha256=${hash},${size}`);
|
|
325
|
+
}
|
|
326
|
+
await (0, import_promises2.appendFile)(recordPath, prefix + lines.join("\n") + "\n");
|
|
327
|
+
}
|
|
328
|
+
return newEntries.length;
|
|
329
|
+
}
|
|
216
330
|
|
|
217
331
|
// src/manifest/package.ts
|
|
218
332
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
@@ -433,42 +547,6 @@ var PipfileLikeSchema = pipfileLikeSchema;
|
|
|
433
547
|
var PipfileLockMetaSchema = pipfileLockMetaSchema.passthrough();
|
|
434
548
|
var PipfileLockLikeSchema = pipfileLockLikeSchema;
|
|
435
549
|
|
|
436
|
-
// src/manifest/pep508.ts
|
|
437
|
-
var EXTRAS_REGEX = /^(.+)\[([^\]]+)\]$/;
|
|
438
|
-
function splitExtras(spec) {
|
|
439
|
-
const match = EXTRAS_REGEX.exec(spec);
|
|
440
|
-
if (!match) {
|
|
441
|
-
return [spec, void 0];
|
|
442
|
-
}
|
|
443
|
-
const extras = match[2].split(",").map((e) => e.trim());
|
|
444
|
-
return [match[1], extras];
|
|
445
|
-
}
|
|
446
|
-
function formatPep508(req) {
|
|
447
|
-
let result = req.name;
|
|
448
|
-
if (req.extras && req.extras.length > 0) {
|
|
449
|
-
result += `[${req.extras.join(",")}]`;
|
|
450
|
-
}
|
|
451
|
-
if (req.url) {
|
|
452
|
-
result += ` @ ${req.url}`;
|
|
453
|
-
} else if (req.version && req.version !== "*") {
|
|
454
|
-
result += req.version;
|
|
455
|
-
}
|
|
456
|
-
if (req.markers) {
|
|
457
|
-
result += ` ; ${req.markers}`;
|
|
458
|
-
}
|
|
459
|
-
return result;
|
|
460
|
-
}
|
|
461
|
-
function mergeExtras(existing, additional) {
|
|
462
|
-
const result = new Set(existing || []);
|
|
463
|
-
if (additional) {
|
|
464
|
-
const additionalArray = Array.isArray(additional) ? additional : [additional];
|
|
465
|
-
for (const extra of additionalArray) {
|
|
466
|
-
result.add(extra);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
return result.size > 0 ? Array.from(result) : void 0;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
550
|
// src/util/type.ts
|
|
473
551
|
function isPlainObject(value) {
|
|
474
552
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -2266,7 +2344,7 @@ function isPrivatePackageSource(source) {
|
|
|
2266
2344
|
}
|
|
2267
2345
|
return false;
|
|
2268
2346
|
}
|
|
2269
|
-
function
|
|
2347
|
+
function normalizePackageName2(name) {
|
|
2270
2348
|
return name.toLowerCase().replace(/[-_.]+/g, "-");
|
|
2271
2349
|
}
|
|
2272
2350
|
function classifyPackages(options) {
|
|
@@ -2274,9 +2352,9 @@ function classifyPackages(options) {
|
|
|
2274
2352
|
const privatePackages = [];
|
|
2275
2353
|
const publicPackages = [];
|
|
2276
2354
|
const packageVersions = {};
|
|
2277
|
-
const excludeSet = new Set(excludePackages.map(
|
|
2355
|
+
const excludeSet = new Set(excludePackages.map(normalizePackageName2));
|
|
2278
2356
|
for (const pkg of lockFile.packages) {
|
|
2279
|
-
if (excludeSet.has(
|
|
2357
|
+
if (excludeSet.has(normalizePackageName2(pkg.name))) {
|
|
2280
2358
|
continue;
|
|
2281
2359
|
}
|
|
2282
2360
|
packageVersions[pkg.name] = pkg.version;
|
|
@@ -2476,8 +2554,11 @@ var HashDigestSchema = hashDigestSchema;
|
|
|
2476
2554
|
containsAppOrHandler,
|
|
2477
2555
|
createMinimalManifest,
|
|
2478
2556
|
discoverPythonPackage,
|
|
2557
|
+
extendDistRecord,
|
|
2558
|
+
getStringConstant,
|
|
2479
2559
|
isPrivatePackageSource,
|
|
2480
2560
|
normalizePackageName,
|
|
2561
|
+
parseDjangoSettingsModule,
|
|
2481
2562
|
parseUvLock,
|
|
2482
2563
|
scanDistributions,
|
|
2483
2564
|
selectPython,
|
package/dist/index.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module @vercel/python-analysis
|
|
8
8
|
*/
|
|
9
|
-
export { containsAppOrHandler } from './semantic/entrypoints';
|
|
9
|
+
export { containsAppOrHandler, getStringConstant, parseDjangoSettingsModule, } from './semantic/entrypoints';
|
|
10
10
|
export type { Distribution, DistributionIndex, PackagePath, DirectUrlInfo, } from './manifest/dist-metadata';
|
|
11
|
-
export { scanDistributions } from './manifest/dist-metadata';
|
|
11
|
+
export { extendDistRecord, scanDistributions } from './manifest/dist-metadata';
|
|
12
12
|
export type { PythonConfig, PythonConfigs, PythonLockFile, PythonManifest, PythonManifestOrigin, PythonPackage, PythonVersionConfig, } from './manifest/package';
|
|
13
13
|
export { discoverPythonPackage, PythonConfigKind, PythonLockFileKind, PythonManifestConvertedKind, PythonManifestKind, } from './manifest/package';
|
|
14
14
|
export { createMinimalManifest, stringifyManifest, type CreateMinimalManifestOptions, } from './manifest/serialize';
|
package/dist/index.js
CHANGED
|
@@ -46,10 +46,65 @@ async function containsAppOrHandler(source) {
|
|
|
46
46
|
const mod = await importWasmModule();
|
|
47
47
|
return mod.containsAppOrHandler(source);
|
|
48
48
|
}
|
|
49
|
+
async function getStringConstant(source, name) {
|
|
50
|
+
const mod = await importWasmModule();
|
|
51
|
+
return mod.getStringConstant(source, name) ?? null;
|
|
52
|
+
}
|
|
53
|
+
var DJANGO_SETTINGS_MODULE_PATTERN_RE = /DJANGO_SETTINGS_MODULE/;
|
|
54
|
+
async function parseDjangoSettingsModule(content) {
|
|
55
|
+
if (!DJANGO_SETTINGS_MODULE_PATTERN_RE.test(content)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const mod = await importWasmModule();
|
|
59
|
+
return mod.parseDjangoSettingsModule(content) ?? null;
|
|
60
|
+
}
|
|
49
61
|
|
|
50
62
|
// src/manifest/dist-metadata.ts
|
|
51
|
-
import {
|
|
63
|
+
import { createHash } from "crypto";
|
|
64
|
+
import { createReadStream } from "fs";
|
|
65
|
+
import { appendFile, readdir, readFile as readFile2 } from "fs/promises";
|
|
52
66
|
import { join as join2 } from "path";
|
|
67
|
+
|
|
68
|
+
// src/manifest/pep508.ts
|
|
69
|
+
var EXTRAS_REGEX = /^(.+)\[([^\]]+)\]$/;
|
|
70
|
+
function splitExtras(spec) {
|
|
71
|
+
const match = EXTRAS_REGEX.exec(spec);
|
|
72
|
+
if (!match) {
|
|
73
|
+
return [spec, void 0];
|
|
74
|
+
}
|
|
75
|
+
const extras = match[2].split(",").map((e) => e.trim());
|
|
76
|
+
return [match[1], extras];
|
|
77
|
+
}
|
|
78
|
+
function normalizePackageName(name) {
|
|
79
|
+
return name.toLowerCase().replace(/[-_.]+/g, "-");
|
|
80
|
+
}
|
|
81
|
+
function formatPep508(req) {
|
|
82
|
+
let result = req.name;
|
|
83
|
+
if (req.extras && req.extras.length > 0) {
|
|
84
|
+
result += `[${req.extras.join(",")}]`;
|
|
85
|
+
}
|
|
86
|
+
if (req.url) {
|
|
87
|
+
result += ` @ ${req.url}`;
|
|
88
|
+
} else if (req.version && req.version !== "*") {
|
|
89
|
+
result += req.version;
|
|
90
|
+
}
|
|
91
|
+
if (req.markers) {
|
|
92
|
+
result += ` ; ${req.markers}`;
|
|
93
|
+
}
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
function mergeExtras(existing, additional) {
|
|
97
|
+
const result = new Set(existing || []);
|
|
98
|
+
if (additional) {
|
|
99
|
+
const additionalArray = Array.isArray(additional) ? additional : [additional];
|
|
100
|
+
for (const extra of additionalArray) {
|
|
101
|
+
result.add(extra);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return result.size > 0 ? Array.from(result) : void 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/manifest/dist-metadata.ts
|
|
53
108
|
async function readDistInfoFile(distInfoDir, filename) {
|
|
54
109
|
try {
|
|
55
110
|
return await readFile2(join2(distInfoDir, filename), "utf-8");
|
|
@@ -136,6 +191,62 @@ async function scanDistributions(sitePackagesDir) {
|
|
|
136
191
|
}
|
|
137
192
|
return index;
|
|
138
193
|
}
|
|
194
|
+
function hashFile(filePath) {
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
const h = createHash("sha256");
|
|
197
|
+
let size = 0;
|
|
198
|
+
const stream = createReadStream(filePath);
|
|
199
|
+
stream.on("data", (chunk) => {
|
|
200
|
+
size += chunk.length;
|
|
201
|
+
h.update(chunk);
|
|
202
|
+
});
|
|
203
|
+
stream.on("error", reject);
|
|
204
|
+
stream.on("end", () => {
|
|
205
|
+
resolve({ hash: h.digest("base64url"), size });
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
async function extendDistRecord(sitePackagesDir, packageName, paths) {
|
|
210
|
+
const normalizedTarget = normalizePackageName(packageName);
|
|
211
|
+
const entries = await readdir(sitePackagesDir);
|
|
212
|
+
const distInfoDirName = entries.find((e) => {
|
|
213
|
+
if (!e.endsWith(".dist-info"))
|
|
214
|
+
return false;
|
|
215
|
+
const withoutSuffix = e.slice(0, -".dist-info".length);
|
|
216
|
+
const lastHyphen = withoutSuffix.lastIndexOf("-");
|
|
217
|
+
if (lastHyphen === -1)
|
|
218
|
+
return false;
|
|
219
|
+
const dirName = withoutSuffix.slice(0, lastHyphen);
|
|
220
|
+
return normalizePackageName(dirName) === normalizedTarget;
|
|
221
|
+
});
|
|
222
|
+
if (!distInfoDirName) {
|
|
223
|
+
throw new Error(
|
|
224
|
+
`No .dist-info directory found for package "${packageName}" in ${sitePackagesDir}`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const recordPath = join2(sitePackagesDir, distInfoDirName, "RECORD");
|
|
228
|
+
let existingRecord;
|
|
229
|
+
try {
|
|
230
|
+
existingRecord = await readFile2(recordPath, "utf-8");
|
|
231
|
+
} catch {
|
|
232
|
+
throw new Error(`RECORD file not found in ${distInfoDirName}`);
|
|
233
|
+
}
|
|
234
|
+
const existingPaths = new Set(
|
|
235
|
+
existingRecord.split("\n").filter((line) => line.length > 0).map((line) => line.split(",")[0])
|
|
236
|
+
);
|
|
237
|
+
const newEntries = paths.filter((p) => !existingPaths.has(p));
|
|
238
|
+
if (newEntries.length > 0) {
|
|
239
|
+
const prefix = existingRecord.length > 0 && !existingRecord.endsWith("\n") ? "\n" : "";
|
|
240
|
+
const lines = [];
|
|
241
|
+
for (const p of newEntries) {
|
|
242
|
+
const fullPath = join2(sitePackagesDir, p);
|
|
243
|
+
const { hash, size } = await hashFile(fullPath);
|
|
244
|
+
lines.push(`${p},sha256=${hash},${size}`);
|
|
245
|
+
}
|
|
246
|
+
await appendFile(recordPath, prefix + lines.join("\n") + "\n");
|
|
247
|
+
}
|
|
248
|
+
return newEntries.length;
|
|
249
|
+
}
|
|
139
250
|
|
|
140
251
|
// src/manifest/package.ts
|
|
141
252
|
import path3 from "path";
|
|
@@ -359,42 +470,6 @@ var PipfileLikeSchema = pipfileLikeSchema;
|
|
|
359
470
|
var PipfileLockMetaSchema = pipfileLockMetaSchema.passthrough();
|
|
360
471
|
var PipfileLockLikeSchema = pipfileLockLikeSchema;
|
|
361
472
|
|
|
362
|
-
// src/manifest/pep508.ts
|
|
363
|
-
var EXTRAS_REGEX = /^(.+)\[([^\]]+)\]$/;
|
|
364
|
-
function splitExtras(spec) {
|
|
365
|
-
const match = EXTRAS_REGEX.exec(spec);
|
|
366
|
-
if (!match) {
|
|
367
|
-
return [spec, void 0];
|
|
368
|
-
}
|
|
369
|
-
const extras = match[2].split(",").map((e) => e.trim());
|
|
370
|
-
return [match[1], extras];
|
|
371
|
-
}
|
|
372
|
-
function formatPep508(req) {
|
|
373
|
-
let result = req.name;
|
|
374
|
-
if (req.extras && req.extras.length > 0) {
|
|
375
|
-
result += `[${req.extras.join(",")}]`;
|
|
376
|
-
}
|
|
377
|
-
if (req.url) {
|
|
378
|
-
result += ` @ ${req.url}`;
|
|
379
|
-
} else if (req.version && req.version !== "*") {
|
|
380
|
-
result += req.version;
|
|
381
|
-
}
|
|
382
|
-
if (req.markers) {
|
|
383
|
-
result += ` ; ${req.markers}`;
|
|
384
|
-
}
|
|
385
|
-
return result;
|
|
386
|
-
}
|
|
387
|
-
function mergeExtras(existing, additional) {
|
|
388
|
-
const result = new Set(existing || []);
|
|
389
|
-
if (additional) {
|
|
390
|
-
const additionalArray = Array.isArray(additional) ? additional : [additional];
|
|
391
|
-
for (const extra of additionalArray) {
|
|
392
|
-
result.add(extra);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
return result.size > 0 ? Array.from(result) : void 0;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
473
|
// src/util/type.ts
|
|
399
474
|
function isPlainObject(value) {
|
|
400
475
|
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -2192,7 +2267,7 @@ function isPrivatePackageSource(source) {
|
|
|
2192
2267
|
}
|
|
2193
2268
|
return false;
|
|
2194
2269
|
}
|
|
2195
|
-
function
|
|
2270
|
+
function normalizePackageName2(name) {
|
|
2196
2271
|
return name.toLowerCase().replace(/[-_.]+/g, "-");
|
|
2197
2272
|
}
|
|
2198
2273
|
function classifyPackages(options) {
|
|
@@ -2200,9 +2275,9 @@ function classifyPackages(options) {
|
|
|
2200
2275
|
const privatePackages = [];
|
|
2201
2276
|
const publicPackages = [];
|
|
2202
2277
|
const packageVersions = {};
|
|
2203
|
-
const excludeSet = new Set(excludePackages.map(
|
|
2278
|
+
const excludeSet = new Set(excludePackages.map(normalizePackageName2));
|
|
2204
2279
|
for (const pkg of lockFile.packages) {
|
|
2205
|
-
if (excludeSet.has(
|
|
2280
|
+
if (excludeSet.has(normalizePackageName2(pkg.name))) {
|
|
2206
2281
|
continue;
|
|
2207
2282
|
}
|
|
2208
2283
|
packageVersions[pkg.name] = pkg.version;
|
|
@@ -2401,8 +2476,11 @@ export {
|
|
|
2401
2476
|
containsAppOrHandler,
|
|
2402
2477
|
createMinimalManifest,
|
|
2403
2478
|
discoverPythonPackage,
|
|
2479
|
+
extendDistRecord,
|
|
2480
|
+
getStringConstant,
|
|
2404
2481
|
isPrivatePackageSource,
|
|
2405
|
-
normalizePackageName,
|
|
2482
|
+
normalizePackageName2 as normalizePackageName,
|
|
2483
|
+
parseDjangoSettingsModule,
|
|
2406
2484
|
parseUvLock,
|
|
2407
2485
|
scanDistributions,
|
|
2408
2486
|
selectPython,
|
|
@@ -101,3 +101,17 @@ export type DistributionIndex = Map<string, Distribution>;
|
|
|
101
101
|
* @returns Map of normalized package name to distribution info
|
|
102
102
|
*/
|
|
103
103
|
export declare function scanDistributions(sitePackagesDir: string): Promise<DistributionIndex>;
|
|
104
|
+
/**
|
|
105
|
+
* Append new file entries to a distribution's RECORD file.
|
|
106
|
+
*
|
|
107
|
+
* Finds the `.dist-info` directory for the given package, reads its RECORD,
|
|
108
|
+
* and appends any paths not already tracked. The caller is responsible for
|
|
109
|
+
* scanning directories and building the path list.
|
|
110
|
+
*
|
|
111
|
+
* @param sitePackagesDir - Absolute path to a site-packages directory
|
|
112
|
+
* @param packageName - Distribution name (matched via PEP 503 normalization)
|
|
113
|
+
* @param paths - File paths relative to site-packages to add
|
|
114
|
+
* @returns Count of new entries appended (skips paths already in RECORD)
|
|
115
|
+
* @throws If the dist-info directory or RECORD file is not found
|
|
116
|
+
*/
|
|
117
|
+
export declare function extendDistRecord(sitePackagesDir: string, packageName: string, paths: string[]): Promise<number>;
|
|
@@ -27,3 +27,23 @@
|
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
29
|
export declare function containsAppOrHandler(source: string): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Extract the string value of a top-level constant with the given name.
|
|
32
|
+
* Only considers simple assignments (NAME = "string") and annotated assignments
|
|
33
|
+
* (NAME: str = "string") at module level. Returns the first matching string
|
|
34
|
+
* value, or null if not found or the value is not a string literal.
|
|
35
|
+
*
|
|
36
|
+
* @param source - Python source code
|
|
37
|
+
* @param name - Constant name (e.g. "VERSION", "APP_NAME")
|
|
38
|
+
* @returns The string value or null
|
|
39
|
+
*/
|
|
40
|
+
export declare function getStringConstant(source: string, name: string): Promise<string | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Parse manage.py content for DJANGO_SETTINGS_MODULE (e.g. from
|
|
43
|
+
* os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')).
|
|
44
|
+
* Uses the WASM Python parser to extract the value from the AST.
|
|
45
|
+
*
|
|
46
|
+
* @param content - Raw content of manage.py
|
|
47
|
+
* @returns The settings module string (e.g. 'app.settings') or null if not found
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseDjangoSettingsModule(content: string): Promise<string | null>;
|
|
Binary file
|
|
@@ -69,6 +69,8 @@ export interface ImportObject {
|
|
|
69
69
|
}
|
|
70
70
|
export interface Root {
|
|
71
71
|
containsAppOrHandler(source: string): boolean,
|
|
72
|
+
getStringConstant(source: string, name: string): string | undefined,
|
|
73
|
+
parseDjangoSettingsModule(source: string): string | undefined,
|
|
72
74
|
parseDistMetadata(content: Uint8Array): DistMetadata,
|
|
73
75
|
parseRecord(content: string): Array<RecordEntry>,
|
|
74
76
|
parseDirectUrl(content: string): DirectUrlInfo,
|
|
@@ -1036,6 +1036,7 @@ let gen = (function* _initGenerator () {
|
|
|
1036
1036
|
let postReturn1;
|
|
1037
1037
|
let postReturn2;
|
|
1038
1038
|
let postReturn3;
|
|
1039
|
+
let postReturn4;
|
|
1039
1040
|
function trampoline0(handle) {
|
|
1040
1041
|
const handleEntry = rscTableRemove(handleTable1, handle);
|
|
1041
1042
|
if (handleEntry.own) {
|
|
@@ -1125,10 +1126,11 @@ let gen = (function* _initGenerator () {
|
|
|
1125
1126
|
'7': trampoline5,
|
|
1126
1127
|
},
|
|
1127
1128
|
}));
|
|
1128
|
-
postReturn0 = exports1['
|
|
1129
|
-
postReturn1 = exports1['cabi_post_parse-
|
|
1130
|
-
postReturn2 = exports1['cabi_post_parse-
|
|
1131
|
-
postReturn3 = exports1['
|
|
1129
|
+
postReturn0 = exports1['cabi_post_get-string-constant'];
|
|
1130
|
+
postReturn1 = exports1['cabi_post_parse-dist-metadata'];
|
|
1131
|
+
postReturn2 = exports1['cabi_post_parse-record'];
|
|
1132
|
+
postReturn3 = exports1['cabi_post_parse-direct-url'];
|
|
1133
|
+
postReturn4 = exports1['cabi_post_normalize-package-name'];
|
|
1132
1134
|
let exports1ContainsAppOrHandler;
|
|
1133
1135
|
|
|
1134
1136
|
function containsAppOrHandler(arg0) {
|
|
@@ -1152,6 +1154,100 @@ let gen = (function* _initGenerator () {
|
|
|
1152
1154
|
});
|
|
1153
1155
|
return bool1 == 0 ? false : (bool1 == 1 ? true : throwInvalidBool());
|
|
1154
1156
|
}
|
|
1157
|
+
let exports1GetStringConstant;
|
|
1158
|
+
|
|
1159
|
+
function getStringConstant(arg0, arg1) {
|
|
1160
|
+
var ptr0 = utf8Encode(arg0, realloc0, memory0);
|
|
1161
|
+
var len0 = utf8EncodedLen;
|
|
1162
|
+
var ptr1 = utf8Encode(arg1, realloc0, memory0);
|
|
1163
|
+
var len1 = utf8EncodedLen;
|
|
1164
|
+
_debugLog('[iface="get-string-constant", function="get-string-constant"][Instruction::CallWasm] enter', {
|
|
1165
|
+
funcName: 'get-string-constant',
|
|
1166
|
+
paramCount: 4,
|
|
1167
|
+
async: false,
|
|
1168
|
+
postReturn: true,
|
|
1169
|
+
});
|
|
1170
|
+
const _wasm_call_currentTaskID = startCurrentTask(0, false, 'exports1GetStringConstant');
|
|
1171
|
+
const ret = exports1GetStringConstant(ptr0, len0, ptr1, len1);
|
|
1172
|
+
endCurrentTask(0);
|
|
1173
|
+
let variant3;
|
|
1174
|
+
switch (dataView(memory0).getUint8(ret + 0, true)) {
|
|
1175
|
+
case 0: {
|
|
1176
|
+
variant3 = undefined;
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
1179
|
+
case 1: {
|
|
1180
|
+
var ptr2 = dataView(memory0).getUint32(ret + 4, true);
|
|
1181
|
+
var len2 = dataView(memory0).getUint32(ret + 8, true);
|
|
1182
|
+
var result2 = utf8Decoder.decode(new Uint8Array(memory0.buffer, ptr2, len2));
|
|
1183
|
+
variant3 = result2;
|
|
1184
|
+
break;
|
|
1185
|
+
}
|
|
1186
|
+
default: {
|
|
1187
|
+
throw new TypeError('invalid variant discriminant for option');
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
_debugLog('[iface="get-string-constant", function="get-string-constant"][Instruction::Return]', {
|
|
1191
|
+
funcName: 'get-string-constant',
|
|
1192
|
+
paramCount: 1,
|
|
1193
|
+
async: false,
|
|
1194
|
+
postReturn: true
|
|
1195
|
+
});
|
|
1196
|
+
const retCopy = variant3;
|
|
1197
|
+
|
|
1198
|
+
let cstate = getOrCreateAsyncState(0);
|
|
1199
|
+
cstate.mayLeave = false;
|
|
1200
|
+
postReturn0(ret);
|
|
1201
|
+
cstate.mayLeave = true;
|
|
1202
|
+
return retCopy;
|
|
1203
|
+
|
|
1204
|
+
}
|
|
1205
|
+
let exports1ParseDjangoSettingsModule;
|
|
1206
|
+
|
|
1207
|
+
function parseDjangoSettingsModule(arg0) {
|
|
1208
|
+
var ptr0 = utf8Encode(arg0, realloc0, memory0);
|
|
1209
|
+
var len0 = utf8EncodedLen;
|
|
1210
|
+
_debugLog('[iface="parse-django-settings-module", function="parse-django-settings-module"][Instruction::CallWasm] enter', {
|
|
1211
|
+
funcName: 'parse-django-settings-module',
|
|
1212
|
+
paramCount: 2,
|
|
1213
|
+
async: false,
|
|
1214
|
+
postReturn: true,
|
|
1215
|
+
});
|
|
1216
|
+
const _wasm_call_currentTaskID = startCurrentTask(0, false, 'exports1ParseDjangoSettingsModule');
|
|
1217
|
+
const ret = exports1ParseDjangoSettingsModule(ptr0, len0);
|
|
1218
|
+
endCurrentTask(0);
|
|
1219
|
+
let variant2;
|
|
1220
|
+
switch (dataView(memory0).getUint8(ret + 0, true)) {
|
|
1221
|
+
case 0: {
|
|
1222
|
+
variant2 = undefined;
|
|
1223
|
+
break;
|
|
1224
|
+
}
|
|
1225
|
+
case 1: {
|
|
1226
|
+
var ptr1 = dataView(memory0).getUint32(ret + 4, true);
|
|
1227
|
+
var len1 = dataView(memory0).getUint32(ret + 8, true);
|
|
1228
|
+
var result1 = utf8Decoder.decode(new Uint8Array(memory0.buffer, ptr1, len1));
|
|
1229
|
+
variant2 = result1;
|
|
1230
|
+
break;
|
|
1231
|
+
}
|
|
1232
|
+
default: {
|
|
1233
|
+
throw new TypeError('invalid variant discriminant for option');
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
_debugLog('[iface="parse-django-settings-module", function="parse-django-settings-module"][Instruction::Return]', {
|
|
1237
|
+
funcName: 'parse-django-settings-module',
|
|
1238
|
+
paramCount: 1,
|
|
1239
|
+
async: false,
|
|
1240
|
+
postReturn: true
|
|
1241
|
+
});
|
|
1242
|
+
const retCopy = variant2;
|
|
1243
|
+
|
|
1244
|
+
let cstate = getOrCreateAsyncState(0);
|
|
1245
|
+
cstate.mayLeave = false;
|
|
1246
|
+
postReturn0(ret);
|
|
1247
|
+
cstate.mayLeave = true;
|
|
1248
|
+
return retCopy;
|
|
1249
|
+
|
|
1250
|
+
}
|
|
1155
1251
|
let exports1ParseDistMetadata;
|
|
1156
1252
|
|
|
1157
1253
|
function parseDistMetadata(arg0) {
|
|
@@ -1482,7 +1578,7 @@ let gen = (function* _initGenerator () {
|
|
|
1482
1578
|
|
|
1483
1579
|
let cstate = getOrCreateAsyncState(0);
|
|
1484
1580
|
cstate.mayLeave = false;
|
|
1485
|
-
|
|
1581
|
+
postReturn1(ret);
|
|
1486
1582
|
cstate.mayLeave = true;
|
|
1487
1583
|
|
|
1488
1584
|
|
|
@@ -1585,7 +1681,7 @@ let gen = (function* _initGenerator () {
|
|
|
1585
1681
|
|
|
1586
1682
|
let cstate = getOrCreateAsyncState(0);
|
|
1587
1683
|
cstate.mayLeave = false;
|
|
1588
|
-
|
|
1684
|
+
postReturn2(ret);
|
|
1589
1685
|
cstate.mayLeave = true;
|
|
1590
1686
|
|
|
1591
1687
|
|
|
@@ -1745,7 +1841,7 @@ let gen = (function* _initGenerator () {
|
|
|
1745
1841
|
|
|
1746
1842
|
let cstate = getOrCreateAsyncState(0);
|
|
1747
1843
|
cstate.mayLeave = false;
|
|
1748
|
-
|
|
1844
|
+
postReturn3(ret);
|
|
1749
1845
|
cstate.mayLeave = true;
|
|
1750
1846
|
|
|
1751
1847
|
|
|
@@ -1783,18 +1879,20 @@ let gen = (function* _initGenerator () {
|
|
|
1783
1879
|
|
|
1784
1880
|
let cstate = getOrCreateAsyncState(0);
|
|
1785
1881
|
cstate.mayLeave = false;
|
|
1786
|
-
|
|
1882
|
+
postReturn4(ret);
|
|
1787
1883
|
cstate.mayLeave = true;
|
|
1788
1884
|
return retCopy;
|
|
1789
1885
|
|
|
1790
1886
|
}
|
|
1791
1887
|
exports1ContainsAppOrHandler = exports1['contains-app-or-handler'];
|
|
1888
|
+
exports1GetStringConstant = exports1['get-string-constant'];
|
|
1889
|
+
exports1ParseDjangoSettingsModule = exports1['parse-django-settings-module'];
|
|
1792
1890
|
exports1ParseDistMetadata = exports1['parse-dist-metadata'];
|
|
1793
1891
|
exports1ParseRecord = exports1['parse-record'];
|
|
1794
1892
|
exports1ParseDirectUrl = exports1['parse-direct-url'];
|
|
1795
1893
|
exports1NormalizePackageName = exports1['normalize-package-name'];
|
|
1796
1894
|
|
|
1797
|
-
return { containsAppOrHandler, normalizePackageName, parseDirectUrl, parseDistMetadata, parseRecord, };
|
|
1895
|
+
return { containsAppOrHandler, getStringConstant, normalizePackageName, parseDirectUrl, parseDistMetadata, parseDjangoSettingsModule, parseRecord, };
|
|
1798
1896
|
})();
|
|
1799
1897
|
let promise, resolve, reject;
|
|
1800
1898
|
function runNext (value) {
|