Monday, 18 January 2021

Filter method is behaving unexpectedly

I'm trying to introduce type hints into an existing codebase, but I'm running into an issue when I attempt to type my query.

from sqlalchemy.orm.query import Query

class DbContext:
    def __init__(self, db_host, db_port, db_name, db_user, db_password):

        engine = create_engine(...)

        session = sessionmaker(bind=engine)
        self.Session: Session = session(bind=engine)

...

def fetch(context: DbContext
   sub_query: Query = context.Session.query(...)

Before I added type hints, filtering dynamically was simply a matter of:

if filters.name is not None:
   sub_query = sub_query.name(
                Person.name.ilike(f"%{filters.name}%"))

However, now with hinting I'm getting this error:

Expression of type "None" cannot be assigned to declared type "Query"

Sure enough, filter appears to return None:

(method) filter: (*criterion: Unknown) -> None

I navigated to the source and it appears the method does indeed not return anything.

def filter(self, *criterion):
        for criterion in list(criterion):
            criterion = expression._expression_literal_as_text(criterion)

            criterion = self._adapt_clause(criterion, True, True)

            if self._criterion is not None:
                self._criterion = self._criterion & criterion
            else:
                self._criterion = criterion

There's obviously a disconnect somewhere, as assigning None to sub_query should result in an error which the hint is warning against, but I need to perform the assignment for the filtering to actually work:

# Does NOT work, filtering is not applied
if filters.name is not None:
  sub_query.filter(
               Person.name.ilike(f"%{filters.name}%"))

# Works but Pylance complains
if filters.name is not None:
  sub_query = sub_query.filter(
               Person.name.ilike(f"%{filters.name}%"))

This is my first foray into Python, would love some guidance as to what is going on here!



from Filter method is behaving unexpectedly

No comments:

Post a Comment