Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions codemode.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ uvx lkr-dev-cli code-mode sandbox --code="return me()"

# Execute Python script file
uvx lkr-dev-cli code-mode sandbox --file=./path/to/script.py

# Execute Python script file with injected variables (--var / -v)
uvx lkr-dev-cli code-mode sandbox --file=./path/to/script.py --var project=my_project --var connection=my_connection
```

### 2. Starting the Server
Expand Down
22 changes: 22 additions & 0 deletions lkr.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ $ lkr [OPTIONS] COMMAND [ARGS]...

**Options**:

* `--version`: Show the version and exit.
* `--client-id TEXT`: [env var: LOOKERSDK_CLIENT_ID]
* `--client-secret TEXT`: [env var: LOOKERSDK_CLIENT_SECRET]
* `--base-url TEXT`: [env var: LOOKERSDK_BASE_URL]
Expand Down Expand Up @@ -262,6 +263,7 @@ $ lkr tools lookml [OPTIONS] COMMAND [ARGS]...
#### `lkr tools lookml push`

Push local files to Looker, removing files on the instance that aren't being pushed.
If --file / -f is specified (or folder_name is a file), only that single file is pushed without deleting remote orphans.

**Usage**:

Expand All @@ -276,13 +278,15 @@ $ lkr tools lookml push [OPTIONS] FOLDER_NAME
**Options**:

* `--project-id, --project TEXT`: Looker project ID to push to (if different from folder name)
* `-f, --file TEXT`: Single file relative path (or absolute path) to push
* `--deploy`: Commit and deploy to production after push
* `--message TEXT`: Commit message when deploying [default: push from lkr cli]
* `--help`: Show this message and exit.

#### `lkr tools lookml pull`

Pull remote files from Looker to local disk, removing local files that aren't on the instance.
If --file / -f is specified, only that single file is pulled without deleting local orphans.

**Usage**:

Expand All @@ -297,6 +301,7 @@ $ lkr tools lookml pull [OPTIONS] FOLDER_NAME
**Options**:

* `--project-id, --project TEXT`: Looker project ID to pull from (if different from folder name)
* `-f, --file TEXT`: Single file relative path to pull from Looker
* `--deploy`: Commit and deploy to production on Looker after pull
* `--message TEXT`: Commit message when deploying [default: pull from lkr cli then commit and deploy]
* `--help`: Show this message and exit.
Expand Down Expand Up @@ -335,8 +340,25 @@ $ lkr code-mode [OPTIONS] COMMAND [ARGS]...

**Commands**:

* `sandbox`
* `run`

### `lkr code-mode sandbox`

**Usage**:

```console
$ lkr code-mode sandbox [OPTIONS]
```

**Options**:

* `-c, --code TEXT`: Execute Python code directly in the sandbox
* `-f, --file TEXT`: Execute Python code from a file in the sandbox
* `--dev-mode`: Run in dev mode
* `-v, --var TEXT`: Inject variable as key=value pair (e.g. -v project=my_project)
* `--help`: Show this message and exit.

### `lkr code-mode run`

**Usage**:
Expand Down
22 changes: 21 additions & 1 deletion lkr/codemode/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ast
import inspect
import json
import keyword
import os
import re
import sys
Expand Down Expand Up @@ -223,6 +224,9 @@ def sandbox(
dev_mode: bool = typer.Option(
False, "--dev-mode", help="Run in dev mode"
),
var: list[str] | None = typer.Option(
None, "--var", "-v", help="Inject variable as key=value pair (e.g. -v project=my_project)"
),
):
if not code and not file:
logger.error("Must specify either --code or --file")
Expand All @@ -239,8 +243,24 @@ def sandbox(
except Exception as e:
logger.error(f"Failed to read file {file}: {e}")
raise typer.Exit(1)
else:
elif code:
code_to_run = code
else:
raise typer.Exit(1)

if var:
var_defs = []
for v_str in var:
if "=" not in v_str:
logger.error(f"Invalid variable format: '{v_str}'. Must be key=value.")
raise typer.Exit(1)
k, v = v_str.split("=", 1)
k = k.strip()
if not k.isidentifier() or keyword.iskeyword(k):
logger.error(f"Invalid variable name: '{k}'. Must be a valid Python identifier and not a keyword.")
raise typer.Exit(1)
var_defs.append(f"{k} = {json.dumps(v)}")
code_to_run = "\n".join(var_defs) + "\n" + code_to_run
Comment thread
bwebs marked this conversation as resolved.

global ctx_lkr
ctx_lkr = (
Expand Down
1 change: 1 addition & 0 deletions lkr/codemode/readme.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def get_readme() -> str:
6. **Efficiency**: Always use the `fields` parameter (e.g., `all_dashboards(fields="id,title")`) when listing many objects to prevent timeouts.
7. **Nested Folders**: Use `folder_children(id)` to get sub-folders.
8. **Search with Lookups**: If `help('pattern')` returns too many results and you want to see full details for all of them at once, use `search_with_lookups('pattern')`.
9. **Injected CLI Variables**: When using `sandbox` with `--var key=value` flags, those variables are directly available in your code as top-level string constants.

EXAMPLES:

Expand Down
Loading