Skip to content

Commit 4e53934

Browse files
rustyconoverclaude
andcommitted
docs(catalog): standardize dataclass field docs on Google Attributes: style
Convert leading-`#` field comments in vgi/catalog to Google-style `Attributes:` sections so they are visible to ruff/pydocstyle, pydoclint, and mkdocstrings. The `#` comments rendered in no generated docs and could not be linted; `Attributes:` sections are parsed by griffe and checkable via `pydoclint --check-class-attributes`. - pyproject.toml: pin `[tool.ruff.lint.pydocstyle] convention = "google"` (drops the now-redundant D203/D213 ignores). - catalog_interface.py: migrate 9 dataclasses (CatalogAttachResult, TableInfo, FunctionInfo, SchemaInfo, CatalogInfo, ...) and drop the redundant inline comments on ScanFunctionResult. - descriptors.py: complete Table's `Attributes:` (was missing 11 fields) and fold its two inline `#` field comments in. - fix the D205/D416 the google convention surfaced. Note: also carries pre-existing in-progress edits to filters.py that were already in the working tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 67a5d6c commit 4e53934

4 files changed

Lines changed: 479 additions & 284 deletions

File tree

pyproject.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,9 @@ exclude = ["duckdb"]
116116

117117
[tool.ruff.lint]
118118
select = ["E", "F", "I", "UP", "B", "SIM", "D"]
119-
ignore = [
120-
"D203", # incompatible with D211 (no-blank-line-before-class)
121-
"D213", # incompatible with D212 (multi-line-summary-first-line)
122-
]
119+
120+
[tool.ruff.lint.pydocstyle]
121+
convention = "google"
123122

124123
[tool.ruff.format]
125124
quote-style = "double"

vgi/_test_fixtures/table/filters.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,129 @@ def process(
287287
state.cursor += size
288288

289289

290+
# ============================================================================
291+
# FilteredColumnsEchoFunction — echoes the column-introspection accessors on the
292+
# pushed-down filter set: filtered_columns(), has_filter_for_column(), and the
293+
# typed (string-capable) get_column_values(). A query's WHERE clause is reflected
294+
# back as diagnostic columns so each accessor is observable end-to-end.
295+
# ============================================================================
296+
297+
298+
@dataclass(slots=True, frozen=True)
299+
class _FilteredColumnsEchoArgs:
300+
"""Arguments for FilteredColumnsEchoFunction."""
301+
302+
count: Annotated[int, Arg(0, doc="Number of rows to generate", ge=0)]
303+
batch_size: Annotated[int, Arg("batch_size", default=2048, doc="Batch size for output", ge=1)]
304+
305+
306+
@dataclass(kw_only=True)
307+
class _FilteredColumnsEchoState(ArrowSerializableDataclass):
308+
"""Resolved diagnostics (serialized so the HTTP rehydrate path preserves them)."""
309+
310+
count: int
311+
filtered_cols: str
312+
has_n: bool
313+
has_tag: bool
314+
tag_values: str
315+
cursor: int = 0
316+
317+
318+
@init_single_worker
319+
@bind_fixed_schema
320+
@_cardinality_from_count
321+
class FilteredColumnsEchoFunction(
322+
TableFunctionGenerator[_FilteredColumnsEchoArgs, _FilteredColumnsEchoState]
323+
):
324+
"""Report the columns referenced by pushed-down filters and ``tag``'s values.
325+
326+
Surfaces which columns the pushed-down filters reference and the discrete
327+
value set resolved for the string column ``tag``.
328+
329+
``filtered_cols`` is the sorted, comma-joined ``filtered_columns()`` set;
330+
``has_n`` / ``has_tag`` are ``has_filter_for_column()``; ``tag_values`` is
331+
the sorted, comma-joined ``get_column_values('tag')`` result (``"(none)"``
332+
when the predicate is not an enumerable equality/IN on ``tag``).
333+
"""
334+
335+
class Meta:
336+
"""Metadata for FilteredColumnsEchoFunction."""
337+
338+
name = "filtered_columns_echo"
339+
description = "Echoes filtered_columns / has_filter_for_column / get_column_values_array"
340+
categories = ["generator", "diagnostic"]
341+
filter_pushdown = True
342+
auto_apply_filters = True
343+
projection_pushdown = True
344+
345+
FIXED_SCHEMA: ClassVar[pa.Schema] = schema(
346+
{
347+
"n": pa.int64(),
348+
"tag": pa.utf8(),
349+
"filtered_cols": pa.utf8(),
350+
"has_n": pa.bool_(),
351+
"has_tag": pa.bool_(),
352+
"tag_values": pa.utf8(),
353+
}
354+
)
355+
356+
@classmethod
357+
def initial_state(
358+
cls, params: ProcessParams[_FilteredColumnsEchoArgs]
359+
) -> _FilteredColumnsEchoState:
360+
"""Resolve the filter-column diagnostics from the pushed-down filters."""
361+
assert params.init_call is not None
362+
pf = params.init_call.pushdown_filters
363+
jk = params.init_call.join_keys
364+
filters = cls.pushdown_filters(pf, join_keys=jk) if pf is not None else None
365+
if filters is not None:
366+
filtered_cols = ",".join(sorted(filters.filtered_columns))
367+
has_n = filters.has_filter_for_column("n")
368+
has_tag = filters.has_filter_for_column("tag")
369+
tag_arr = filters.get_column_values("tag")
370+
if tag_arr is not None:
371+
tag_values = ",".join(sorted(str(v) for v in tag_arr.to_pylist() if v is not None))
372+
else:
373+
tag_values = "(none)"
374+
else:
375+
filtered_cols, has_n, has_tag, tag_values = "", False, False, "(none)"
376+
return _FilteredColumnsEchoState(
377+
count=params.args.count,
378+
filtered_cols=filtered_cols,
379+
has_n=has_n,
380+
has_tag=has_tag,
381+
tag_values=tag_values,
382+
)
383+
384+
@classmethod
385+
def process(
386+
cls,
387+
params: ProcessParams[_FilteredColumnsEchoArgs],
388+
state: _FilteredColumnsEchoState,
389+
out: OutputCollector,
390+
) -> None:
391+
"""Emit the generated rows, each carrying the resolved diagnostics."""
392+
if state.cursor >= state.count:
393+
out.finish()
394+
return
395+
size = min(state.count - state.cursor, params.args.batch_size)
396+
ns = list(range(state.cursor, state.cursor + size))
397+
out.emit(
398+
pa.RecordBatch.from_pydict(
399+
{
400+
"n": ns,
401+
"tag": [f"t{i}" for i in ns],
402+
"filtered_cols": [state.filtered_cols] * size,
403+
"has_n": [state.has_n] * size,
404+
"has_tag": [state.has_tag] * size,
405+
"tag_values": [state.tag_values] * size,
406+
},
407+
schema=params.output_schema,
408+
)
409+
)
410+
state.cursor += size
411+
412+
290413
# ============================================================================
291414
# DictFilterEchoFunction — output column declared as a *dictionary* Arrow type
292415
# (dictionary<int8, utf8>) with no ENUM metadata. DuckDB maps such a column to

0 commit comments

Comments
 (0)