simonw / sqlite-utils

Python CLI utility and library for manipulating SQLite databases
https://sqlite-utils.datasette.io
Apache License 2.0
1.67k stars 111 forks source link

Mypy & Pyright show errors for basic sqlite-utils usage #638

Open etjones opened 2 months ago

etjones commented 2 months ago

Duplicate of the unresolved closed bug #607.

Here's perfectly valid sqlite_utils code that raises objections from Mypy & Pyright/PyLance in VS Code:

#! /usr/bin/env python3

from sqlite_utils import Database

# Create or connect to the database
db = Database("example.db")

# Create a table with an autoincrementing primary key
"""
Mypy/Pylance objects to the create() call with the error:
    "Cannot access attribute "create" for class "View"
Attribute "create" is unknownPylancereportAttributeAccessIssue
"""
db["my_table"].create(
    {"id": int, "name": str, "value": int}, pk="id", if_not_exists=True
)

"""
Mypy/Pylance objects to the upsert() call with the same error.
It also objects to the pk="id" argument, with error:
    "Argument of type "Literal['id']" cannot be assigned to parameter "pk" of type "Default"
    "Literal['id']" is incompatible with "Default"
"""
db["my_table"].upsert({"name": "example", "value": 42}, pk="id")

# Verify the data
print(list(db["my_table"].rows))

Is there a workaround or another approach that wouldn't throw these spurious errors?

etjones commented 2 months ago

Here's a pattern that casts calls to DB[] to Table, but it's verbose:

from sqlite_utils import Database
from sqlite_utils.db import Table
from typing import cast

DB = Database("example.db")
table = cast(Table, DB["my_table"]) # this avoids errors, but it's a mouthful every time you use a table
table.upsert({"name": "example", "value": 42}, pk="id") # upsert() call is happy, although literal "id" is sometimes an issue