diff --git a/README.md b/README.md index 40daa3c..184c514 100644 --- a/README.md +++ b/README.md @@ -196,11 +196,10 @@ import eea_datalakehouse.notebook # registers %catalog/%ingest — no %load_ext %ingest commit(retry=True) ``` -`%catalog help` (or `%catalog help()`) prints every command as a plain table — name, +`%catalog help` (or `%catalog help()`) renders every command as an HTML table — name, parameters, description — rather than a raw Python signature, since its audience is a data -custodian, not necessarily a developer. `%ingest help` does the same for `IngestSession`, -listing its (fewer) methods with their real signatures — handy when you don't remember an -exact parameter name mid-notebook. +custodian, not necessarily a developer. `%ingest help` does the same for `IngestSession`'s +(fewer) methods — handy when you don't remember an exact parameter name mid-notebook. `%%catalog` (the cell-magic form) sets the context once, with `use(path)` on its magic line, then runs every other line of the cell in order under that context, without repeating the full diff --git a/docs/notebooks/ingest_session_example.ipynb b/docs/notebooks/ingest_session_example.ipynb index 1a98729..dc98794 100644 --- a/docs/notebooks/ingest_session_example.ipynb +++ b/docs/notebooks/ingest_session_example.ipynb @@ -37,7 +37,7 @@ { "cell_type": "markdown", "id": "53bc1b4a", - "source": "## Quick reference\n\n`%ingest help` (or `%ingest help()`) lists every `IngestSession` method with its signature\nand a short description — handy when you don't remember an exact parameter name\nmid-notebook.", + "source": "## Quick reference\n\n`%ingest help` (or `%ingest help()`) renders every `IngestSession` method as an HTML table —\nname, parameters, description — the same format `%catalog help` uses. Handy when you don't\nremember an exact parameter name mid-notebook.", "metadata": {} }, { diff --git a/src/eea_datalakehouse/notebook/magics.py b/src/eea_datalakehouse/notebook/magics.py index 06fdb9d..5f24015 100644 --- a/src/eea_datalakehouse/notebook/magics.py +++ b/src/eea_datalakehouse/notebook/magics.py @@ -242,50 +242,9 @@ def _is_help(line: str) -> bool: return line.strip() in ("help", "help()") -def _format_signature(func: Any) -> str: - """Render `func`'s signature (minus `self`) the way it reads in source — - `inspect.Signature`'s own `str()` wraps string annotations in quotes - (they're plain `str`s at runtime because of this module's, and the - session modules', `from __future__ import annotations`), which is - accurate but noisy for a notebook help message.""" - sig = inspect.signature(func) - parts = [] - seen_star = False - for name, param in sig.parameters.items(): - if name == "self": - continue - if param.kind is inspect.Parameter.KEYWORD_ONLY and not seen_star: - parts.append("*") - seen_star = True - piece = name - if param.annotation is not inspect.Parameter.empty: - piece += f": {param.annotation}" - if param.default is not inspect.Parameter.empty: - piece += f" = {param.default!r}" - parts.append(piece) - rendered = f"({', '.join(parts)})" - if sig.return_annotation is not inspect.Signature.empty: - rendered += f" -> {sig.return_annotation}" - return rendered - - -def _print_help(cls: type, methods: list[tuple[str, str]], label: str) -> None: - """Print every method in `methods` with its real signature (introspected - from `cls`, so it can't drift from the source) and a one-line - description. Signatures drop `self`; everything else — parameter names, - defaults, `*`-only markers, return types — comes straight from `cls`.""" - print(f"%{label} methods — usage: {_USAGE[label]}") - print() - for name, description in methods: - print(f" {name}{_format_signature(getattr(cls, name))}") - print(f" {description}") - print() - print(f"%{label} help — show this message") - - def _plain_params(func: Any) -> str: """Comma-separated parameter names (minus `self`), for a non-developer - reading `%catalog help`'s table — no Python type-hint syntax (a bare + reading `%catalog help`'s/`%ingest help`'s table — no Python type-hint syntax (a bare `str | None` union means nothing to a data custodian, and would collide visually with the table's own `|` column separators anyway) and no `*` keyword-only marker. A parameter with a default is shown as `name=default` @@ -299,26 +258,35 @@ def _plain_params(func: Any) -> str: return ", ".join(parts) -_CATALOG_HELP_HEADER_STYLE = ( +_HELP_TABLE_HEADER_STYLE = ( "text-align:left; padding:4px 12px; border-bottom:2px solid currentColor;" ) -_CATALOG_HELP_CELL_STYLE = ( +_HELP_TABLE_CELL_STYLE = ( "text-align:left; padding:4px 12px; border-bottom:1px solid currentColor; vertical-align:top;" ) -_CATALOG_HELP_CODE_STYLE = _CATALOG_HELP_CELL_STYLE + " font-family:monospace; white-space:pre;" +_HELP_TABLE_CODE_STYLE = _HELP_TABLE_CELL_STYLE + " font-family:monospace; white-space:pre;" + +# Catalog-specific: printed once above %catalog help's table, not per-row, +# since it applies across every path/source_path/target_path. %ingest help +# has no equivalent note. +_CATALOG_HELP_NOTE = ( + "A path/source_path/target_path starting with '.' resolves against the current " + "context (see use); one or more leading '../' (or a bare '..') walks up that many " + "levels first. Ordinary use already keeps context current on its own." +) -def _catalog_help_html(rows: list[tuple[str, str, str]]) -> str: - """Build the `
| {_escape(text)} | ' + return f'{_escape(text)} | ' def td(text: str, *, code: bool = False) -> str: - style = _CATALOG_HELP_CODE_STYLE if code else _CATALOG_HELP_CELL_STYLE + style = _HELP_TABLE_CODE_STYLE if code else _HELP_TABLE_CELL_STYLE return f'{_escape(text)} | ' head = f"
|---|