How to specify nested type hint for a shelve object?

139 Views Asked by At

Trying to use the Python persistence library shelve

import shelve


cache = shelve.open("path/to/cache")
cache["b"] = 3
cache.sync()

This works fine.

Now I want to specify a type hint, so that I can use specific shelve functions inside other functions without worrying:

def foo(cache: Dict[str, int]):
    cache["c"] = 2
    cache.sync()

This (correctly) warns be that Dict has no sync.

Trying

from shelve import DbfilenameShelf


def foo(cache: DbfilenameShelf[str, int]):
    cache["c"] = 2
    cache.sync()

gives

Traceback (most recent call last):
  File ".../ssss.py", line 11, in <module>
    def foo(cache: DbfilenameShelf[str, int]):
TypeError: 'ABCMeta' object is not subscriptable

What does work is

from shelve import DbfilenameShelf


def foo(cache: DbfilenameShelf):
    cache["c"] = 2
    cache.sync()

Is it possible to specify the types of the shelve object in a type hint?

Full code for copy-paste

from typing import Dict
import shelve
from shelve import DbfilenameShelf


def main():
    cache = shelve.open("path/to/cache")
    cache["b"] = 3
    cache.sync()

def foo0(cache: Dict[str, int]):
    cache["c"] = 2
    cache.sync()

def foo1(cache: DbfilenameShelf[str, int]):
    cache["c"] = 2
    cache.sync()
    
def foo2(cache: DbfilenameShelf):
    cache["c"] = 2
    cache.sync()
1

There are 1 best solutions below

0
joel On

This might require an intersection of DbfilenameShelf with MutableMapping which isn't possible atm. You could, for this mcve, use a protocol

class Foo(Protocol[K, V]):
    def sync(self) -> None:
        ...

    def __setitem__(self, k: K, v: V) -> None:
        ...

def foo(cache: Foo[str, int]) -> None:
    cache["c"] = 2
    cache.sync()

but that might not scale to your full use-case.