@vercel/python-analysis 0.4.1 → 0.5.0
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 +235 -44
- package/dist/index.d.ts +4 -0
- package/dist/index.js +197 -12
- package/dist/manifest/dist-metadata.d.ts +103 -0
- package/dist/manifest/uv-lock-parser.d.ts +77 -0
- package/dist/wasm/interfaces/wasi-random-insecure-seed.d.ts +2 -0
- package/dist/wasm/vercel_python_analysis.core.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.core2.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.core3.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.core4.wasm +0 -0
- package/dist/wasm/vercel_python_analysis.d.ts +60 -0
- package/dist/wasm/vercel_python_analysis.js +734 -20
- package/package.json +1 -1
- /package/dist/{semantic → wasm}/load.d.ts +0 -0
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/wasm/load.ts
|
|
2
2
|
import { readFile } from "fs/promises";
|
|
3
3
|
import { createRequire } from "module";
|
|
4
4
|
import { dirname, join } from "path";
|
|
@@ -17,7 +17,7 @@ function getWasmDir() {
|
|
|
17
17
|
}
|
|
18
18
|
async function getCoreModule(path4) {
|
|
19
19
|
const wasmPath = join(getWasmDir(), path4);
|
|
20
|
-
const wasmBytes = await readFile(wasmPath);
|
|
20
|
+
const wasmBytes = new Uint8Array(await readFile(wasmPath));
|
|
21
21
|
return WebAssembly.compile(wasmBytes);
|
|
22
22
|
}
|
|
23
23
|
async function importWasmModule() {
|
|
@@ -47,6 +47,96 @@ async function containsAppOrHandler(source) {
|
|
|
47
47
|
return mod.containsAppOrHandler(source);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// src/manifest/dist-metadata.ts
|
|
51
|
+
import { readdir, readFile as readFile2 } from "fs/promises";
|
|
52
|
+
import { join as join2 } from "path";
|
|
53
|
+
async function readDistInfoFile(distInfoDir, filename) {
|
|
54
|
+
try {
|
|
55
|
+
return await readFile2(join2(distInfoDir, filename), "utf-8");
|
|
56
|
+
} catch {
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function scanDistributions(sitePackagesDir) {
|
|
61
|
+
const mod = await importWasmModule();
|
|
62
|
+
const index = /* @__PURE__ */ new Map();
|
|
63
|
+
let entries;
|
|
64
|
+
try {
|
|
65
|
+
entries = await readdir(sitePackagesDir);
|
|
66
|
+
} catch {
|
|
67
|
+
return index;
|
|
68
|
+
}
|
|
69
|
+
const distInfoDirs = entries.filter((e) => e.endsWith(".dist-info"));
|
|
70
|
+
for (const dirName of distInfoDirs) {
|
|
71
|
+
const distInfoPath = join2(sitePackagesDir, dirName);
|
|
72
|
+
const metadataContent = await readDistInfoFile(distInfoPath, "METADATA");
|
|
73
|
+
if (!metadataContent) {
|
|
74
|
+
console.debug(`Missing METADATA in ${dirName}`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
let metadata;
|
|
78
|
+
try {
|
|
79
|
+
metadata = mod.parseDistMetadata(
|
|
80
|
+
new TextEncoder().encode(metadataContent)
|
|
81
|
+
);
|
|
82
|
+
} catch (e) {
|
|
83
|
+
console.debug(`Failed to parse METADATA for ${dirName}: ${e}`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const normalizedName = mod.normalizePackageName(metadata.name);
|
|
87
|
+
let files = [];
|
|
88
|
+
const recordContent = await readDistInfoFile(distInfoPath, "RECORD");
|
|
89
|
+
if (recordContent) {
|
|
90
|
+
try {
|
|
91
|
+
files = mod.parseRecord(recordContent);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
console.warn(`Failed to parse RECORD for ${dirName}: ${e}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
let origin;
|
|
97
|
+
const directUrlContent = await readDistInfoFile(
|
|
98
|
+
distInfoPath,
|
|
99
|
+
"direct_url.json"
|
|
100
|
+
);
|
|
101
|
+
if (directUrlContent) {
|
|
102
|
+
try {
|
|
103
|
+
origin = mod.parseDirectUrl(directUrlContent);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.debug(`Failed to parse direct_url.json for ${dirName}: ${e}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const installerContent = await readDistInfoFile(distInfoPath, "INSTALLER");
|
|
109
|
+
const installer = installerContent?.trim() || void 0;
|
|
110
|
+
const dist = {
|
|
111
|
+
name: normalizedName,
|
|
112
|
+
version: metadata.version,
|
|
113
|
+
metadataVersion: metadata.metadataVersion,
|
|
114
|
+
summary: metadata.summary,
|
|
115
|
+
description: metadata.description,
|
|
116
|
+
descriptionContentType: metadata.descriptionContentType,
|
|
117
|
+
requiresDist: metadata.requiresDist,
|
|
118
|
+
requiresPython: metadata.requiresPython,
|
|
119
|
+
providesExtra: metadata.providesExtra,
|
|
120
|
+
author: metadata.author,
|
|
121
|
+
authorEmail: metadata.authorEmail,
|
|
122
|
+
maintainer: metadata.maintainer,
|
|
123
|
+
maintainerEmail: metadata.maintainerEmail,
|
|
124
|
+
license: metadata.license,
|
|
125
|
+
licenseExpression: metadata.licenseExpression,
|
|
126
|
+
classifiers: metadata.classifiers,
|
|
127
|
+
homePage: metadata.homePage,
|
|
128
|
+
projectUrls: metadata.projectUrls,
|
|
129
|
+
platforms: metadata.platforms,
|
|
130
|
+
dynamic: metadata.dynamic,
|
|
131
|
+
files,
|
|
132
|
+
origin,
|
|
133
|
+
installer
|
|
134
|
+
};
|
|
135
|
+
index.set(normalizedName, dist);
|
|
136
|
+
}
|
|
137
|
+
return index;
|
|
138
|
+
}
|
|
139
|
+
|
|
50
140
|
// src/manifest/package.ts
|
|
51
141
|
import path3 from "path";
|
|
52
142
|
import { match as minimatchMatch } from "minimatch";
|
|
@@ -58,7 +148,7 @@ import toml from "smol-toml";
|
|
|
58
148
|
|
|
59
149
|
// src/util/fs.ts
|
|
60
150
|
import path from "path";
|
|
61
|
-
import { readFile as
|
|
151
|
+
import { readFile as readFile3 } from "fs-extra";
|
|
62
152
|
|
|
63
153
|
// src/util/error.ts
|
|
64
154
|
import util from "util";
|
|
@@ -88,7 +178,7 @@ var PythonAnalysisError = class extends Error {
|
|
|
88
178
|
// src/util/fs.ts
|
|
89
179
|
async function readFileIfExists(file) {
|
|
90
180
|
try {
|
|
91
|
-
return await
|
|
181
|
+
return await readFile3(file);
|
|
92
182
|
} catch (error) {
|
|
93
183
|
if (!isErrnoException(error, "ENOENT")) {
|
|
94
184
|
throw error;
|
|
@@ -991,9 +1081,9 @@ function normalizePathRequirement(rawLine) {
|
|
|
991
1081
|
}
|
|
992
1082
|
return req;
|
|
993
1083
|
}
|
|
994
|
-
function convertRequirementsToPyprojectToml(fileContent,
|
|
1084
|
+
function convertRequirementsToPyprojectToml(fileContent, readFile4) {
|
|
995
1085
|
const pyproject = {};
|
|
996
|
-
const parsed = parseRequirementsFile(fileContent,
|
|
1086
|
+
const parsed = parseRequirementsFile(fileContent, readFile4);
|
|
997
1087
|
const deps = [];
|
|
998
1088
|
const sources = {};
|
|
999
1089
|
for (const req of parsed.requirements) {
|
|
@@ -1052,11 +1142,11 @@ function buildIndexEntries(pipOptions) {
|
|
|
1052
1142
|
}
|
|
1053
1143
|
return indexes;
|
|
1054
1144
|
}
|
|
1055
|
-
function parseRequirementsFile(fileContent,
|
|
1145
|
+
function parseRequirementsFile(fileContent, readFile4) {
|
|
1056
1146
|
const visited = /* @__PURE__ */ new Set();
|
|
1057
|
-
return parseRequirementsFileInternal(fileContent,
|
|
1147
|
+
return parseRequirementsFileInternal(fileContent, readFile4, visited);
|
|
1058
1148
|
}
|
|
1059
|
-
function parseRequirementsFileInternal(fileContent,
|
|
1149
|
+
function parseRequirementsFileInternal(fileContent, readFile4, visited) {
|
|
1060
1150
|
const { cleanedContent, options, pathRequirements, editableRequirements } = extractPipArguments(fileContent);
|
|
1061
1151
|
const hashMap = buildHashMap(fileContent);
|
|
1062
1152
|
const requirements = parsePipRequirementsFile(cleanedContent);
|
|
@@ -1104,18 +1194,18 @@ function parseRequirementsFileInternal(fileContent, readFile3, visited) {
|
|
|
1104
1194
|
normalized.push(norm);
|
|
1105
1195
|
}
|
|
1106
1196
|
}
|
|
1107
|
-
if (
|
|
1197
|
+
if (readFile4) {
|
|
1108
1198
|
for (const refPath of mergedOptions.requirementFiles) {
|
|
1109
1199
|
const refPathKey = normalize(refPath);
|
|
1110
1200
|
if (visited.has(refPathKey)) {
|
|
1111
1201
|
continue;
|
|
1112
1202
|
}
|
|
1113
1203
|
visited.add(refPathKey);
|
|
1114
|
-
const refContent =
|
|
1204
|
+
const refContent = readFile4(refPath);
|
|
1115
1205
|
if (refContent != null) {
|
|
1116
1206
|
const refParsed = parseRequirementsFileInternal(
|
|
1117
1207
|
refContent,
|
|
1118
|
-
|
|
1208
|
+
readFile4,
|
|
1119
1209
|
visited
|
|
1120
1210
|
);
|
|
1121
1211
|
const existingNames = new Set(
|
|
@@ -2052,6 +2142,95 @@ function createMinimalManifest(options = {}) {
|
|
|
2052
2142
|
};
|
|
2053
2143
|
}
|
|
2054
2144
|
|
|
2145
|
+
// src/manifest/uv-lock-parser.ts
|
|
2146
|
+
import toml3 from "smol-toml";
|
|
2147
|
+
function parseUvLock(content, path4) {
|
|
2148
|
+
let parsed;
|
|
2149
|
+
try {
|
|
2150
|
+
parsed = toml3.parse(content);
|
|
2151
|
+
} catch (error) {
|
|
2152
|
+
throw new PythonAnalysisError({
|
|
2153
|
+
message: `Could not parse uv.lock: ${error instanceof Error ? error.message : String(error)}`,
|
|
2154
|
+
code: "PYTHON_UV_LOCK_PARSE_ERROR",
|
|
2155
|
+
path: path4,
|
|
2156
|
+
fileContent: content
|
|
2157
|
+
});
|
|
2158
|
+
}
|
|
2159
|
+
const packages = (parsed.package ?? []).filter((pkg) => pkg.name && pkg.version).map((pkg) => ({
|
|
2160
|
+
name: pkg.name,
|
|
2161
|
+
version: pkg.version,
|
|
2162
|
+
source: pkg.source
|
|
2163
|
+
}));
|
|
2164
|
+
return { version: parsed.version, packages };
|
|
2165
|
+
}
|
|
2166
|
+
var PUBLIC_PYPI_PATTERNS = [
|
|
2167
|
+
"https://pypi.org",
|
|
2168
|
+
"https://files.pythonhosted.org",
|
|
2169
|
+
"pypi.org"
|
|
2170
|
+
];
|
|
2171
|
+
function isPublicPyPIRegistry(registryUrl) {
|
|
2172
|
+
if (!registryUrl)
|
|
2173
|
+
return true;
|
|
2174
|
+
const normalized = registryUrl.toLowerCase();
|
|
2175
|
+
return PUBLIC_PYPI_PATTERNS.some((pattern) => normalized.includes(pattern));
|
|
2176
|
+
}
|
|
2177
|
+
function isPrivatePackageSource(source) {
|
|
2178
|
+
if (!source)
|
|
2179
|
+
return false;
|
|
2180
|
+
if (source.git)
|
|
2181
|
+
return true;
|
|
2182
|
+
if (source.path)
|
|
2183
|
+
return true;
|
|
2184
|
+
if (source.editable)
|
|
2185
|
+
return true;
|
|
2186
|
+
if (source.url)
|
|
2187
|
+
return true;
|
|
2188
|
+
if (source.virtual)
|
|
2189
|
+
return true;
|
|
2190
|
+
if (source.registry && !isPublicPyPIRegistry(source.registry)) {
|
|
2191
|
+
return true;
|
|
2192
|
+
}
|
|
2193
|
+
return false;
|
|
2194
|
+
}
|
|
2195
|
+
function normalizePackageName(name) {
|
|
2196
|
+
return name.toLowerCase().replace(/[-_.]+/g, "-");
|
|
2197
|
+
}
|
|
2198
|
+
function classifyPackages(options) {
|
|
2199
|
+
const { lockFile, excludePackages = [] } = options;
|
|
2200
|
+
const privatePackages = [];
|
|
2201
|
+
const publicPackages = [];
|
|
2202
|
+
const packageVersions = {};
|
|
2203
|
+
const excludeSet = new Set(excludePackages.map(normalizePackageName));
|
|
2204
|
+
for (const pkg of lockFile.packages) {
|
|
2205
|
+
if (excludeSet.has(normalizePackageName(pkg.name))) {
|
|
2206
|
+
continue;
|
|
2207
|
+
}
|
|
2208
|
+
packageVersions[pkg.name] = pkg.version;
|
|
2209
|
+
if (isPrivatePackageSource(pkg.source)) {
|
|
2210
|
+
privatePackages.push(pkg.name);
|
|
2211
|
+
} else {
|
|
2212
|
+
publicPackages.push(pkg.name);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
return { privatePackages, publicPackages, packageVersions };
|
|
2216
|
+
}
|
|
2217
|
+
function generateRuntimeRequirements(classification) {
|
|
2218
|
+
const lines = [
|
|
2219
|
+
"# Auto-generated requirements for runtime installation",
|
|
2220
|
+
"# Private packages are bundled separately and not listed here.",
|
|
2221
|
+
""
|
|
2222
|
+
];
|
|
2223
|
+
for (const pkgName of classification.publicPackages) {
|
|
2224
|
+
const version = classification.packageVersions[pkgName];
|
|
2225
|
+
if (version) {
|
|
2226
|
+
lines.push(`${pkgName}==${version}`);
|
|
2227
|
+
} else {
|
|
2228
|
+
lines.push(pkgName);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
return lines.join("\n");
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2055
2234
|
// src/manifest/python-selector.ts
|
|
2056
2235
|
function selectPython(constraints, available) {
|
|
2057
2236
|
const warnings = [];
|
|
@@ -2234,9 +2413,15 @@ export {
|
|
|
2234
2413
|
UvConfigSchema,
|
|
2235
2414
|
UvConfigWorkspaceSchema,
|
|
2236
2415
|
UvIndexEntrySchema,
|
|
2416
|
+
classifyPackages,
|
|
2237
2417
|
containsAppOrHandler,
|
|
2238
2418
|
createMinimalManifest,
|
|
2239
2419
|
discoverPythonPackage,
|
|
2420
|
+
generateRuntimeRequirements,
|
|
2421
|
+
isPrivatePackageSource,
|
|
2422
|
+
normalizePackageName,
|
|
2423
|
+
parseUvLock,
|
|
2424
|
+
scanDistributions,
|
|
2240
2425
|
selectPython,
|
|
2241
2426
|
stringifyManifest
|
|
2242
2427
|
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installed distribution metadata scanning.
|
|
3
|
+
*
|
|
4
|
+
* Scans a site-packages directory for .dist-info subdirectories and parses
|
|
5
|
+
* their metadata using WASM-based parsers.
|
|
6
|
+
*
|
|
7
|
+
* Nomenclature strives to follow that of Python's importlib.metadata module:
|
|
8
|
+
* https://docs.python.org/3/library/importlib.metadata.html
|
|
9
|
+
*/
|
|
10
|
+
/** A file record from a RECORD file (analogous to importlib.metadata.PackagePath). */
|
|
11
|
+
export interface PackagePath {
|
|
12
|
+
path: string;
|
|
13
|
+
hash?: string;
|
|
14
|
+
size?: bigint;
|
|
15
|
+
}
|
|
16
|
+
/** PEP 610 direct URL origin info (analogous to importlib.metadata.Distribution.origin). */
|
|
17
|
+
export type DirectUrlInfo = {
|
|
18
|
+
tag: 'local-directory';
|
|
19
|
+
val: {
|
|
20
|
+
url: string;
|
|
21
|
+
editable: boolean;
|
|
22
|
+
};
|
|
23
|
+
} | {
|
|
24
|
+
tag: 'archive';
|
|
25
|
+
val: {
|
|
26
|
+
url: string;
|
|
27
|
+
hash?: string;
|
|
28
|
+
};
|
|
29
|
+
} | {
|
|
30
|
+
tag: 'vcs';
|
|
31
|
+
val: {
|
|
32
|
+
url: string;
|
|
33
|
+
vcs: string;
|
|
34
|
+
commitId?: string;
|
|
35
|
+
requestedRevision?: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* An installed distribution parsed from a .dist-info directory.
|
|
40
|
+
* Analogous to importlib.metadata.Distribution.
|
|
41
|
+
*/
|
|
42
|
+
export interface Distribution {
|
|
43
|
+
/** Normalized package name (PEP 503). */
|
|
44
|
+
name: string;
|
|
45
|
+
/** Package version string. */
|
|
46
|
+
version: string;
|
|
47
|
+
/** Metadata version (e.g. "2.1", "2.3"). */
|
|
48
|
+
metadataVersion: string;
|
|
49
|
+
/** One-line summary. */
|
|
50
|
+
summary?: string;
|
|
51
|
+
/** Full description. */
|
|
52
|
+
description?: string;
|
|
53
|
+
/** Description content type (e.g. "text/markdown"). */
|
|
54
|
+
descriptionContentType?: string;
|
|
55
|
+
/** PEP 508 dependency specifiers (analogous to importlib.metadata.requires()). */
|
|
56
|
+
requiresDist: string[];
|
|
57
|
+
/** Python version requirement (e.g. ">=3.8"). */
|
|
58
|
+
requiresPython?: string;
|
|
59
|
+
/** Extra names provided by this distribution. */
|
|
60
|
+
providesExtra: string[];
|
|
61
|
+
/** Author name. */
|
|
62
|
+
author?: string;
|
|
63
|
+
/** Author email. */
|
|
64
|
+
authorEmail?: string;
|
|
65
|
+
/** Maintainer name. */
|
|
66
|
+
maintainer?: string;
|
|
67
|
+
/** Maintainer email. */
|
|
68
|
+
maintainerEmail?: string;
|
|
69
|
+
/** License text. */
|
|
70
|
+
license?: string;
|
|
71
|
+
/** SPDX license expression. */
|
|
72
|
+
licenseExpression?: string;
|
|
73
|
+
/** Trove classifiers. */
|
|
74
|
+
classifiers: string[];
|
|
75
|
+
/** Home page URL. */
|
|
76
|
+
homePage?: string;
|
|
77
|
+
/** Project URLs as [label, url] pairs. */
|
|
78
|
+
projectUrls: [string, string][];
|
|
79
|
+
/** Supported platforms. */
|
|
80
|
+
platforms: string[];
|
|
81
|
+
/** Dynamic metadata fields. */
|
|
82
|
+
dynamic: string[];
|
|
83
|
+
/** Installed files from RECORD (analogous to importlib.metadata.files()). */
|
|
84
|
+
files: PackagePath[];
|
|
85
|
+
/** PEP 610 origin info (analogous to importlib.metadata.Distribution.origin). */
|
|
86
|
+
origin?: DirectUrlInfo;
|
|
87
|
+
/** Installer tool name (from INSTALLER file). */
|
|
88
|
+
installer?: string;
|
|
89
|
+
}
|
|
90
|
+
/** Map of normalized package name to distribution info. */
|
|
91
|
+
export type DistributionIndex = Map<string, Distribution>;
|
|
92
|
+
/**
|
|
93
|
+
* Scan a site-packages directory for installed distributions.
|
|
94
|
+
*
|
|
95
|
+
* Reads .dist-info directories and parses their METADATA, RECORD,
|
|
96
|
+
* direct_url.json, and INSTALLER files.
|
|
97
|
+
*
|
|
98
|
+
* Analogous to importlib.metadata.distributions() but returns an indexed map.
|
|
99
|
+
*
|
|
100
|
+
* @param sitePackagesDir - Absolute path to a site-packages directory
|
|
101
|
+
* @returns Map of normalized package name to distribution info
|
|
102
|
+
*/
|
|
103
|
+
export declare function scanDistributions(sitePackagesDir: string): Promise<DistributionIndex>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A source of a package in a uv.lock file
|
|
3
|
+
*/
|
|
4
|
+
export interface UvLockPackageSource {
|
|
5
|
+
registry?: string;
|
|
6
|
+
url?: string;
|
|
7
|
+
git?: string;
|
|
8
|
+
path?: string;
|
|
9
|
+
editable?: string;
|
|
10
|
+
virtual?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A package entry from a parsed uv.lock file.
|
|
14
|
+
*/
|
|
15
|
+
export interface UvLockPackage {
|
|
16
|
+
name: string;
|
|
17
|
+
version: string;
|
|
18
|
+
source?: UvLockPackageSource;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parsed uv.lock file structure.
|
|
22
|
+
*/
|
|
23
|
+
export interface UvLockFile {
|
|
24
|
+
version?: number;
|
|
25
|
+
packages: UvLockPackage[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse the contents of a uv.lock file.
|
|
29
|
+
*
|
|
30
|
+
* @param content - The raw content of the uv.lock file
|
|
31
|
+
* @param path - Optional path to the file for error reporting
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseUvLock(content: string, path?: string): UvLockFile;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a package source indicates it's a private package.
|
|
36
|
+
*
|
|
37
|
+
* Private packages are those from:
|
|
38
|
+
* - Git repositories
|
|
39
|
+
* - Local file paths
|
|
40
|
+
* - Editable installs
|
|
41
|
+
* - Direct URLs
|
|
42
|
+
* - Non-PyPI registry URLs (private PyPI mirrors, custom indexes)
|
|
43
|
+
*/
|
|
44
|
+
export declare function isPrivatePackageSource(source: UvLockPackageSource | undefined): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Result of classifying packages from a uv.lock file.
|
|
47
|
+
*/
|
|
48
|
+
export interface PackageClassification {
|
|
49
|
+
privatePackages: string[];
|
|
50
|
+
publicPackages: string[];
|
|
51
|
+
packageVersions: Record<string, string>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Normalize a Python package name according to PEP 503.
|
|
55
|
+
*/
|
|
56
|
+
export declare function normalizePackageName(name: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Options for classifying packages.
|
|
59
|
+
*/
|
|
60
|
+
export interface ClassifyPackagesOptions {
|
|
61
|
+
lockFile: UvLockFile;
|
|
62
|
+
excludePackages?: string[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Classify packages from a uv.lock file into private and public categories.
|
|
66
|
+
*
|
|
67
|
+
* This is used for determining which packages can be installed from PyPI
|
|
68
|
+
* at runtime vs. which must be bundled with the deployment.
|
|
69
|
+
*/
|
|
70
|
+
export declare function classifyPackages(options: ClassifyPackagesOptions): PackageClassification;
|
|
71
|
+
/**
|
|
72
|
+
* Generate requirements.txt content for runtime installation.
|
|
73
|
+
*
|
|
74
|
+
* Only includes public packages that will be installed at runtime from PyPI.
|
|
75
|
+
* Private packages should be bundled separately.
|
|
76
|
+
*/
|
|
77
|
+
export declare function generateRuntimeRequirements(classification: PackageClassification): string;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,18 +1,78 @@
|
|
|
1
1
|
// world root:component/root
|
|
2
|
+
export interface RecordEntry {
|
|
3
|
+
path: string,
|
|
4
|
+
hash?: string,
|
|
5
|
+
size?: bigint,
|
|
6
|
+
}
|
|
7
|
+
export interface DistMetadata {
|
|
8
|
+
metadataVersion: string,
|
|
9
|
+
name: string,
|
|
10
|
+
version: string,
|
|
11
|
+
summary?: string,
|
|
12
|
+
description?: string,
|
|
13
|
+
descriptionContentType?: string,
|
|
14
|
+
requiresDist: Array<string>,
|
|
15
|
+
requiresPython?: string,
|
|
16
|
+
providesExtra: Array<string>,
|
|
17
|
+
author?: string,
|
|
18
|
+
authorEmail?: string,
|
|
19
|
+
maintainer?: string,
|
|
20
|
+
maintainerEmail?: string,
|
|
21
|
+
license?: string,
|
|
22
|
+
licenseExpression?: string,
|
|
23
|
+
classifiers: Array<string>,
|
|
24
|
+
homePage?: string,
|
|
25
|
+
projectUrls: Array<[string, string]>,
|
|
26
|
+
platforms: Array<string>,
|
|
27
|
+
dynamic: Array<string>,
|
|
28
|
+
}
|
|
29
|
+
export interface DirUrlInfo {
|
|
30
|
+
url: string,
|
|
31
|
+
editable: boolean,
|
|
32
|
+
}
|
|
33
|
+
export interface ArchiveUrlInfo {
|
|
34
|
+
url: string,
|
|
35
|
+
hash?: string,
|
|
36
|
+
}
|
|
37
|
+
export interface VcsUrlInfo {
|
|
38
|
+
url: string,
|
|
39
|
+
vcs: string,
|
|
40
|
+
commitId?: string,
|
|
41
|
+
requestedRevision?: string,
|
|
42
|
+
}
|
|
43
|
+
export type DirectUrlInfo = DirectUrlInfoLocalDirectory | DirectUrlInfoArchive | DirectUrlInfoVcs;
|
|
44
|
+
export interface DirectUrlInfoLocalDirectory {
|
|
45
|
+
tag: 'local-directory',
|
|
46
|
+
val: DirUrlInfo,
|
|
47
|
+
}
|
|
48
|
+
export interface DirectUrlInfoArchive {
|
|
49
|
+
tag: 'archive',
|
|
50
|
+
val: ArchiveUrlInfo,
|
|
51
|
+
}
|
|
52
|
+
export interface DirectUrlInfoVcs {
|
|
53
|
+
tag: 'vcs',
|
|
54
|
+
val: VcsUrlInfo,
|
|
55
|
+
}
|
|
2
56
|
import type * as WasiCliEnvironment from './interfaces/wasi-cli-environment.js'; // wasi:cli/environment@0.2.6
|
|
3
57
|
import type * as WasiCliExit from './interfaces/wasi-cli-exit.js'; // wasi:cli/exit@0.2.6
|
|
4
58
|
import type * as WasiCliStderr from './interfaces/wasi-cli-stderr.js'; // wasi:cli/stderr@0.2.6
|
|
5
59
|
import type * as WasiIoError from './interfaces/wasi-io-error.js'; // wasi:io/error@0.2.6
|
|
6
60
|
import type * as WasiIoStreams from './interfaces/wasi-io-streams.js'; // wasi:io/streams@0.2.6
|
|
61
|
+
import type * as WasiRandomInsecureSeed from './interfaces/wasi-random-insecure-seed.js'; // wasi:random/insecure-seed@0.2.6
|
|
7
62
|
export interface ImportObject {
|
|
8
63
|
'wasi:cli/environment@0.2.6': typeof WasiCliEnvironment,
|
|
9
64
|
'wasi:cli/exit@0.2.6': typeof WasiCliExit,
|
|
10
65
|
'wasi:cli/stderr@0.2.6': typeof WasiCliStderr,
|
|
11
66
|
'wasi:io/error@0.2.6': typeof WasiIoError,
|
|
12
67
|
'wasi:io/streams@0.2.6': typeof WasiIoStreams,
|
|
68
|
+
'wasi:random/insecure-seed@0.2.6': typeof WasiRandomInsecureSeed,
|
|
13
69
|
}
|
|
14
70
|
export interface Root {
|
|
15
71
|
containsAppOrHandler(source: string): boolean,
|
|
72
|
+
parseDistMetadata(content: Uint8Array): DistMetadata,
|
|
73
|
+
parseRecord(content: string): Array<RecordEntry>,
|
|
74
|
+
parseDirectUrl(content: string): DirectUrlInfo,
|
|
75
|
+
normalizePackageName(name: string): string,
|
|
16
76
|
}
|
|
17
77
|
|
|
18
78
|
/**
|