0

I'm trying to use PyMongo in a type safe(ish) way in VS Code. I've tried following the type hints section in the PyMongo documentation and arrived at the following (app is a Flask instance):

from typing import Any, TypedDict
from pymongo import MongoClient
from app import app
from pymongo.collection import Collection

class Movie(TypedDict):
    title: str
    genres: list[str]

def get_db():
    conn_string = str(app.config['MONGO_URI'])
    return MongoClient[dict[str, Any]](conn_string)

@app.route('/test')
def models():
    client = get_db()
    db = client['sample_mflix']
    coll: Collection[Movie] = cast(Collection[Movie], db['movies'])

    genres = list(coll.aggregate([
        {"$unwind": "$genres"},
        {"$group": {"_id": None, "genres": {"$addToSet": "$genres"}}}
    ]))[0]['genres']

    return make_response(jsonify(genres), 200)

I realize that the error stems from the fact that I've typed db to be dict[str, Any], so the type of the collection is Collection[dict[str, Any]] requiring a cast to the type (Movie). I could get around this if typed the client as MongoClient[Movie], but presumably, I will want to interact with collections other than the movies collection.

Should I make a client per collection? Live with the cast? Some other pattern I'm missing?

1

1 Answer 1

0

While using type hinting is a great idea, they are just hints and it will not create anything remotely "type safe". That just isn't a thing in python.

So using TypedDict or cast will not help you at runtime.

A better option is to use a validation library like pydantic, model your expected requests and response and validate each record.

Furthermore you might want to consider $jsonSchema.

Sign up to request clarification or add additional context in comments.

1 Comment

Appreciate the response. I realize saying "type safe" was a misnomer, and I understand they are simply hints that have no effect at runtime. Was simply aspiring to write code that improves the DX provided by type hints.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.