Make square braces only return tables, not views

Breaking change for 4.0: db["name"] now only returns Table objects, never View objects.
This improves type safety since views lack methods like .insert().

Use db.view("view_name") to access views explicitly.

Closes #699
This commit is contained in:
Claude 2025-12-21 00:32:25 +00:00
commit c791a31047
No known key found for this signature in database
6 changed files with 18 additions and 15 deletions

View file

@ -12,6 +12,7 @@ from sqlite_utils.db import (
BadMultiValues,
DescIndex,
NoTable,
NoView,
quote_identifier,
)
from sqlite_utils.plugins import pm, get_plugins
@ -1796,9 +1797,10 @@ def drop_view(path, view, ignore, load_extension):
_register_db_for_cleanup(db)
_load_extensions(db, load_extension)
try:
db[view].drop(ignore=ignore)
except OperationalError:
raise click.ClickException('View "{}" does not exist'.format(view))
db.view(view).drop(ignore=ignore)
except NoView:
if not ignore:
raise click.ClickException('View "{}" does not exist'.format(view))
@cli.command()

View file

@ -445,15 +445,15 @@ class Database:
finally:
self._tracer = prev_tracer
def __getitem__(self, table_name: str) -> Union["Table", "View"]:
def __getitem__(self, table_name: str) -> "Table":
"""
``db[table_name]`` returns a :class:`.Table` object for the table with the specified name.
If the table does not exist yet it will be created the first time data is inserted into it.
Use ``db.view(view_name)`` to access views.
:param table_name: The name of the table
"""
if table_name in self.view_names():
return self.view(table_name)
return self.table(table_name)
def __repr__(self) -> str:
@ -1206,9 +1206,9 @@ class Database:
return self
elif replace:
# If SQL is the same, do nothing
if create_sql == self[name].schema:
if create_sql == self.view(name).schema:
return self
self[name].drop()
self.view(name).drop()
self.execute(create_sql)
return self