caffeinated-whale-cli 3.2.1__tar.gz → 3.3.0__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.
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/PKG-INFO +27 -2
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/README.md +26 -1
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/pyproject.toml +1 -1
- caffeinated_whale_cli-3.3.0/src/caffeinated_whale_cli/__init__.py +1 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/config.py +49 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/auto_inspect.py +8 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/config.py +35 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/inspect.py +12 -1
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/where.py +18 -1
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/cache.py +6 -1
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/completion_utils.py +13 -1
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/config_utils.py +60 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/db_utils.py +75 -14
- caffeinated_whale_cli-3.2.1/src/caffeinated_whale_cli/__init__.py +0 -1
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/LICENSE +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/setup.cfg +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/__main__.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/__init__.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/apps.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/axi.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/backup.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/console.html +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/doctor.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/init.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/inspect.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/label.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/list.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/logs.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/open.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/restart.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/restore.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/rm.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/rm_bench.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/rm_site.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/run.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/scale.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/self_update.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/serve.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/setup.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/start.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/status.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/stop.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/unlock.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/update.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/utils.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/where.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/__init__.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/apps.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/backup.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/bench_ops.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/cred_bridge.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/credbridge.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/docker.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/doctor.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/envelope.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/errors.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/exec_stream.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/fleet.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/init.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/label.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/list.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/logs.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/open.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/resolvers.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/restart.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/restore.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/rm.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/rm_bench.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/rm_site.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/run.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/scale.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/setup.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/start.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/status.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/stop.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/supervision.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/unlock.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/update.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/url.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/version.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/main.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/update_notice.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/__init__.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/agent_hooks.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/auto_inspect.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/bench_labels.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/bench_sites.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/console.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/cred_daemon.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/daemon_identity.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/docker_utils.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/port_utils.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/sendme_utils.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/shared_home.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/signals.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/startup.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/tips.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/toon.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/vscode_utils.py +0 -0
- {caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli.egg-info/SOURCES.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: caffeinated-whale-cli
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3.0
|
|
4
4
|
Summary: A CLI tool to help manage Frappe Docker instances.
|
|
5
5
|
Author-email: Christopher McKay <mckay.christopher73@outlook.com>
|
|
6
6
|
License: MIT
|
|
@@ -2027,7 +2027,7 @@ cwcli config [SUBCOMMAND]
|
|
|
2027
2027
|
|
|
2028
2028
|
##### `config show` - Show the Effective Configuration
|
|
2029
2029
|
|
|
2030
|
-
The one read for everything: the custom search paths, the auto-inspect settings together with live daemon state and boot-hook state, the credential-bridge state (enabled, daemon, transport, wired instances), the tips setting, and the config-file and cache-DB locations.
|
|
2030
|
+
The one read for everything: the cache on/off state (and whether `CWCLI_NO_CACHE` is overriding it), the custom search paths, the auto-inspect settings together with live daemon state and boot-hook state, the credential-bridge state (enabled, daemon, transport, wired instances), the tips setting, and the config-file and cache-DB locations.
|
|
2031
2031
|
|
|
2032
2032
|
```bash
|
|
2033
2033
|
cwcli config show
|
|
@@ -2095,6 +2095,31 @@ cwcli config cache [SUBCOMMAND]
|
|
|
2095
2095
|
- **`list [--json]`** - List all projects currently in the cache
|
|
2096
2096
|
- Example: `cwcli config cache list --json`
|
|
2097
2097
|
|
|
2098
|
+
- **`disable`** / **`enable`** - Turn the on-disk cache off entirely, or back on (the default)
|
|
2099
|
+
- Example: `cwcli config cache disable`
|
|
2100
|
+
- Example: `cwcli config cache enable`
|
|
2101
|
+
- See ["Disabling caching entirely"](#disabling-caching-entirely) below.
|
|
2102
|
+
|
|
2103
|
+
###### Disabling caching entirely
|
|
2104
|
+
|
|
2105
|
+
cwcli keeps an on-disk SQLite cache (under `~/.cwcli/cache`, or `$CWCLI_HOME/cache`) that read commands - `inspect`, `status`, `where`, `open`, the `apps` group, tab completion, and every `axi` read verb - work from, so they do not re-inspect a running instance every time.
|
|
2106
|
+
|
|
2107
|
+
You can turn it off entirely, in two equivalent ways:
|
|
2108
|
+
|
|
2109
|
+
- **Config key:** `cwcli config cache disable` sets `[cache] enabled = false` in the config file. `cwcli config cache enable` reverts it.
|
|
2110
|
+
- **Environment variable:** `CWCLI_NO_CACHE=1` disables caching for a single shell or CI job; `CWCLI_NO_CACHE=0` re-enables it. The environment variable **overrides** the config key, so you can force caching on or off for one invocation regardless of the persisted setting.
|
|
2111
|
+
|
|
2112
|
+
With caching disabled:
|
|
2113
|
+
|
|
2114
|
+
- Every read resolves **live**, as if a fresh `inspect` had just run - a stale cached row can never be served.
|
|
2115
|
+
- **Nothing** is written to or read from the cache DB, and a pre-existing cache file is left in place untouched, so re-enabling restores the previous behaviour.
|
|
2116
|
+
- Tab completion degrades gracefully to a live/empty lookup rather than serving stale names.
|
|
2117
|
+
- `auto-inspect` refuses to start (it exists only to keep the cache warm, which does nothing when caching is off).
|
|
2118
|
+
- Bench labels still work, because they are also stored in each bench's marker file.
|
|
2119
|
+
- Safety-critical commands (`rm`/`rm-site`'s backup step, `apps checkout`'s wrong-copy detection) get correct live data.
|
|
2120
|
+
|
|
2121
|
+
Because every read resolves live, commands are slower than with the cache warm - this is a correctness/isolation mode, not the everyday default.
|
|
2122
|
+
|
|
2098
2123
|
##### `config auto-inspect` - Automatic Project Inspection
|
|
2099
2124
|
|
|
2100
2125
|
Manages automatic background inspection of running Frappe projects to keep cached data fresh (tab completion, project status queries, and other commands that rely on cached data).
|
|
@@ -1987,7 +1987,7 @@ cwcli config [SUBCOMMAND]
|
|
|
1987
1987
|
|
|
1988
1988
|
##### `config show` - Show the Effective Configuration
|
|
1989
1989
|
|
|
1990
|
-
The one read for everything: the custom search paths, the auto-inspect settings together with live daemon state and boot-hook state, the credential-bridge state (enabled, daemon, transport, wired instances), the tips setting, and the config-file and cache-DB locations.
|
|
1990
|
+
The one read for everything: the cache on/off state (and whether `CWCLI_NO_CACHE` is overriding it), the custom search paths, the auto-inspect settings together with live daemon state and boot-hook state, the credential-bridge state (enabled, daemon, transport, wired instances), the tips setting, and the config-file and cache-DB locations.
|
|
1991
1991
|
|
|
1992
1992
|
```bash
|
|
1993
1993
|
cwcli config show
|
|
@@ -2055,6 +2055,31 @@ cwcli config cache [SUBCOMMAND]
|
|
|
2055
2055
|
- **`list [--json]`** - List all projects currently in the cache
|
|
2056
2056
|
- Example: `cwcli config cache list --json`
|
|
2057
2057
|
|
|
2058
|
+
- **`disable`** / **`enable`** - Turn the on-disk cache off entirely, or back on (the default)
|
|
2059
|
+
- Example: `cwcli config cache disable`
|
|
2060
|
+
- Example: `cwcli config cache enable`
|
|
2061
|
+
- See ["Disabling caching entirely"](#disabling-caching-entirely) below.
|
|
2062
|
+
|
|
2063
|
+
###### Disabling caching entirely
|
|
2064
|
+
|
|
2065
|
+
cwcli keeps an on-disk SQLite cache (under `~/.cwcli/cache`, or `$CWCLI_HOME/cache`) that read commands - `inspect`, `status`, `where`, `open`, the `apps` group, tab completion, and every `axi` read verb - work from, so they do not re-inspect a running instance every time.
|
|
2066
|
+
|
|
2067
|
+
You can turn it off entirely, in two equivalent ways:
|
|
2068
|
+
|
|
2069
|
+
- **Config key:** `cwcli config cache disable` sets `[cache] enabled = false` in the config file. `cwcli config cache enable` reverts it.
|
|
2070
|
+
- **Environment variable:** `CWCLI_NO_CACHE=1` disables caching for a single shell or CI job; `CWCLI_NO_CACHE=0` re-enables it. The environment variable **overrides** the config key, so you can force caching on or off for one invocation regardless of the persisted setting.
|
|
2071
|
+
|
|
2072
|
+
With caching disabled:
|
|
2073
|
+
|
|
2074
|
+
- Every read resolves **live**, as if a fresh `inspect` had just run - a stale cached row can never be served.
|
|
2075
|
+
- **Nothing** is written to or read from the cache DB, and a pre-existing cache file is left in place untouched, so re-enabling restores the previous behaviour.
|
|
2076
|
+
- Tab completion degrades gracefully to a live/empty lookup rather than serving stale names.
|
|
2077
|
+
- `auto-inspect` refuses to start (it exists only to keep the cache warm, which does nothing when caching is off).
|
|
2078
|
+
- Bench labels still work, because they are also stored in each bench's marker file.
|
|
2079
|
+
- Safety-critical commands (`rm`/`rm-site`'s backup step, `apps checkout`'s wrong-copy detection) get correct live data.
|
|
2080
|
+
|
|
2081
|
+
Because every read resolves live, commands are slower than with the cache warm - this is a correctness/isolation mode, not the everyday default.
|
|
2082
|
+
|
|
2058
2083
|
##### `config auto-inspect` - Automatic Project Inspection
|
|
2059
2084
|
|
|
2060
2085
|
Manages automatic background inspection of running Frappe projects to keep cached data fresh (tab completion, project status queries, and other commands that rely on cached data).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.3.0"
|
|
@@ -101,6 +101,17 @@ def show(
|
|
|
101
101
|
console.print("[bold]Locations[/bold]")
|
|
102
102
|
console.print(f" Config file: [green]{report.config_file}[/green]")
|
|
103
103
|
console.print(f" Cache DB: [green]{report.cache_db}[/green]")
|
|
104
|
+
|
|
105
|
+
console.print("\n[bold]Cache[/bold]")
|
|
106
|
+
if report.cache_enabled:
|
|
107
|
+
console.print(" Enabled: [green]Yes[/green]")
|
|
108
|
+
else:
|
|
109
|
+
source = "CWCLI_NO_CACHE" if report.cache_env_override else "config"
|
|
110
|
+
console.print(f" Enabled: [red]No[/red] [dim](disabled via {source})[/dim]")
|
|
111
|
+
console.print(" [dim]Reads resolve live; nothing is written to the cache DB.[/dim]")
|
|
112
|
+
if report.cache_env_override:
|
|
113
|
+
console.print(" [dim]CWCLI_NO_CACHE is set and overrides the config key.[/dim]")
|
|
114
|
+
|
|
104
115
|
console.print("\n[bold]Search paths[/bold]")
|
|
105
116
|
if report.search_paths:
|
|
106
117
|
for path in report.search_paths:
|
|
@@ -351,6 +362,44 @@ def clear_cache(
|
|
|
351
362
|
)
|
|
352
363
|
|
|
353
364
|
|
|
365
|
+
@cache_app.command("enable")
|
|
366
|
+
def cache_enable():
|
|
367
|
+
"""
|
|
368
|
+
Turn the on-disk cache back on (the default).
|
|
369
|
+
"""
|
|
370
|
+
_apply_cache_setting(True)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
@cache_app.command("disable")
|
|
374
|
+
def cache_disable():
|
|
375
|
+
"""
|
|
376
|
+
Turn the on-disk cache off entirely.
|
|
377
|
+
|
|
378
|
+
Every read command then resolves live (as if a fresh inspect ran) and nothing
|
|
379
|
+
is written to or read from the cache DB. The existing cache file is left in
|
|
380
|
+
place, so re-enabling restores it. Set CWCLI_NO_CACHE=1 for the same effect
|
|
381
|
+
per shell / in CI.
|
|
382
|
+
"""
|
|
383
|
+
_apply_cache_setting(False)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def _apply_cache_setting(enabled: bool):
|
|
387
|
+
state = core_config.set_cache(enabled).data
|
|
388
|
+
assert state is not None
|
|
389
|
+
if enabled:
|
|
390
|
+
console.print("[green]Caching enabled.[/green] Reads use the on-disk cache.")
|
|
391
|
+
else:
|
|
392
|
+
console.print(
|
|
393
|
+
"[yellow]Caching disabled.[/yellow] Reads resolve live; nothing is written "
|
|
394
|
+
"to the cache DB (the existing cache is left in place)."
|
|
395
|
+
)
|
|
396
|
+
if state.env_override and state.enabled != enabled:
|
|
397
|
+
console.print(
|
|
398
|
+
"[yellow]Note:[/yellow] CWCLI_NO_CACHE is set and overrides this setting; "
|
|
399
|
+
f"caching is currently {'enabled' if state.enabled else 'disabled'} for this shell."
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
|
|
354
403
|
@cache_app.command("path")
|
|
355
404
|
def cache_path():
|
|
356
405
|
"""
|
|
@@ -160,6 +160,14 @@ def enable(interval: int | None = None, at_boot: bool | None = None) -> Result[A
|
|
|
160
160
|
it when a changed interval must take effect), then syncs the boot hook when
|
|
161
161
|
``at_boot`` was requested (``None`` leaves the hook untouched).
|
|
162
162
|
"""
|
|
163
|
+
if config_utils.cache_disabled():
|
|
164
|
+
raise CwcliError(
|
|
165
|
+
ErrorKind.USAGE,
|
|
166
|
+
"auto_inspect.cache_disabled",
|
|
167
|
+
"Caching is disabled, so auto-inspect has nothing to keep warm.",
|
|
168
|
+
hint="Re-enable caching first: `cwcli config cache enable` (or unset CWCLI_NO_CACHE).",
|
|
169
|
+
)
|
|
170
|
+
|
|
163
171
|
if interval is not None and interval < MIN_INTERVAL:
|
|
164
172
|
raise CwcliError(
|
|
165
173
|
ErrorKind.USAGE,
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/config.py
RENAMED
|
@@ -18,6 +18,7 @@ cannot be checked, nothing is pruned.
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
+
import os
|
|
21
22
|
import posixpath
|
|
22
23
|
from dataclasses import dataclass, field
|
|
23
24
|
|
|
@@ -38,12 +39,22 @@ class ConfigReport:
|
|
|
38
39
|
|
|
39
40
|
config_file: str
|
|
40
41
|
cache_db: str
|
|
42
|
+
cache_enabled: bool
|
|
43
|
+
cache_env_override: bool
|
|
41
44
|
search_paths: list[str]
|
|
42
45
|
auto_inspect: AutoInspectState
|
|
43
46
|
cred_bridge: CredBridgeState
|
|
44
47
|
show_tips: bool
|
|
45
48
|
|
|
46
49
|
|
|
50
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
51
|
+
class CacheState:
|
|
52
|
+
"""Whether the on-disk cache is on, and whether an env var is forcing it."""
|
|
53
|
+
|
|
54
|
+
enabled: bool
|
|
55
|
+
env_override: bool # True when CWCLI_NO_CACHE is set (config key is inert)
|
|
56
|
+
|
|
57
|
+
|
|
47
58
|
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
48
59
|
class SearchPathChange:
|
|
49
60
|
"""A search-path add/remove: the normalized path and whether anything changed."""
|
|
@@ -79,6 +90,12 @@ def _normalize(path: str) -> str:
|
|
|
79
90
|
return posixpath.normpath(posixpath.expanduser(path))
|
|
80
91
|
|
|
81
92
|
|
|
93
|
+
def _cache_env_override() -> bool:
|
|
94
|
+
"""True when CWCLI_NO_CACHE is set to a non-empty value (it wins over config)."""
|
|
95
|
+
env = os.environ.get("CWCLI_NO_CACHE")
|
|
96
|
+
return env is not None and env.strip() != ""
|
|
97
|
+
|
|
98
|
+
|
|
82
99
|
def show_config() -> Result[ConfigReport]:
|
|
83
100
|
"""The effective config as one report: paths, auto-inspect, tips, locations."""
|
|
84
101
|
state = core_auto_inspect.status().data
|
|
@@ -91,6 +108,8 @@ def show_config() -> Result[ConfigReport]:
|
|
|
91
108
|
data=ConfigReport(
|
|
92
109
|
config_file=str(config_utils.CONFIG_FILE),
|
|
93
110
|
cache_db=str(db_utils.DB_PATH),
|
|
111
|
+
cache_enabled=not config_utils.cache_disabled(),
|
|
112
|
+
cache_env_override=_cache_env_override(),
|
|
94
113
|
search_paths=list(config["search_paths"]["custom_bench_paths"]),
|
|
95
114
|
auto_inspect=state,
|
|
96
115
|
cred_bridge=bridge_state,
|
|
@@ -99,6 +118,22 @@ def show_config() -> Result[ConfigReport]:
|
|
|
99
118
|
)
|
|
100
119
|
|
|
101
120
|
|
|
121
|
+
def set_cache(enabled: bool) -> Result[CacheState]:
|
|
122
|
+
"""Turn the on-disk cache on or off via the ``[cache] enabled`` config key.
|
|
123
|
+
|
|
124
|
+
The cache DB is never deleted or altered here - it is left in place so
|
|
125
|
+
re-enabling restores the previous behaviour. When ``CWCLI_NO_CACHE`` is set it
|
|
126
|
+
overrides this key, so the returned :class:`CacheState` reports that override.
|
|
127
|
+
"""
|
|
128
|
+
config_utils.set_cache_enabled(enabled)
|
|
129
|
+
return Result(
|
|
130
|
+
status=Status.OK,
|
|
131
|
+
data=CacheState(
|
|
132
|
+
enabled=not config_utils.cache_disabled(), env_override=_cache_env_override()
|
|
133
|
+
),
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
102
137
|
def add_search_path(path: str) -> Result[SearchPathChange]:
|
|
103
138
|
"""Add a bench search path: refuse non-absolute, normalize before dedup.
|
|
104
139
|
|
|
@@ -581,6 +581,14 @@ def inspect_raw(
|
|
|
581
581
|
f"Unknown refresh mode '{refresh}'. Use one of: {', '.join(_REFRESH_MODES)}.",
|
|
582
582
|
)
|
|
583
583
|
|
|
584
|
+
# Caching off: always resolve live. Force the full tier so no cached row (T1)
|
|
585
|
+
# or partial refresh (T2) can be served, and the write below lands in the
|
|
586
|
+
# ephemeral in-memory store db_utils redirects to (the on-disk cache is never
|
|
587
|
+
# touched). This is also the recursion base for db_utils._live_populate: a
|
|
588
|
+
# forced-full run with no selector never reads the cache back.
|
|
589
|
+
if config_utils.cache_disabled():
|
|
590
|
+
refresh = "full"
|
|
591
|
+
|
|
584
592
|
emit = on_event or _noop
|
|
585
593
|
warnings: list[Message] = []
|
|
586
594
|
|
|
@@ -592,7 +600,10 @@ def inspect_raw(
|
|
|
592
600
|
served_from = "cache"
|
|
593
601
|
|
|
594
602
|
cached_data = None
|
|
595
|
-
|
|
603
|
+
# With caching disabled there is nothing to read and the read would only
|
|
604
|
+
# trigger a redundant nested live populate; the forced-full path below does a
|
|
605
|
+
# fresh discovery and narrows the selector from that.
|
|
606
|
+
if (refresh != "full" or bench is not None) and not config_utils.cache_disabled():
|
|
596
607
|
cached_data = db_utils.get_cached_project_data(project_name)
|
|
597
608
|
|
|
598
609
|
if refresh != "full":
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/where.py
RENAMED
|
@@ -31,7 +31,7 @@ from dataclasses import dataclass, field, replace
|
|
|
31
31
|
|
|
32
32
|
import peewee
|
|
33
33
|
|
|
34
|
-
from ..utils import db_utils
|
|
34
|
+
from ..utils import config_utils, db_utils
|
|
35
35
|
from .envelope import Message, Result, Status
|
|
36
36
|
from .errors import CwcliError, ErrorKind
|
|
37
37
|
from .list import list_instances
|
|
@@ -177,6 +177,21 @@ def _live_project_names() -> set[str] | None:
|
|
|
177
177
|
return {instance.project_name for instance in (result.data or [])}
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
def _populate_live_if_disabled() -> None:
|
|
181
|
+
"""With caching off, ``where`` has no cache to search, so inspect every live
|
|
182
|
+
instance into the ephemeral in-memory store first, then search that.
|
|
183
|
+
|
|
184
|
+
Reuses the same live-populate ``db_utils`` runs for a single project (one full
|
|
185
|
+
inspect per running instance); the on-disk cache is never touched. A daemon we
|
|
186
|
+
cannot reach leaves the store empty, which ``where`` reports as no matches.
|
|
187
|
+
"""
|
|
188
|
+
if not config_utils.cache_disabled():
|
|
189
|
+
return
|
|
190
|
+
live = _live_project_names()
|
|
191
|
+
for project_name in live or set():
|
|
192
|
+
db_utils.get_cached_project_data(project_name)
|
|
193
|
+
|
|
194
|
+
|
|
180
195
|
def where(
|
|
181
196
|
search: str,
|
|
182
197
|
*,
|
|
@@ -193,6 +208,8 @@ def where(
|
|
|
193
208
|
"Cannot use --apps and --sites together.",
|
|
194
209
|
)
|
|
195
210
|
|
|
211
|
+
_populate_live_if_disabled()
|
|
212
|
+
|
|
196
213
|
matches: list[WhereMatch] = []
|
|
197
214
|
|
|
198
215
|
# A corrupt/locked cache or a schema mismatch surfaces here as a raw peewee
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/cache.py
RENAMED
|
@@ -5,7 +5,7 @@ This module provides utilities for managing the project inspection cache,
|
|
|
5
5
|
including re-caching operations built on the core inspect slice.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from . import db_utils
|
|
8
|
+
from . import config_utils, db_utils
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def recache_project(project_name: str, verbose: bool = False) -> bool:
|
|
@@ -31,6 +31,11 @@ def recache_project(project_name: str, verbose: bool = False) -> bool:
|
|
|
31
31
|
True if recache succeeded, False otherwise (including when the project's
|
|
32
32
|
containers are not running, since a stopped bench cannot be inspected).
|
|
33
33
|
"""
|
|
34
|
+
# Caching off: there is no on-disk cache to refresh, so a post-mutation
|
|
35
|
+
# recache would only run a full inspect into a store that is discarded.
|
|
36
|
+
if config_utils.cache_disabled():
|
|
37
|
+
return True
|
|
38
|
+
|
|
34
39
|
try:
|
|
35
40
|
# Clear the cache for this project
|
|
36
41
|
db_utils.clear_cache_for_project(project_name)
|
|
@@ -11,7 +11,7 @@ import time
|
|
|
11
11
|
import docker
|
|
12
12
|
import typer
|
|
13
13
|
|
|
14
|
-
from . import db_utils
|
|
14
|
+
from . import config_utils, db_utils
|
|
15
15
|
|
|
16
16
|
# Cache configuration
|
|
17
17
|
_CACHE_TTL = 2.0 # Cache results for 2 seconds (enough for tab completion session)
|
|
@@ -138,6 +138,12 @@ def complete_app_names(
|
|
|
138
138
|
if not project_name:
|
|
139
139
|
return []
|
|
140
140
|
|
|
141
|
+
# Caching off: degrade to an empty completion rather than blocking the shell
|
|
142
|
+
# on a live inspect. Empty beats stale, and completion must never do container
|
|
143
|
+
# I/O.
|
|
144
|
+
if config_utils.cache_disabled():
|
|
145
|
+
return []
|
|
146
|
+
|
|
141
147
|
# Check cache first
|
|
142
148
|
cache_key = f"apps:{project_name}"
|
|
143
149
|
cached = _get_cached(cache_key)
|
|
@@ -186,6 +192,12 @@ def complete_site_names(
|
|
|
186
192
|
if not project_name:
|
|
187
193
|
return []
|
|
188
194
|
|
|
195
|
+
# Caching off: degrade to an empty completion rather than blocking the shell
|
|
196
|
+
# on a live inspect. Empty beats stale, and completion must never do container
|
|
197
|
+
# I/O.
|
|
198
|
+
if config_utils.cache_disabled():
|
|
199
|
+
return []
|
|
200
|
+
|
|
189
201
|
# Check cache first
|
|
190
202
|
cache_key = f"sites:{project_name}"
|
|
191
203
|
cached = _get_cached(cache_key)
|
|
@@ -99,6 +99,18 @@ startup_enabled = false
|
|
|
99
99
|
# Applies immediately (no daemon restart needed); cwcli's own per-operation
|
|
100
100
|
# bridge (apps install/update, init) is not restricted by this list.
|
|
101
101
|
allowed_hosts = ["github.com", "gitlab.com"]
|
|
102
|
+
|
|
103
|
+
[cache]
|
|
104
|
+
# The on-disk SQLite cache under <cwcli home>/cache speeds up read commands
|
|
105
|
+
# (inspect, status, where, tab completion, ...) by remembering each project's
|
|
106
|
+
# benches, sites, and apps.
|
|
107
|
+
#
|
|
108
|
+
# Set enabled = false to turn caching off entirely: every read resolves live
|
|
109
|
+
# (as if a fresh inspect ran), nothing is written to or read from the cache DB,
|
|
110
|
+
# and a pre-existing cache is left in place untouched so turning caching back on
|
|
111
|
+
# restores it. The CWCLI_NO_CACHE environment variable overrides this key per
|
|
112
|
+
# shell / in CI (CWCLI_NO_CACHE=1 disables, CWCLI_NO_CACHE=0 re-enables).
|
|
113
|
+
enabled = true
|
|
102
114
|
"""
|
|
103
115
|
|
|
104
116
|
DEFAULT_ALLOWED_HOSTS = ("github.com", "gitlab.com")
|
|
@@ -150,6 +162,10 @@ def load_config() -> dict:
|
|
|
150
162
|
else:
|
|
151
163
|
for key, value in _cred_bridge_defaults().items():
|
|
152
164
|
config_data["cred_bridge"].setdefault(key, value)
|
|
165
|
+
if "cache" not in config_data:
|
|
166
|
+
config_data["cache"] = {"enabled": True}
|
|
167
|
+
elif "enabled" not in config_data["cache"]:
|
|
168
|
+
config_data["cache"]["enabled"] = True
|
|
153
169
|
return config_data
|
|
154
170
|
except toml.TomlDecodeError:
|
|
155
171
|
return {
|
|
@@ -157,6 +173,7 @@ def load_config() -> dict:
|
|
|
157
173
|
"auto_inspect": {"enabled": False, "interval": 3600, "startup_enabled": False},
|
|
158
174
|
"ui": {"show_tips": True},
|
|
159
175
|
"cred_bridge": _cred_bridge_defaults(),
|
|
176
|
+
"cache": {"enabled": True},
|
|
160
177
|
}
|
|
161
178
|
|
|
162
179
|
|
|
@@ -286,6 +303,49 @@ def set_cred_bridge_startup(enabled: bool):
|
|
|
286
303
|
save_config(config)
|
|
287
304
|
|
|
288
305
|
|
|
306
|
+
def read_cache_config() -> dict:
|
|
307
|
+
"""Read the [cache] config WITHOUT creating config state.
|
|
308
|
+
|
|
309
|
+
Used by :func:`cache_disabled`, which runs on the hot path of every cache
|
|
310
|
+
read; it must never write a default config file into the user's home as a
|
|
311
|
+
side effect (mirrors :func:`read_cred_bridge_config`).
|
|
312
|
+
"""
|
|
313
|
+
default = {"enabled": True}
|
|
314
|
+
if not CONFIG_FILE.is_file():
|
|
315
|
+
return default
|
|
316
|
+
try:
|
|
317
|
+
with open(CONFIG_FILE) as f:
|
|
318
|
+
config = toml.load(f)
|
|
319
|
+
except (OSError, toml.TomlDecodeError):
|
|
320
|
+
return default
|
|
321
|
+
cache = config.get("cache", default)
|
|
322
|
+
return cache if isinstance(cache, dict) else default
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def cache_disabled() -> bool:
|
|
326
|
+
"""Whether cwcli's on-disk SQLite cache is turned off.
|
|
327
|
+
|
|
328
|
+
The ``CWCLI_NO_CACHE`` environment variable overrides the ``[cache] enabled``
|
|
329
|
+
config key, so caching can be toggled per shell / in CI - and can even be
|
|
330
|
+
re-enabled (``CWCLI_NO_CACHE=0``) when the config file disables it. An unset
|
|
331
|
+
or empty env var falls through to the config key (default: enabled).
|
|
332
|
+
"""
|
|
333
|
+
env = os.environ.get("CWCLI_NO_CACHE")
|
|
334
|
+
if env is not None and env.strip() != "":
|
|
335
|
+
return env.strip().lower() in ("1", "true", "yes", "on")
|
|
336
|
+
return not bool(read_cache_config().get("enabled", True))
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def set_cache_enabled(enabled: bool):
|
|
340
|
+
"""Enable or disable the on-disk cache via the ``[cache] enabled`` config key."""
|
|
341
|
+
config = load_config()
|
|
342
|
+
if "cache" not in config:
|
|
343
|
+
config["cache"] = {"enabled": enabled}
|
|
344
|
+
else:
|
|
345
|
+
config["cache"]["enabled"] = enabled
|
|
346
|
+
save_config(config)
|
|
347
|
+
|
|
348
|
+
|
|
289
349
|
def get_show_tips() -> bool:
|
|
290
350
|
"""
|
|
291
351
|
Get whether tips should be shown during long-running operations.
|
|
@@ -12,7 +12,7 @@ from peewee import (
|
|
|
12
12
|
TextField,
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
-
from . import shared_home
|
|
15
|
+
from . import config_utils, shared_home
|
|
16
16
|
from .config_utils import cwcli_home
|
|
17
17
|
|
|
18
18
|
# Resolve the cache location through the shared cwcli_home() helper so the
|
|
@@ -21,6 +21,12 @@ from .config_utils import cwcli_home
|
|
|
21
21
|
CACHE_DIR = cwcli_home() / "cache"
|
|
22
22
|
DB_PATH = CACHE_DIR / "cwc-cache.db"
|
|
23
23
|
|
|
24
|
+
# The sentinel path an ephemeral in-memory SQLite database uses. When caching is
|
|
25
|
+
# disabled (config_utils.cache_disabled()) the whole cache is redirected here, so
|
|
26
|
+
# the on-disk DB is never opened, read, or written and a stale row can never leak
|
|
27
|
+
# through - see initialize_database() and _live_populate().
|
|
28
|
+
_MEMORY_DB = ":memory:"
|
|
29
|
+
|
|
24
30
|
# SECURITY: config_json rows are whitelist-filtered by _redact_config_for_cache
|
|
25
31
|
# before write, so the cache never stores DB credentials, encryption keys, or
|
|
26
32
|
# redis URLs. Restrictive filesystem permissions (0700 dir / 0600 file) remain
|
|
@@ -30,20 +36,23 @@ DB_PATH = CACHE_DIR / "cwc-cache.db"
|
|
|
30
36
|
# shared_home).
|
|
31
37
|
|
|
32
38
|
# Create cache directory with restricted permissions (0700 = owner-only access)
|
|
33
|
-
# This prevents other users on the system from reading cached credentials
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
# This prevents other users on the system from reading cached credentials. Skip
|
|
40
|
+
# it entirely when caching is disabled, so a disabled install leaves no on-disk
|
|
41
|
+
# footprint at all.
|
|
42
|
+
if not config_utils.cache_disabled():
|
|
43
|
+
CACHE_DIR.mkdir(parents=True, mode=shared_home.dir_mode(0o700), exist_ok=True)
|
|
44
|
+
|
|
45
|
+
# Ensure existing directory has correct permissions
|
|
46
|
+
if CACHE_DIR.exists():
|
|
47
|
+
try:
|
|
48
|
+
CACHE_DIR.chmod(shared_home.dir_mode(0o700))
|
|
49
|
+
shared_home.apply_group(CACHE_DIR)
|
|
50
|
+
except (OSError, PermissionError):
|
|
51
|
+
# On Windows or restricted filesystems, chmod may fail
|
|
52
|
+
# Still proceed but permissions may not be as strict
|
|
53
|
+
pass
|
|
45
54
|
|
|
46
|
-
db = SqliteDatabase(DB_PATH)
|
|
55
|
+
db = SqliteDatabase(_MEMORY_DB if config_utils.cache_disabled() else DB_PATH)
|
|
47
56
|
|
|
48
57
|
|
|
49
58
|
class BaseModel(Model):
|
|
@@ -371,7 +380,54 @@ def _scrub_cached_config_secrets():
|
|
|
371
380
|
print(f"Warning: could not scrub cached config secrets: {e}", file=sys.stderr)
|
|
372
381
|
|
|
373
382
|
|
|
383
|
+
# Projects live-populated into the ephemeral in-memory cache this process (see
|
|
384
|
+
# _live_populate). A reentrancy flag stops the populating inspect - which writes
|
|
385
|
+
# the same in-memory DB - from recursing back through a cache read.
|
|
386
|
+
_live_populated: set[str] = set()
|
|
387
|
+
_populating = False
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
def _db_target() -> str:
|
|
391
|
+
"""Where the cache DB should point right now: in-memory when disabled."""
|
|
392
|
+
return _MEMORY_DB if config_utils.cache_disabled() else str(DB_PATH)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _live_populate(project_name: str) -> None:
|
|
396
|
+
"""In cache-disabled mode, populate the ephemeral in-memory DB with one live
|
|
397
|
+
inspect so downstream cache reads resolve fresh data instead of nothing.
|
|
398
|
+
|
|
399
|
+
The on-disk cache is never touched: the disabled DB points at ``:memory:``,
|
|
400
|
+
so the inspect's write lands in the ephemeral store this process discards on
|
|
401
|
+
exit. Memoized and reentrancy-guarded (the inspect writes the same DB), and
|
|
402
|
+
best-effort: a stopped/absent project simply yields no in-memory rows, which
|
|
403
|
+
every caller already handles as a cache miss.
|
|
404
|
+
"""
|
|
405
|
+
global _populating
|
|
406
|
+
if not config_utils.cache_disabled() or _populating or project_name in _live_populated:
|
|
407
|
+
return
|
|
408
|
+
_populating = True
|
|
409
|
+
try:
|
|
410
|
+
from ..core import inspect as core_inspect
|
|
411
|
+
|
|
412
|
+
core_inspect.inspect(project_name, refresh="full", offer_choice=False)
|
|
413
|
+
except Exception: # noqa: BLE001 - a failed live read just leaves the store empty
|
|
414
|
+
pass
|
|
415
|
+
finally:
|
|
416
|
+
_live_populated.add(project_name) # never retry within one process
|
|
417
|
+
_populating = False
|
|
418
|
+
|
|
419
|
+
|
|
374
420
|
def initialize_database():
|
|
421
|
+
target = _db_target()
|
|
422
|
+
if str(db.database) != target:
|
|
423
|
+
# The disabled state flipped (e.g. a test toggled CWCLI_NO_CACHE, or the
|
|
424
|
+
# first read after enable/disable). Re-point the shared database so every
|
|
425
|
+
# model follows it. Switching TO :memory: gives a fresh empty store;
|
|
426
|
+
# switching back opens the untouched on-disk cache.
|
|
427
|
+
if not db.is_closed():
|
|
428
|
+
db.close()
|
|
429
|
+
db.init(target)
|
|
430
|
+
_live_populated.clear()
|
|
375
431
|
if db.is_closed():
|
|
376
432
|
db.connect()
|
|
377
433
|
# Create tables if missing
|
|
@@ -528,6 +584,7 @@ def _cache_project_data(project_name: str, bench_instances_data: list[dict]) ->
|
|
|
528
584
|
|
|
529
585
|
def get_cached_project_data(project_name):
|
|
530
586
|
initialize_database()
|
|
587
|
+
_live_populate(project_name)
|
|
531
588
|
try:
|
|
532
589
|
project = Project.get(Project.name == project_name)
|
|
533
590
|
|
|
@@ -643,6 +700,7 @@ def get_common_site_config(project_name: str, bench_path: str | None = None) ->
|
|
|
643
700
|
Dictionary with common site config or None if not found
|
|
644
701
|
"""
|
|
645
702
|
initialize_database()
|
|
703
|
+
_live_populate(project_name)
|
|
646
704
|
try:
|
|
647
705
|
project = Project.get(Project.name == project_name)
|
|
648
706
|
|
|
@@ -685,6 +743,7 @@ def get_site_config(
|
|
|
685
743
|
Dictionary with site config or None if not found
|
|
686
744
|
"""
|
|
687
745
|
initialize_database()
|
|
746
|
+
_live_populate(project_name)
|
|
688
747
|
try:
|
|
689
748
|
project = Project.get(Project.name == project_name)
|
|
690
749
|
|
|
@@ -729,6 +788,7 @@ def get_all_site_configs(project_name: str, bench_path: str | None = None) -> di
|
|
|
729
788
|
Dictionary mapping site names to their configs
|
|
730
789
|
"""
|
|
731
790
|
initialize_database()
|
|
791
|
+
_live_populate(project_name)
|
|
732
792
|
result = {}
|
|
733
793
|
|
|
734
794
|
try:
|
|
@@ -763,6 +823,7 @@ def get_current_site(project_name: str, bench_path: str | None = None) -> str |
|
|
|
763
823
|
non-empty ``current_site`` found (scoped to ``bench_path`` when given).
|
|
764
824
|
"""
|
|
765
825
|
initialize_database()
|
|
826
|
+
_live_populate(project_name)
|
|
766
827
|
try:
|
|
767
828
|
project = Project.get(Project.name == project_name)
|
|
768
829
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.2.1"
|
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/commands/rm.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/apps.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/backup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/docker.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/doctor.py
RENAMED
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/fleet.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/init.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/label.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/list.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/logs.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/open.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/rm.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/run.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/scale.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/setup.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/start.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/status.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/stop.py
RENAMED
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/unlock.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/update.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/core/url.py
RENAMED
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/main.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/tips.py
RENAMED
|
File without changes
|
{caffeinated_whale_cli-3.2.1 → caffeinated_whale_cli-3.3.0}/src/caffeinated_whale_cli/utils/toon.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|