furu 0.0.2__tar.gz → 0.0.3__tar.gz
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.
- {furu-0.0.2 → furu-0.0.3}/PKG-INFO +14 -1
- {furu-0.0.2 → furu-0.0.3}/README.md +13 -0
- {furu-0.0.2 → furu-0.0.3}/pyproject.toml +1 -1
- {furu-0.0.2 → furu-0.0.3}/src/furu/__init__.py +3 -1
- {furu-0.0.2 → furu-0.0.3}/src/furu/config.py +8 -2
- furu-0.0.3/src/furu/core/__init__.py +4 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/core/furu.py +427 -66
- furu-0.0.2/src/furu/dashboard/frontend/dist/assets/index-CbdDfSOZ.css → furu-0.0.3/src/furu/dashboard/frontend/dist/assets/index-BXAIKNNr.css +1 -1
- furu-0.0.2/src/furu/dashboard/frontend/dist/assets/index-DDv_TYB_.js → furu-0.0.3/src/furu/dashboard/frontend/dist/assets/index-DS3FsqcY.js +3 -3
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/frontend/dist/index.html +2 -2
- {furu-0.0.2 → furu-0.0.3}/src/furu/errors.py +47 -5
- {furu-0.0.2 → furu-0.0.3}/src/furu/migration.py +8 -4
- {furu-0.0.2 → furu-0.0.3}/src/furu/serialization/serializer.py +40 -2
- {furu-0.0.2 → furu-0.0.3}/src/furu/storage/metadata.py +17 -5
- {furu-0.0.2 → furu-0.0.3}/src/furu/storage/state.py +44 -6
- furu-0.0.2/src/furu/core/__init__.py +0 -4
- {furu-0.0.2 → furu-0.0.3}/src/furu/adapters/__init__.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/adapters/submitit.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/core/list.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/__init__.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/__main__.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/api/__init__.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/api/models.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/api/routes.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/frontend/dist/favicon.svg +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/main.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/dashboard/scanner.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/migrate.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/runtime/__init__.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/runtime/env.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/runtime/logging.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/runtime/tracebacks.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/serialization/__init__.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/serialization/migrations.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/storage/__init__.py +0 -0
- {furu-0.0.2 → furu-0.0.3}/src/furu/storage/migration.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: furu
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: Cacheable, nested pipelines for Python. Define computations as configs; furu handles caching, state tracking, and result reuse across runs.
|
|
5
5
|
Author: Herman Brunborg
|
|
6
6
|
Author-email: Herman Brunborg <herman@brunborg.com>
|
|
@@ -336,6 +336,17 @@ except FuruLockNotAcquired:
|
|
|
336
336
|
print("Could not acquire lock")
|
|
337
337
|
```
|
|
338
338
|
|
|
339
|
+
By default, failed artifacts are retried on the next `load_or_create()` call. Set
|
|
340
|
+
`FURU_RETRY_FAILED=0` or pass `retry_failed=False` to keep failures sticky.
|
|
341
|
+
|
|
342
|
+
`FURU_MAX_WAIT_SECS` overrides the per-class `_max_wait_time_sec` (default 600s)
|
|
343
|
+
timeout used when waiting for compute locks before raising `FuruWaitTimeout`.
|
|
344
|
+
|
|
345
|
+
Failures during metadata collection or signal handler setup (before `_create()`
|
|
346
|
+
runs) raise `FuruComputeError` with the original exception attached. These
|
|
347
|
+
failures still mark the attempt as failed and record details in `state.json`
|
|
348
|
+
and `furu.log`.
|
|
349
|
+
|
|
339
350
|
## Submitit Integration
|
|
340
351
|
|
|
341
352
|
Run computations on SLURM clusters via [submitit](https://github.com/facebookincubator/submitit):
|
|
@@ -415,7 +426,9 @@ The `/api/experiments` endpoint supports:
|
|
|
415
426
|
| `FURU_LOG_LEVEL` | `INFO` | Console verbosity (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |
|
|
416
427
|
| `FURU_IGNORE_DIFF` | `false` | Skip embedding git diff in metadata |
|
|
417
428
|
| `FURU_ALWAYS_RERUN` | `""` | Comma-separated class qualnames to always rerun (use `ALL` to bypass cache globally; cannot combine with other entries; entries must be importable) |
|
|
429
|
+
| `FURU_RETRY_FAILED` | `true` | Retry failed artifacts by default (set to `0` to keep failures sticky) |
|
|
418
430
|
| `FURU_POLL_INTERVAL_SECS` | `10` | Polling interval for queued/running jobs |
|
|
431
|
+
| `FURU_MAX_WAIT_SECS` | unset | Override wait timeout (falls back to `_max_wait_time_sec`, default 600s) |
|
|
419
432
|
| `FURU_WAIT_LOG_EVERY_SECS` | `10` | Interval between "waiting" log messages |
|
|
420
433
|
| `FURU_STALE_AFTER_SECS` | `1800` | Consider running jobs stale after this duration |
|
|
421
434
|
| `FURU_LEASE_SECS` | `120` | Compute lock lease duration |
|
|
@@ -317,6 +317,17 @@ except FuruLockNotAcquired:
|
|
|
317
317
|
print("Could not acquire lock")
|
|
318
318
|
```
|
|
319
319
|
|
|
320
|
+
By default, failed artifacts are retried on the next `load_or_create()` call. Set
|
|
321
|
+
`FURU_RETRY_FAILED=0` or pass `retry_failed=False` to keep failures sticky.
|
|
322
|
+
|
|
323
|
+
`FURU_MAX_WAIT_SECS` overrides the per-class `_max_wait_time_sec` (default 600s)
|
|
324
|
+
timeout used when waiting for compute locks before raising `FuruWaitTimeout`.
|
|
325
|
+
|
|
326
|
+
Failures during metadata collection or signal handler setup (before `_create()`
|
|
327
|
+
runs) raise `FuruComputeError` with the original exception attached. These
|
|
328
|
+
failures still mark the attempt as failed and record details in `state.json`
|
|
329
|
+
and `furu.log`.
|
|
330
|
+
|
|
320
331
|
## Submitit Integration
|
|
321
332
|
|
|
322
333
|
Run computations on SLURM clusters via [submitit](https://github.com/facebookincubator/submitit):
|
|
@@ -396,7 +407,9 @@ The `/api/experiments` endpoint supports:
|
|
|
396
407
|
| `FURU_LOG_LEVEL` | `INFO` | Console verbosity (`DEBUG`, `INFO`, `WARNING`, `ERROR`) |
|
|
397
408
|
| `FURU_IGNORE_DIFF` | `false` | Skip embedding git diff in metadata |
|
|
398
409
|
| `FURU_ALWAYS_RERUN` | `""` | Comma-separated class qualnames to always rerun (use `ALL` to bypass cache globally; cannot combine with other entries; entries must be importable) |
|
|
410
|
+
| `FURU_RETRY_FAILED` | `true` | Retry failed artifacts by default (set to `0` to keep failures sticky) |
|
|
399
411
|
| `FURU_POLL_INTERVAL_SECS` | `10` | Polling interval for queued/running jobs |
|
|
412
|
+
| `FURU_MAX_WAIT_SECS` | unset | Override wait timeout (falls back to `_max_wait_time_sec`, default 600s) |
|
|
400
413
|
| `FURU_WAIT_LOG_EVERY_SECS` | `10` | Interval between "waiting" log messages |
|
|
401
414
|
| `FURU_STALE_AFTER_SECS` | `1800` | Consider running jobs stale after this duration |
|
|
402
415
|
| `FURU_LEASE_SECS` | `120` | Compute lock lease duration |
|
|
@@ -13,7 +13,7 @@ __version__ = version("furu")
|
|
|
13
13
|
|
|
14
14
|
from .config import FURU_CONFIG, FuruConfig, get_furu_root, set_furu_root
|
|
15
15
|
from .adapters import SubmititAdapter
|
|
16
|
-
from .core import Furu, FuruList
|
|
16
|
+
from .core import DependencyChzSpec, DependencySpec, Furu, FuruList
|
|
17
17
|
from .errors import (
|
|
18
18
|
FuruComputeError,
|
|
19
19
|
FuruError,
|
|
@@ -56,6 +56,8 @@ __all__ = [
|
|
|
56
56
|
"FuruMigrationRequired",
|
|
57
57
|
"FuruSerializer",
|
|
58
58
|
"FuruWaitTimeout",
|
|
59
|
+
"DependencyChzSpec",
|
|
60
|
+
"DependencySpec",
|
|
59
61
|
"MISSING",
|
|
60
62
|
"migrate",
|
|
61
63
|
"NamespacePair",
|
|
@@ -22,12 +22,19 @@ class FuruConfig:
|
|
|
22
22
|
self.poll_interval = float(os.getenv("FURU_POLL_INTERVAL_SECS", "10"))
|
|
23
23
|
self.wait_log_every_sec = float(os.getenv("FURU_WAIT_LOG_EVERY_SECS", "10"))
|
|
24
24
|
self.stale_timeout = float(os.getenv("FURU_STALE_AFTER_SECS", str(30 * 60)))
|
|
25
|
+
max_wait_env = os.getenv("FURU_MAX_WAIT_SECS")
|
|
26
|
+
self.max_wait_time_sec = float(max_wait_env) if max_wait_env else None
|
|
25
27
|
self.lease_duration_sec = float(os.getenv("FURU_LEASE_SECS", "120"))
|
|
26
28
|
hb = os.getenv("FURU_HEARTBEAT_SECS")
|
|
27
29
|
self.heartbeat_interval_sec = (
|
|
28
30
|
float(hb) if hb is not None else max(1.0, self.lease_duration_sec / 3.0)
|
|
29
31
|
)
|
|
30
32
|
self.max_requeues = int(os.getenv("FURU_PREEMPT_MAX", "5"))
|
|
33
|
+
self.retry_failed = os.getenv("FURU_RETRY_FAILED", "1").lower() in {
|
|
34
|
+
"1",
|
|
35
|
+
"true",
|
|
36
|
+
"yes",
|
|
37
|
+
}
|
|
31
38
|
self.ignore_git_diff = os.getenv("FURU_IGNORE_DIFF", "0").lower() in {
|
|
32
39
|
"1",
|
|
33
40
|
"true",
|
|
@@ -151,8 +158,7 @@ class FuruConfig:
|
|
|
151
158
|
value = getattr(target, attr, missing_sentinel)
|
|
152
159
|
if value is missing_sentinel:
|
|
153
160
|
raise ValueError(
|
|
154
|
-
"FURU_ALWAYS_RERUN entry does not exist: "
|
|
155
|
-
f"{namespace!r}"
|
|
161
|
+
f"FURU_ALWAYS_RERUN entry does not exist: {namespace!r}"
|
|
156
162
|
)
|
|
157
163
|
target = value
|
|
158
164
|
|