Skip to content

Commit 508fddc

Browse files
rustyconoverclaude
andcommitted
docs: document class members across the core package
Add Google-style `Attributes:` sections (and a few method `Args:`/`Returns:`/ `Yields:` sections) to ~80 previously-undocumented core classes so their members render in the API docs and are covered by the pydoclint gate. The protocol contract is the headline: every protocol.py request/response dataclass (BindRequest, InitRequest, the aggregate/table-buffering/window messages, catalog create/attach requests, etc.) now documents each wire field, using a consistent vocabulary for recurring fields (attach_opaque_data, execution_id, function_name, transaction_opaque_data, output_schema, ...). Also covered: metadata.ResolvedMetadata, the table_filter_pushdown AST nodes, table_function/table_in_out_function params, aggregate_function (AggregateBindParams, AggregateFunction.state_class), worker/client/catalog/ secret/codegen data classes, and table_buffering_function.Meta. Inline `#` field comments were folded into the docstrings where present. Because each documented class now has a multi-line docstring, the existing pydoclint gate enforces its attribute completeness going forward — no config change or baseline needed. (skip_checking_short_docstrings stays default; the remaining one-line-docstring classes/methods are intentionally not gated.) Docstrings only; no runtime behavior changed. mypy clean, gate clean, tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e5afadd commit 508fddc

20 files changed

Lines changed: 1476 additions & 187 deletions

‎vgi/aggregate_function.py‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,15 @@
4646

4747
@dataclass(slots=True, frozen=True, kw_only=True)
4848
class AggregateBindParams:
49-
"""Parameters passed to `AggregateFunction.on_bind()`."""
49+
"""Parameters passed to `AggregateFunction.on_bind()`.
50+
51+
Attributes:
52+
args: The bound function [`Arguments`][], or ``None`` if none.
53+
input_schema: Arrow schema of the aggregate's input columns, or ``None``.
54+
settings: DuckDB session settings relevant to the function.
55+
secrets: Accessor for the resolved secrets the function declared.
56+
auth_context: The caller's authentication context (anonymous by default).
57+
"""
5058

5159
args: Arguments | None
5260
input_schema: pa.Schema | None
@@ -136,6 +144,11 @@ def finalize(
136144
) -> Annotated[pa.RecordBatch, Returns(pa.int64())]:
137145
...
138146
147+
Attributes:
148+
state_class: The resolved ``TState`` dataclass used for per-group
149+
accumulation state, inferred from the generic parameter; ``None``
150+
until resolved by ``__init_subclass__``.
151+
139152
"""
140153

141154
state_class: type[TState] | None = None

‎vgi/arguments.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ class IdentityFunction(TableFunctionGenerator):
344344
Unlike [`TableInput`][], [`AnyArrow`][] arguments have actual Arrow values -
345345
they are just not constrained to a specific Arrow type.
346346
347+
Attributes:
348+
value: The resolved Arrow value of the argument.
349+
position: The argument's positional index or name used to resolve it.
350+
name: The argument's name.
347351
"""
348352

349353
# Type stubs for static analysis - at runtime, Arg[AnyArrow] returns AnyArrowValue
@@ -1618,6 +1622,12 @@ class SecretLookupEntry(ArrowSerializableDataclass):
16181622
- By type + scope: SecretLookupEntry(secret_type="s3", scope="s3://bucket/")
16191623
- By type + name: SecretLookupEntry(secret_type="s3", secret_name="my_cred")
16201624
- By type + scope + name: all three fields set
1625+
1626+
Attributes:
1627+
secret_type: The DuckDB secret type to match (required; C++ enforces
1628+
type matching).
1629+
scope: Optional URI prefix the secret must apply to.
1630+
secret_name: Optional name of the specific secret to resolve.
16211631
"""
16221632

16231633
secret_type: str

‎vgi/catalog/catalog_interface.py‎

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,14 @@ class MacroInfo(CatalogSchemaObject, ArrowSerializableDataclass):
445445

446446

447447
class FunctionType(Enum):
448-
"""The type of function in a schema."""
448+
"""The type of function in a schema.
449+
450+
Attributes:
451+
SCALAR: A scalar function.
452+
TABLE: A table function.
453+
TABLE_BUFFERING: A table-buffering (table-in-out) function.
454+
AGGREGATE: An aggregate function.
455+
"""
449456

450457
SCALAR = "scalar"
451458
TABLE = "table"
@@ -454,7 +461,12 @@ class FunctionType(Enum):
454461

455462

456463
class MacroType(Enum):
457-
"""The type of macro in a schema."""
464+
"""The type of macro in a schema.
465+
466+
Attributes:
467+
SCALAR: A scalar macro.
468+
TABLE: A table macro.
469+
"""
458470

459471
SCALAR = "scalar"
460472
TABLE = "table"
@@ -463,9 +475,10 @@ class MacroType(Enum):
463475
class IndexConstraintType(Enum):
464476
"""The constraint type of an index.
465477
466-
NONE: Regular index (no constraint enforcement).
467-
UNIQUE: Index enforces a UNIQUE constraint.
468-
PRIMARY: Index enforces a PRIMARY KEY constraint.
478+
Attributes:
479+
NONE: Regular index (no constraint enforcement).
480+
UNIQUE: Index enforces a UNIQUE constraint.
481+
PRIMARY: Index enforces a PRIMARY KEY constraint.
469482
"""
470483

471484
NONE = "none"
@@ -499,6 +512,16 @@ class SchemaObjectType(Enum):
499512
"""The type of object that can exist within a schema.
500513
501514
Used to filter results from schema_contents().
515+
516+
Attributes:
517+
TABLE: A table.
518+
VIEW: A view.
519+
SCALAR_FUNCTION: A scalar function.
520+
TABLE_FUNCTION: A table function.
521+
AGGREGATE_FUNCTION: An aggregate function.
522+
SCALAR_MACRO: A scalar macro.
523+
TABLE_MACRO: A table macro.
524+
INDEX: An index.
502525
"""
503526

504527
TABLE = "table"
@@ -514,9 +537,10 @@ class SchemaObjectType(Enum):
514537
class OnConflict(Enum):
515538
"""Behavior when a conflict occurs during creation of an object.
516539
517-
IGNORE: Do nothing if the object already exists.
518-
REPLACE: Replace the existing object if it already exists.
519-
ERROR: Raise an error if the object already exists.
540+
Attributes:
541+
ERROR: Raise an error if the object already exists.
542+
IGNORE: Do nothing if the object already exists.
543+
REPLACE: Replace the existing object if it already exists.
520544
"""
521545

522546
ERROR = "error"
@@ -2096,6 +2120,47 @@ class ReadOnlyCatalogInterface(CatalogInterface):
20962120
All DDL operations (create, drop, rename, modify) will raise
20972121
[`CatalogReadOnlyError`][].
20982122
2123+
Attributes:
2124+
supports_transactions: Always ``False`` -- read-only catalogs do not
2125+
support transactions.
2126+
catalog_version_frozen: Always ``True`` -- the catalog version never
2127+
changes.
2128+
catalog_name: Name of the catalog exposed when using the functions-list
2129+
mode (default ``"functions"``).
2130+
functions: Function classes to expose in the ``"main"`` schema.
2131+
settings: DuckDB setting specs the catalog declares.
2132+
secret_types: Secret type specs the catalog declares.
2133+
attach_option_specs: Attach option specs accepted at ``ATTACH`` time.
2134+
catalog: Optional declarative `[`Catalog`][]` object describing the
2135+
catalog's schemas, tables, and views.
2136+
catalog_create: DDL stub that raises `[`CatalogReadOnlyError`][].
2137+
catalog_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2138+
catalog_transaction_begin: DDL stub that raises `[`CatalogReadOnlyError`][].
2139+
catalog_transaction_commit: DDL stub that raises `[`CatalogReadOnlyError`][].
2140+
catalog_transaction_rollback: DDL stub that raises `[`CatalogReadOnlyError`][].
2141+
schema_create: DDL stub that raises `[`CatalogReadOnlyError`][].
2142+
schema_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2143+
table_create: DDL stub that raises `[`CatalogReadOnlyError`][].
2144+
table_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2145+
table_comment_set: DDL stub that raises `[`CatalogReadOnlyError`][].
2146+
table_column_comment_set: DDL stub that raises `[`CatalogReadOnlyError`][].
2147+
table_rename: DDL stub that raises `[`CatalogReadOnlyError`][].
2148+
table_column_add: DDL stub that raises `[`CatalogReadOnlyError`][].
2149+
table_column_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2150+
table_column_rename: DDL stub that raises `[`CatalogReadOnlyError`][].
2151+
table_column_default_set: DDL stub that raises `[`CatalogReadOnlyError`][].
2152+
table_column_default_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2153+
table_column_type_change: DDL stub that raises `[`CatalogReadOnlyError`][].
2154+
table_not_null_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2155+
table_not_null_set: DDL stub that raises `[`CatalogReadOnlyError`][].
2156+
view_create: DDL stub that raises `[`CatalogReadOnlyError`][].
2157+
view_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2158+
view_rename: DDL stub that raises `[`CatalogReadOnlyError`][].
2159+
view_comment_set: DDL stub that raises `[`CatalogReadOnlyError`][].
2160+
macro_create: DDL stub that raises `[`CatalogReadOnlyError`][].
2161+
macro_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
2162+
index_create: DDL stub that raises `[`CatalogReadOnlyError`][].
2163+
index_drop: DDL stub that raises `[`CatalogReadOnlyError`][].
20992164
"""
21002165

21012166
supports_transactions = False

‎vgi/catalog/descriptors.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ class ColumnStatisticsInput:
107107
# Explicit PyArrow scalars
108108
ColumnStatisticsInput(min=pa.scalar(1, pa.int32()), max=pa.scalar(100, pa.int32()))
109109
110+
Attributes:
111+
min: Minimum value as a Python literal or PyArrow scalar, or ``None`` if
112+
unknown.
113+
max: Maximum value as a Python literal or PyArrow scalar, or ``None`` if
114+
unknown. Must share the column's Arrow type with ``min``.
115+
has_null: Whether the column contains any null values.
116+
has_not_null: Whether the column contains any non-null values.
117+
distinct_count: Approximate count of distinct values, or ``None`` if
118+
unknown.
119+
contains_unicode: String/binary columns only -- whether values contain
120+
non-ASCII characters. ``None`` for non-string columns.
121+
max_string_length: String/binary columns only -- maximum byte length of
122+
values. ``None`` for non-string columns.
110123
"""
111124

112125
min: StatValue = None

‎vgi/catalog/storage.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,12 @@ class CatalogStorageSqlite:
139139
- catalog_attachments: Maps attach_opaque_data to catalog name and options
140140
- catalog_transactions: Tracks active transactions
141141
142+
Attributes:
143+
db_path: Filesystem path to the backing SQLite database file.
142144
"""
143145

146+
db_path: str
147+
144148
def __init__(self, db_path: str | None = None) -> None:
145149
"""Initialize SQLite catalog storage.
146150

‎vgi/client/catalog_mixin.py‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,12 @@ class CatalogClientMixin:
9393
``httpx.Client`` (bearer token, headers). Browsing catalogs over HTTP
9494
is the canonical non-DuckDB use case this mixin supports.
9595
96-
Expected attributes from ``Client``:
97-
server_path: str — worker shell command (subprocess transport).
98-
_transport: Literal["subprocess", "http"].
99-
_base_url: str | None — HTTP base URL.
100-
_get_or_create_httpx_client(): shared HTTP client factory.
96+
Other attributes expected from ``Client``: ``_transport`` (subprocess vs
97+
http), ``_base_url`` (HTTP base URL), and ``_get_or_create_httpx_client()``
98+
(shared HTTP client factory).
99+
100+
Attributes:
101+
server_path: Worker shell command used for subprocess transport.
101102
"""
102103

103104
# Type hints for attributes expected from Client
@@ -122,6 +123,9 @@ def _catalog_connect(self) -> Iterator[VgiProtocol]:
122123
connection pooling are consistent.
123124
124125
Worker errors are caught and re-raised as ``CatalogClientError``.
126+
127+
Yields:
128+
A typed `[`VgiProtocol`][]` proxy bound to the active transport.
125129
"""
126130
try:
127131
if getattr(self, "_transport", "subprocess") == "http":

‎vgi/client/client.py‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,13 @@ class WorkerConnection:
201201
202202
Exactly one of {proc+connection, _pool_ctx, _http_ctx} is active per
203203
connection — transport-specific teardown inspects these fields.
204+
205+
Attributes:
206+
proxy: The typed `[`VgiProtocol`][]` proxy used to invoke the worker.
207+
worker_index: Index of this worker within a parallel pool.
208+
stream: The active streaming session, if any.
209+
proc: The worker subprocess for direct (non-pooled) subprocess transport.
210+
connection: The RPC connection for direct subprocess transport.
204211
"""
205212

206213
proxy: VgiProtocol
@@ -242,12 +249,15 @@ class Client(CatalogClientMixin):
242249
with Client.from_http("http://host:port", bearer_token="...") as c:
243250
for batch in c.table_function(function_name="sequence", ...):
244251
...
252+
253+
Attributes:
254+
THREAD_JOIN_TIMEOUT: Seconds to wait for a worker thread to join during
255+
shutdown.
256+
PROCESS_WAIT_TIMEOUT: Seconds to wait for a worker process to exit during
257+
shutdown.
245258
"""
246259

247-
# Timeout for thread join operations (seconds)
248260
THREAD_JOIN_TIMEOUT: float = 5.0
249-
250-
# Timeout for worker process wait operations (seconds)
251261
PROCESS_WAIT_TIMEOUT: float = 5.0
252262

253263
@staticmethod

‎vgi/codegen/_common.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,17 @@ class EmittedSchema:
6969
7070
`name` is the factory/function/const stem (CamelCase, no trailing `Schema`);
7171
emitters are free to append whatever suffix their output language idiom uses.
72+
73+
Attributes:
74+
name: The factory/function/const stem (CamelCase, no trailing ``Schema``).
75+
schema: The Arrow schema to emit.
76+
origin: Human-readable source of the schema (e.g. ``"method
77+
'catalog_catalogs' result"``), used in generated comments.
7278
"""
7379

7480
name: str
7581
schema: pa.Schema
76-
origin: str # e.g. "method 'catalog_catalogs' result"
82+
origin: str
7783

7884

7985
def sanitize_name(name: str) -> str:

‎vgi/codegen/cpp_constants.py‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,18 @@
4040

4141

4242
class _ByteConstant(NamedTuple):
43-
"""One C++-visible byte constant sourced from the Python vgi_rpc package."""
43+
"""One C++-visible byte constant sourced from the Python vgi_rpc package.
4444
45-
cpp_name: str # emitted as `inline constexpr std::string_view {cpp_name}`
46-
python_name: str # key in vgi_rpc.metadata
47-
description: str # one-liner for the doc comment
45+
Attributes:
46+
cpp_name: Identifier emitted as ``inline constexpr std::string_view
47+
{cpp_name}``.
48+
python_name: Key in ``vgi_rpc.metadata`` whose value supplies the bytes.
49+
description: One-liner used for the generated doc comment.
50+
"""
51+
52+
cpp_name: str
53+
python_name: str
54+
description: str
4855

4956

5057
# Ordered list of constants to emit. Add new entries here, regenerate,

‎vgi/codegen/ts_client.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ def _info(name: str) -> type:
110110

111111
@dataclasses.dataclass
112112
class _Ctx:
113+
"""Mutable codegen context tracking emitted TypeScript types.
114+
115+
Attributes:
116+
dataclasses_seen: Maps each registered Python dataclass to its emitted
117+
TypeScript type name.
118+
enums_seen: Maps each registered Python enum to its emitted TypeScript
119+
type name.
120+
dataclass_order: Dataclasses in the order they should be emitted.
121+
enum_order: Enums in the order they should be emitted.
122+
"""
123+
113124
dataclasses_seen: dict[type, str] = dataclasses.field(default_factory=dict)
114125
enums_seen: dict[type, str] = dataclasses.field(default_factory=dict)
115126
dataclass_order: list[type] = dataclasses.field(default_factory=list)

0 commit comments

Comments
 (0)