pyfig 0.5.0 → 0.6.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/config.js CHANGED
@@ -1,14 +1,12 @@
1
1
  import path from 'node:path';
2
2
  import * as envPaths from 'env-paths';
3
- import semver from 'semver';
3
+ import { isValidPep440Specifier, pep440VersionSatisfies, } from './pep440.js';
4
4
  import { resolveProjectRoot } from './project-root.js';
5
- import { isValidPythonSpecifier, pythonVersionSatisfies } from './python-version.js';
6
5
  export const DEFAULT_REQUIRES_PYTHON = '>=3.10,<4';
7
6
  export const DEFAULT_MANAGED_PYTHON = '3.12';
8
- export const DEFAULT_UV_VERSION = '0.13.6';
9
7
  // External uv only needs to support the command and isolation flags Pyfig uses.
10
- // Keep that compatibility floor separate from the newer version Pyfig installs.
11
- export const DEFAULT_UV_RANGE = '>=0.10.0 <1.0.0';
8
+ // The installer resolves the greatest published release allowed by this policy.
9
+ export const DEFAULT_REQUIRES_UV = '>=0.10,<1';
12
10
  const DEFAULT_PROBE_TIMEOUT_MS = 10_000;
13
11
  const DEFAULT_INSTALL_TIMEOUT_MS = 10 * 60_000;
14
12
  const DEFAULT_DOWNLOAD_TIMEOUT_MS = 5 * 60_000;
@@ -28,14 +26,12 @@ export function resolveOptions(options = {}) {
28
26
  const env = { ...(options.env ?? process.env) };
29
27
  const requiresPython = options.requiresPython ??
30
28
  env['PYFIG_REQUIRES_PYTHON'] ?? DEFAULT_REQUIRES_PYTHON;
31
- const uvRange = options.uvRange ?? env['PYFIG_UV_RANGE'] ?? DEFAULT_UV_RANGE;
32
- assertPythonSpecifier(requiresPython);
33
- assertRange('uv', uvRange);
29
+ const requiresUv = options.requiresUv ?? env['PYFIG_REQUIRES_UV'] ?? DEFAULT_REQUIRES_UV;
30
+ assertPep440Specifier('requires-python', requiresPython);
31
+ assertPep440Specifier('requires-uv', requiresUv);
34
32
  const managedPython = options.managedPython ??
35
33
  env['PYFIG_MANAGED_PYTHON'] ?? DEFAULT_MANAGED_PYTHON;
36
- const uvVersion = options.uvVersion ?? env['PYFIG_UV_VERSION'] ?? DEFAULT_UV_VERSION;
37
34
  assertManagedPythonRequest(managedPython, requiresPython);
38
- assertUvVersion(uvVersion, uvRange);
39
35
  const probeTimeoutMs = resolveDuration('probeTimeoutMs', options.probeTimeoutMs, env['PYFIG_PROBE_TIMEOUT_MS'], DEFAULT_PROBE_TIMEOUT_MS);
40
36
  const installTimeoutMs = resolveDuration('installTimeoutMs', options.installTimeoutMs, env['PYFIG_INSTALL_TIMEOUT_MS'], DEFAULT_INSTALL_TIMEOUT_MS);
41
37
  const downloadTimeoutMs = resolveDuration('downloadTimeoutMs', options.downloadTimeoutMs, env['PYFIG_DOWNLOAD_TIMEOUT_MS'], DEFAULT_DOWNLOAD_TIMEOUT_MS);
@@ -53,8 +49,7 @@ export function resolveOptions(options = {}) {
53
49
  python: options.python ?? env['PYFIG_PYTHON'] ?? '',
54
50
  requiresPython,
55
51
  managedPython,
56
- uvVersion,
57
- uvRange,
52
+ requiresUv,
58
53
  requireEmbedding: options.requireEmbedding ?? parseBoolean(env['PYFIG_REQUIRE_EMBEDDING'], false),
59
54
  requireGil: options.requireGil ?? parseBoolean(env['PYFIG_REQUIRE_GIL'], false),
60
55
  autoInstall,
@@ -81,22 +76,9 @@ export function uvEnvironment(options) {
81
76
  UV_NO_CONFIG: '1',
82
77
  };
83
78
  }
84
- function assertRange(tool, range) {
85
- if (!semver.validRange(range)) {
86
- throw new TypeError(`Invalid ${tool} SemVer range: ${range}`);
87
- }
88
- }
89
- function assertUvVersion(version, range) {
90
- if (!semver.valid(version)) {
91
- throw new TypeError(`Invalid exact uv version: ${version}`);
92
- }
93
- if (!semver.satisfies(version, range)) {
94
- throw new TypeError(`Pinned uv ${version} does not satisfy supported range ${range}.`);
95
- }
96
- }
97
- function assertPythonSpecifier(specifier) {
98
- if (!isValidPythonSpecifier(specifier)) {
99
- throw new TypeError(`Invalid requires-python PEP 440 specifier: ${specifier}`);
79
+ function assertPep440Specifier(name, specifier) {
80
+ if (!isValidPep440Specifier(specifier)) {
81
+ throw new TypeError(`Invalid ${name} PEP 440 specifier: ${specifier}`);
100
82
  }
101
83
  }
102
84
  function assertManagedPythonRequest(request, requiresPython) {
@@ -105,7 +87,7 @@ function assertManagedPythonRequest(request, requiresPython) {
105
87
  }
106
88
  if (/^\d+\.\d+(?:\.\d+)?$/u.test(request)) {
107
89
  const normalized = request.split('.').length === 2 ? `${request}.0` : request;
108
- if (!pythonVersionSatisfies(normalized, requiresPython)) {
90
+ if (!pep440VersionSatisfies(normalized, requiresPython)) {
109
91
  throw new TypeError(`Managed Python ${request} cannot satisfy requires-python ${requiresPython}.`);
110
92
  }
111
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAC;AACtC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAErF,MAAM,CAAC,MAAM,uBAAuB,GAAG,WAAW,CAAC;AACnD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAC3C,gFAAgF;AAChF,gFAAgF;AAChF,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAElD,MAAM,wBAAwB,GAAG,MAAM,CAAC;AACxC,MAAM,0BAA0B,GAAG,EAAE,GAAG,MAAM,CAAC;AAC/C,MAAM,2BAA2B,GAAG,CAAC,GAAG,MAAM,CAAC;AAE/C,6EAA6E;AAC7E,+EAA+E;AAC/E,4BAA4B;AAC5B,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE;IAC7B,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAEzB,CAAC;IACF,MAAM,cAAc,GAAG,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;IACpF,IAAI,CAAC,cAAc;QAAE,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IAC3F,OAAO,cAAc,CAAC;AACxB,CAAC,CAAC,EAAE,CAAC;AA8DL,MAAM,UAAU,cAAc,CAAC,OAAO,GAAiB,EAAE;IACvD,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,GAAG,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;IAChD,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc;QAC3C,GAAG,CAAC,uBAAuB,CAAC,IAAI,uBAAuB,CAAC;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,GAAG,CAAC,gBAAgB,CAAC,IAAI,gBAAgB,CAAC;IAC7E,qBAAqB,CAAC,cAAc,CAAC,CAAC;IACtC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE3B,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa;QACzC,GAAG,CAAC,sBAAsB,CAAC,IAAI,sBAAsB,CAAC;IACxD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC,kBAAkB,CAAC,IAAI,kBAAkB,CAAC;IACrF,0BAA0B,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAC1D,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAEpC,MAAM,cAAc,GAAG,eAAe,CACpC,gBAAgB,EAChB,OAAO,CAAC,cAAc,EACtB,GAAG,CAAC,wBAAwB,CAAC,EAC7B,wBAAwB,CACzB,CAAC;IACF,MAAM,gBAAgB,GAAG,eAAe,CACtC,kBAAkB,EAClB,OAAO,CAAC,gBAAgB,EACxB,GAAG,CAAC,0BAA0B,CAAC,EAC/B,0BAA0B,CAC3B,CAAC;IACF,MAAM,iBAAiB,GAAG,eAAe,CACvC,mBAAmB,EACnB,OAAO,CAAC,iBAAiB,EACzB,GAAG,CAAC,2BAA2B,CAAC,EAChC,2BAA2B,CAC5B,CAAC;IACF,MAAM,qBAAqB,GAAG,eAAe,CAC3C,uBAAuB,EACvB,OAAO,CAAC,qBAAqB,EAC7B,GAAG,CAAC,+BAA+B,CAAC,EACpC,gBAAgB,GAAG,iBAAiB,GAAG,MAAM,CAC9C,CAAC;IACF,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,cAAc;QAC7B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC;QAC9B,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC;IACpD,MAAM,qBAAqB,GAAG,OAAO,CAAC,WAAW,IAAI,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,qBAAqB;QACvC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAqB,CAAC;QACrC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,YAAY,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,IAAI,CAAC,CAAC;IAEzF,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE;QACnD,cAAc;QACd,aAAa;QACb,SAAS;QACT,OAAO;QACP,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,IAAI,YAAY,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,KAAK,CAAC;QACjG,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC;QAC/E,WAAW;QACX,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,YAAY,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,WAAW,CAAC;QAC9F,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,YAAY,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC;QAClF,wBAAwB,EAAE,OAAO,CAAC,wBAAwB;YACxD,YAAY,CAAC,GAAG,CAAC,kCAAkC,CAAC,EAAE,WAAW,CAAC;QACpE,QAAQ;QACR,WAAW;QACX,cAAc;QACd,gBAAgB;QAChB,iBAAiB;QACjB,qBAAqB;QACrB,GAAG;KACJ,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,aAAa,CAAC,OAA6B;IACzD,OAAO;QACL,GAAG,OAAO,CAAC,GAAG;QACd,qBAAqB,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC;QAC5D,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC;QACrD,oBAAoB,EAAE,QAAQ;QAC9B,YAAY,EAAE,GAAG;KAClB,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,KAAa;IAC9C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,SAAS,CAAC,WAAW,IAAI,kBAAkB,KAAK,EAAE,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,OAAe,EAAE,KAAa;IACrD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,SAAS,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,SAAS,CAAC,aAAa,OAAO,qCAAqC,KAAK,GAAG,CAAC,CAAC;IACzF,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAiB;IAC9C,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,SAAS,CAAC,8CAA8C,SAAS,EAAE,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED,SAAS,0BAA0B,CAAC,OAAe,EAAE,cAAsB;IACzE,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,SAAS,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;QAC9E,IAAI,CAAC,sBAAsB,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,SAAS,CACjB,kBAAkB,OAAO,mCAAmC,cAAc,GAAG,CAC9E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CACtB,IAAY,EACZ,QAA4B,EAC5B,WAA+B,EAC/B,QAAgB,EAChB,SAAS,GAAG,KAAK;IAEjB,MAAM,KAAK,GAAG,QAAQ,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IACvF,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,OAAO,EAAE,CAAC;QACpD,MAAM,IAAI,SAAS,CAAC,GAAG,IAAI,YAAY,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,YAAY,WAAW,CAAC,CAAC;IACjG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CAAC,KAAyB,EAAE,QAAiB;IAChE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACnD,IAAI,sBAAsB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,MAAM,IAAI,SAAS,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { DEFAULT_MANAGED_PYTHON, DEFAULT_REQUIRES_PYTHON, DEFAULT_UV_RANGE, DEFAULT_UV_VERSION, } from './config.js';
1
+ export { DEFAULT_MANAGED_PYTHON, DEFAULT_REQUIRES_PYTHON, DEFAULT_REQUIRES_UV, } from './config.js';
2
2
  export type { PyfigOptions } from './config.js';
3
3
  export { createPyfig } from './client.js';
4
4
  export type { PyfigClient } from './client.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,MAAM,GACP,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EACL,OAAO,EACP,WAAW,GACZ,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,MAAM,GACP,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EACL,OAAO,EACP,WAAW,GACZ,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { DEFAULT_MANAGED_PYTHON, DEFAULT_REQUIRES_PYTHON, DEFAULT_UV_RANGE, DEFAULT_UV_VERSION, } from './config.js';
1
+ export { DEFAULT_MANAGED_PYTHON, DEFAULT_REQUIRES_PYTHON, DEFAULT_REQUIRES_UV, } from './config.js';
2
2
  export { createPyfig } from './client.js';
3
3
  export { resolveProjectRoot } from './project-root.js';
4
4
  export { ensureEnvironment, ensureUv, } from './provision.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAMvD,OAAO,EACL,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,OAAO,EACP,WAAW,GACZ,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAMvD,OAAO,EACL,iBAAiB,EACjB,QAAQ,GACT,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,OAAO,EACP,WAAW,GACZ,MAAM,cAAc,CAAC"}
@@ -0,0 +1,12 @@
1
+ /** Validate a PEP 440 version specifier used by a runtime policy. */
2
+ export declare function isValidPep440Specifier(specifier: string): boolean;
3
+ /** Normalize a PEP 440 version, or reject invalid input. */
4
+ export declare function normalizePep440Version(version: string): string | null;
5
+ /**
6
+ * Match a version using PEP 440 specifier-set behavior, including its
7
+ * pre-release fallback when the candidate set has no matching final release.
8
+ */
9
+ export declare function pep440VersionSatisfies(version: string, specifier: string): boolean;
10
+ /** Select the greatest PEP 440 version allowed by a specifier. */
11
+ export declare function maxPep440Version(versions: readonly string[], specifier: string): string | null;
12
+ //# sourceMappingURL=pep440.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pep440.d.ts","sourceRoot":"","sources":["../src/pep440.ts"],"names":[],"mappings":"AAOA,qEAAqE;AACrE,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,4DAA4D;AAC5D,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAElF;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,SAAS,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI,CAEf"}
package/dist/pep440.js ADDED
@@ -0,0 +1,21 @@
1
+ import { filter, maxSatisfying, valid as validPep440Version, validRange as validPep440Specifier, } from '@renovatebot/pep440';
2
+ /** Validate a PEP 440 version specifier used by a runtime policy. */
3
+ export function isValidPep440Specifier(specifier) {
4
+ return validPep440Specifier(specifier);
5
+ }
6
+ /** Normalize a PEP 440 version, or reject invalid input. */
7
+ export function normalizePep440Version(version) {
8
+ return validPep440Version(version);
9
+ }
10
+ /**
11
+ * Match a version using PEP 440 specifier-set behavior, including its
12
+ * pre-release fallback when the candidate set has no matching final release.
13
+ */
14
+ export function pep440VersionSatisfies(version, specifier) {
15
+ return filter([version], specifier).length === 1;
16
+ }
17
+ /** Select the greatest PEP 440 version allowed by a specifier. */
18
+ export function maxPep440Version(versions, specifier) {
19
+ return maxSatisfying([...versions], specifier);
20
+ }
21
+ //# sourceMappingURL=pep440.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pep440.js","sourceRoot":"","sources":["../src/pep440.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,KAAK,IAAI,kBAAkB,EAC3B,UAAU,IAAI,oBAAoB,GACnC,MAAM,qBAAqB,CAAC;AAE7B,qEAAqE;AACrE,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe,EAAE,SAAiB;IACvE,OAAO,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,gBAAgB,CAC9B,QAA2B,EAC3B,SAAiB;IAEjB,OAAO,aAAa,CAAC,CAAC,GAAG,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;AACjD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAGxE,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC7C;AAED,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AA+ED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,YAAY,CAAC,GACxF,OAAO,CAQT;AAED,wBAAsB,WAAW,CAC/B,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAe5B;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKlF;AAED,wBAAgB,OAAO,CACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,IAAI,CAQf"}
1
+ {"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAExE,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC7C;AAED,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AA+ED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,IAAI,CAAC,oBAAoB,EAAE,gBAAgB,GAAG,kBAAkB,GAAG,YAAY,CAAC,GACxF,OAAO,CAQT;AAED,wBAAsB,WAAW,CAC/B,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAe5B;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAKlF;AAED,wBAAgB,OAAO,CACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,IAAI,CAQf"}
package/dist/probes.js CHANGED
@@ -1,6 +1,5 @@
1
- import semver from 'semver';
1
+ import { normalizePep440Version, pep440VersionSatisfies } from './pep440.js';
2
2
  import { resolveExecutable, run } from './process.js';
3
- import { isValidPythonVersion, pythonVersionSatisfies } from './python-version.js';
4
3
  const PYTHON_PROBE = `
5
4
  import json
6
5
  import os
@@ -78,7 +77,7 @@ print(json.dumps({
78
77
  }))
79
78
  `;
80
79
  export function pythonSatisfiesPolicy(python, options) {
81
- return pythonVersionSatisfies(python.version, options.requiresPython) &&
80
+ return pep440VersionSatisfies(python.version, options.requiresPython) &&
82
81
  (!options.requireEmbedding || (python.implementation === 'cpython' &&
83
82
  python.embedding !== null &&
84
83
  pythonArchitectureMatchesRuntime(python))) &&
@@ -91,7 +90,7 @@ export async function probePython(candidate, options) {
91
90
  try {
92
91
  const { stdout } = run(executable, [...candidate.args, '-c', PYTHON_PROBE], options.env, options.probeTimeoutMs);
93
92
  const info = JSON.parse(stdout.trim());
94
- return isValidPythonVersion(info.version) ? info : null;
93
+ return normalizePep440Version(info.version) ? info : null;
95
94
  }
96
95
  catch {
97
96
  return null;
@@ -101,7 +100,7 @@ export async function findUv(options) {
101
100
  const configured = options.env['PYFIG_UV'] ?? 'uv';
102
101
  const executable = await resolveExecutable(configured, options.env);
103
102
  const uv = executable ? probeUv(executable, options) : null;
104
- return uv && semver.satisfies(uv.version, options.uvRange) ? uv : null;
103
+ return uv && pep440VersionSatisfies(uv.version, options.requiresUv) ? uv : null;
105
104
  }
106
105
  export function probeUv(executable, options) {
107
106
  try {
@@ -116,7 +115,7 @@ export function probeUv(executable, options) {
116
115
  function normalizeVersion(value) {
117
116
  if (!value)
118
117
  return null;
119
- return semver.valid(value) ?? semver.coerce(value)?.version ?? null;
118
+ return normalizePep440Version(value);
120
119
  }
121
120
  function pythonArchitectureMatchesRuntime(python) {
122
121
  const architecture = python.architecture.toLowerCase();
@@ -1 +1 @@
1
- {"version":3,"file":"probes.js","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"probes.js","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAqBA,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,aAAa,CAAC;AAUrB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,8EAA8E;AAC9E,wBAAsB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,GAAE,YAAiB,EAC1B,YAAY,GAAE,SAAS,MAAM,EAAO,EACpC,iBAAiB,GAAE,wBAA6B,GAC/C,OAAO,CAAC,iBAAiB,CAAC,CAe5B"}
1
+ {"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AAqBA,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAKL,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,aAAa,CAAC;AAUrB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,+EAA+E;IAC/E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED,8EAA8E;AAC9E,wBAAsB,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,GAAE,YAAiB,EAC1B,YAAY,GAAE,SAAS,MAAM,EAAO,EACpC,iBAAiB,GAAE,wBAA6B,GAC/C,OAAO,CAAC,iBAAiB,CAAC,CAe5B"}
package/dist/provision.js CHANGED
@@ -12,6 +12,7 @@ import { EnvHttpProxyAgent, fetch } from 'undici';
12
12
  import { resolveOptions, uvEnvironment, } from './config.js';
13
13
  import { withProvisioningLock } from './provision-lock.js';
14
14
  import { sanitizeUvEnvironment, uvCommandEnvironment } from './package-target.js';
15
+ import { maxPep440Version, normalizePep440Version, } from './pep440.js';
15
16
  import { findUv, probePython, probeUv, pythonSatisfiesPolicy, } from './probes.js';
16
17
  import { runAsync } from './process.js';
17
18
  import { canonicalPath, externalVirtualEnvironmentDirectories, pathsEqual, virtualEnvironmentDirectory, virtualEnvironmentPythonExecutable, } from './virtual-environment.js';
@@ -258,21 +259,30 @@ async function ensureUvResolved(options) {
258
259
  if (existing)
259
260
  return existing;
260
261
  if (!options.installUv) {
261
- throw new Error(`Compatible uv is unavailable (required ${options.uvRange}), and uv installation is disabled.`);
262
+ throw new Error(`Compatible uv is unavailable (requires-uv ${options.requiresUv}), and uv installation is disabled.`);
262
263
  }
263
- const installDir = uvInstallDirectory(options);
264
- const executable = uvExecutable(options);
264
+ const policyKey = createHash('sha256').update(options.requiresUv).digest('hex');
265
265
  return withProvisioningLock({
266
- key: `uv:${canonicalPath(installDir)}`,
266
+ key: `uv-policy:${canonicalPath(uvInstallRoot(options))}:${policyKey}`,
267
267
  timeoutMs: options.coordinationTimeoutMs,
268
268
  check: () => findAvailableUv(options),
269
269
  mutate: async () => {
270
- await installUv(installDir, options);
271
- const result = probeUv(executable, options);
272
- if (!result || result.version !== options.uvVersion) {
273
- throw new Error(`Expected managed uv ${options.uvVersion}, but the installed executable did not match.`);
274
- }
275
- return result;
270
+ const release = await resolveUvRelease(options);
271
+ const installDir = uvInstallDirectory(options, release.version);
272
+ const executable = uvExecutable(options, release.version);
273
+ return withProvisioningLock({
274
+ key: `uv-release:${canonicalPath(installDir)}`,
275
+ timeoutMs: options.coordinationTimeoutMs,
276
+ check: () => findAvailableUv(options),
277
+ mutate: async () => {
278
+ await installUv(installDir, release, options);
279
+ const result = probeUv(executable, options);
280
+ if (!result || result.version !== release.version) {
281
+ throw new Error(`Expected managed uv ${release.version}, but the installed executable did not match.`);
282
+ }
283
+ return result;
284
+ },
285
+ });
276
286
  },
277
287
  });
278
288
  }
@@ -280,8 +290,23 @@ async function findAvailableUv(options) {
280
290
  const external = await findUv(options);
281
291
  if (external)
282
292
  return external;
283
- const managed = probeUv(uvExecutable(options), options);
284
- return managed?.version === options.uvVersion ? managed : null;
293
+ return findManagedUv(options);
294
+ }
295
+ async function findManagedUv(options) {
296
+ const entries = await readdir(uvInstallRoot(options), { withFileTypes: true }).catch(() => []);
297
+ let versions = entries
298
+ .filter(entry => entry.isDirectory() && normalizePep440Version(entry.name) === entry.name)
299
+ .map(entry => entry.name);
300
+ while (versions.length > 0) {
301
+ const selected = maxPep440Version(versions, options.requiresUv);
302
+ if (!selected)
303
+ return null;
304
+ const candidate = probeUv(uvExecutable(options, selected), options);
305
+ if (candidate?.version === selected)
306
+ return candidate;
307
+ versions = versions.filter(version => version !== selected);
308
+ }
309
+ return null;
285
310
  }
286
311
  function normalizeDependencies(dependencies) {
287
312
  const normalized = dependencies.map((dependency) => dependency.trim());
@@ -349,15 +374,168 @@ async function virtualEnvironmentMatchesConfiguredPython(virtualEnvironment, opt
349
374
  : configured.executable;
350
375
  return pathsEqual(configuredBase, virtualEnvironment.baseExecutable);
351
376
  }
352
- function uvInstallDirectory(options) {
353
- return path.join(options.cacheDir, 'tools', 'uv', options.uvVersion);
377
+ const UV_RELEASE_PAGE_SIZE = 100;
378
+ const UV_RELEASE_MAX_PAGES = 20;
379
+ const UV_RELEASE_METADATA_TTL_MS = 24 * 60 * 60_000;
380
+ async function resolveUvRelease(options) {
381
+ const catalog = await ensureUvReleaseCatalog(options);
382
+ const asset = uvAsset();
383
+ const releases = catalog.releases.filter(release => release.assets.includes(asset) && release.assets.includes(`${asset}.sha256`));
384
+ const version = maxPep440Version(releases.map(release => release.version), options.requiresUv);
385
+ const release = releases.find(candidate => candidate.version === version);
386
+ if (!release) {
387
+ throw new Error(`No published uv release satisfies requires-uv ${options.requiresUv}.`);
388
+ }
389
+ return release;
390
+ }
391
+ async function ensureUvReleaseCatalog(options) {
392
+ const file = uvReleaseMetadataFile(options);
393
+ const stale = await readUvReleaseCatalog(file);
394
+ try {
395
+ return await withProvisioningLock({
396
+ key: `uv-metadata:${canonicalPath(file)}`,
397
+ timeoutMs: options.coordinationTimeoutMs,
398
+ check: () => readFreshUvReleaseCatalog(file),
399
+ mutate: async () => {
400
+ const catalog = await fetchUvReleaseCatalog(options);
401
+ await writeUvReleaseCatalog(file, catalog);
402
+ return catalog;
403
+ },
404
+ });
405
+ }
406
+ catch (error) {
407
+ const fallback = await readUvReleaseCatalog(file) ?? stale;
408
+ if (fallback)
409
+ return fallback;
410
+ throw error;
411
+ }
412
+ }
413
+ async function fetchUvReleaseCatalog(options) {
414
+ const dispatcher = proxyDispatcher(options.env);
415
+ const releases = new Map();
416
+ let exhausted = false;
417
+ try {
418
+ for (let page = 1; page <= UV_RELEASE_MAX_PAGES; page += 1) {
419
+ const text = await downloadText(`https://api.github.com/repos/astral-sh/uv/releases?per_page=${UV_RELEASE_PAGE_SIZE}&page=${page}`, options.downloadTimeoutMs, dispatcher, {
420
+ Accept: 'application/vnd.github+json',
421
+ 'User-Agent': 'pyfig',
422
+ 'X-GitHub-Api-Version': '2022-11-28',
423
+ });
424
+ const payload = JSON.parse(text);
425
+ if (!Array.isArray(payload)) {
426
+ throw new Error('GitHub returned invalid uv release metadata.');
427
+ }
428
+ for (const candidate of payload) {
429
+ if (!candidate || typeof candidate !== 'object')
430
+ continue;
431
+ const release = candidate;
432
+ if (release.draft === true || typeof release.tag_name !== 'string')
433
+ continue;
434
+ const assetNames = releaseAssetNames(release.assets);
435
+ const version = normalizePep440Version(release.tag_name);
436
+ if (version) {
437
+ releases.set(version, { assets: assetNames, tag: release.tag_name, version });
438
+ }
439
+ }
440
+ if (payload.length < UV_RELEASE_PAGE_SIZE) {
441
+ exhausted = true;
442
+ break;
443
+ }
444
+ }
445
+ }
446
+ finally {
447
+ await dispatcher?.close();
448
+ }
449
+ if (!exhausted) {
450
+ throw new Error(`uv release catalog exceeded ${UV_RELEASE_MAX_PAGES} pages.`);
451
+ }
452
+ if (releases.size === 0) {
453
+ throw new Error('GitHub returned no usable uv releases.');
454
+ }
455
+ return { fetchedAt: Date.now(), releases: [...releases.values()] };
456
+ }
457
+ async function readFreshUvReleaseCatalog(file) {
458
+ const catalog = await readUvReleaseCatalog(file);
459
+ if (!catalog)
460
+ return null;
461
+ const age = Date.now() - catalog.fetchedAt;
462
+ return age >= 0 && age < UV_RELEASE_METADATA_TTL_MS ? catalog : null;
463
+ }
464
+ async function readUvReleaseCatalog(file) {
465
+ try {
466
+ return parseUvReleaseCatalog(JSON.parse(await readFile(file, 'utf8')));
467
+ }
468
+ catch {
469
+ return null;
470
+ }
471
+ }
472
+ function parseUvReleaseCatalog(value) {
473
+ if (!value || typeof value !== 'object')
474
+ return null;
475
+ const catalog = value;
476
+ if (!Number.isSafeInteger(catalog.fetchedAt) || catalog.fetchedAt < 0 ||
477
+ !Array.isArray(catalog.releases)) {
478
+ return null;
479
+ }
480
+ const releases = [];
481
+ for (const value of catalog.releases) {
482
+ if (!value || typeof value !== 'object')
483
+ return null;
484
+ const release = value;
485
+ if (!Array.isArray(release.assets) ||
486
+ !release.assets.every(asset => typeof asset === 'string') ||
487
+ typeof release.tag !== 'string' ||
488
+ !/^[A-Za-z0-9][A-Za-z0-9._+-]*$/u.test(release.tag) ||
489
+ typeof release.version !== 'string' ||
490
+ normalizePep440Version(release.version) !== release.version) {
491
+ return null;
492
+ }
493
+ releases.push({
494
+ assets: release.assets,
495
+ tag: release.tag,
496
+ version: release.version,
497
+ });
498
+ }
499
+ return { fetchedAt: catalog.fetchedAt, releases };
500
+ }
501
+ async function writeUvReleaseCatalog(file, catalog) {
502
+ await mkdir(path.dirname(file), { recursive: true });
503
+ const staged = path.join(path.dirname(file), `.${path.basename(file)}.${process.pid}.${randomUUID()}.tmp`);
504
+ try {
505
+ await writeFile(staged, `${JSON.stringify(catalog)}\n`, { encoding: 'utf8', flag: 'wx' });
506
+ if (process.platform === 'win32')
507
+ await rm(file, { force: true });
508
+ await rename(staged, file);
509
+ }
510
+ finally {
511
+ await rm(staged, { force: true });
512
+ }
513
+ }
514
+ function uvReleaseMetadataFile(options) {
515
+ return path.join(options.cacheDir, 'metadata', 'uv-releases.json');
516
+ }
517
+ function releaseAssetNames(value) {
518
+ if (!Array.isArray(value))
519
+ return [];
520
+ return value.flatMap(entry => {
521
+ if (!entry || typeof entry !== 'object')
522
+ return [];
523
+ const name = entry.name;
524
+ return typeof name === 'string' ? [name] : [];
525
+ });
526
+ }
527
+ function uvInstallRoot(options) {
528
+ return path.join(options.cacheDir, 'tools', 'uv');
529
+ }
530
+ function uvInstallDirectory(options, version) {
531
+ return path.join(uvInstallRoot(options), version);
354
532
  }
355
- function uvExecutable(options) {
356
- return path.join(uvInstallDirectory(options), process.platform === 'win32' ? 'uv.exe' : 'uv');
533
+ function uvExecutable(options, version) {
534
+ return path.join(uvInstallDirectory(options, version), process.platform === 'win32' ? 'uv.exe' : 'uv');
357
535
  }
358
- async function installUv(installDir, options) {
536
+ async function installUv(installDir, release, options) {
359
537
  const asset = uvAsset();
360
- const baseUrl = `https://github.com/astral-sh/uv/releases/download/${options.uvVersion}`;
538
+ const baseUrl = `https://github.com/astral-sh/uv/releases/download/${release.tag}`;
361
539
  const temporary = await mkdtemp(path.join(os.tmpdir(), 'pyfig-uv-'));
362
540
  const dispatcher = proxyDispatcher(options.env);
363
541
  try {
@@ -373,7 +551,7 @@ async function installUv(installDir, options) {
373
551
  const source = await extractUvExecutable(archive, asset, extracted);
374
552
  if (!source)
375
553
  throw new Error(`uv archive did not contain the expected executable: ${asset}`);
376
- await publishUvAtomically(source, installDir, options);
554
+ await publishUvAtomically(source, installDir, release.version, options);
377
555
  }
378
556
  finally {
379
557
  await dispatcher?.close();
@@ -400,17 +578,17 @@ async function extractUvExecutable(archive, asset, destination) {
400
578
  await writeFile(source, matches[0][1], { flag: 'wx' });
401
579
  return source;
402
580
  }
403
- async function publishUvAtomically(source, installDir, options) {
581
+ async function publishUvAtomically(source, installDir, version, options) {
404
582
  await mkdir(installDir, { recursive: true });
405
- const executable = uvExecutable(options);
583
+ const executable = uvExecutable(options, version);
406
584
  const staged = path.join(installDir, `.${path.basename(executable)}.${process.pid}.${randomUUID()}.tmp`);
407
585
  try {
408
586
  await copyFile(source, staged);
409
587
  if (process.platform !== 'win32')
410
588
  await chmod(staged, 0o755);
411
589
  const stagedUv = probeUv(staged, options);
412
- if (!stagedUv || stagedUv.version !== options.uvVersion) {
413
- throw new Error(`Downloaded uv executable is not version ${options.uvVersion}.`);
590
+ if (!stagedUv || stagedUv.version !== version) {
591
+ throw new Error(`Downloaded uv executable is not version ${version}.`);
414
592
  }
415
593
  if (process.platform === 'win32')
416
594
  await rm(executable, { force: true });
@@ -448,9 +626,10 @@ async function download(url, destination, timeoutMs, dispatcher) {
448
626
  }
449
627
  await pipeline(Readable.fromWeb(response.body), createWriteStream(destination, { flags: 'wx' }));
450
628
  }
451
- async function downloadText(url, timeoutMs, dispatcher) {
629
+ async function downloadText(url, timeoutMs, dispatcher, headers) {
452
630
  const response = await fetch(url, {
453
631
  dispatcher,
632
+ headers,
454
633
  redirect: 'follow',
455
634
  signal: AbortSignal.timeout(timeoutMs),
456
635
  });