fix!(QueryList): Generic fixes #515
                
     Merged
            
            
          
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
ChatGPT helped!
Part 1
Prompt
Assume this:
What would it take to make
QueryListbehave as a generic list type? Right now (as-is)QueryList[CustomObjectType]is not a valid annotation according to mypy.Response:
Response
To make
QueryListbehave as a generic list type and ensure it's recognized as such by static type checkers like mypy, you need to ensure that it correctly inherits from a generic type and uses type annotations properly throughout its definition. The modifications needed involve leveraging the typing system to annotateQueryListas a generic collection properly.Here are the steps to make
QueryLista properly typed, generic list in Python:Ensure Proper Inheritance: The
QueryListshould inherit fromtyping.Genericandcollections.abc.Sequence(or another appropriate base class) to get list-like behavior while also being generic. You've already importedGenericand are usingTypeVar, which is great. However, yourQueryListdefinition should explicitly indicate it's generic over some typeT.Use the TypeVar Correctly: You declared a
TypeVarnamedTbut didn't use it effectively withinQueryListto ensure it's recognized as a generic class by type checkers. You should useTas a placeholder for the type of items contained in theQueryList.Annotate
dataAttribute: Thedataattribute inQueryListshould be annotated to indicate it holds a sequence of typeTelements. However, this attribute seems redundant ifQueryListitself behaves like a list; you might be intending to useselfto store the data directly.Correct Method Annotations: Ensure all methods that operate on elements of the list use the
Ttype variable appropriately. This includes methods that add, remove, retrieve, or operate on elements in any way, ensuring they are compatible with the generic typeT.Update
__init__Method: YourQueryListdoesn't explicitly define an__init__method to initialize the list. It's important to properly initialize the internal list structure that will hold the data.Below is an updated example that incorporates these suggestions:
This example assumes
QueryListdirectly inherits list-like behavior fromList[T]and adds typing information to make it a generic class capable of holding items of any specified type. It demonstrates how to initialize it with items of typeTand includes a placeholder for afiltermethod that should be implemented according to your specific needs.Remember, when you're using
QueryList[CustomObjectType], theCustomObjectTypeneeds to be a class or type alias that mypy can recognize. Also, make sure your runtime logic correctly handles the types you expectQueryListto contain, as Python's type annotations are not enforced at runtime.Part 2
Prompt
Consider the following:
What do I need to do to solve these mypy warnings:
Response:
Response
To resolve the mypy warnings you're encountering, you need to address type compatibility and the correct use of generics in your
QueryListclass. Let's go through each error and discuss the solutions:Error 1: List comprehension has incompatible type List[tuple[Any, T]]; expected List[T]
This error occurs in the
itemsmethod. The method signature implies it returns a list of typeT, but the actual implementation returns a list of tuples. To fix this, you should adjust either the method's return type to accurately reflect the returned data or change the method's functionality to match the expected return type. Since the method's purpose seems to be returning items along with their primary keys, adjusting the return type annotation is the appropriate solution.Solution:
Error 2: Incompatible types in assignment
This error indicates a mismatch in the expected callable type in your
filtermethod. The_filtervariable is expected to be a callable that takes an item of typeTand returns a boolean. However, the assignment toval_matchdoesn't match this signature becauseval_matchis defined to take either a string or a list of any type. This discrepancy arises due to the flexible nature ofmatcher, which can be a list, affecting the expected type of objects passed to_filter.Solution:
To resolve this, you should ensure that the lambda or function assigned to
_filteralways matches the expected signature,(T) -> bool. Ifmatchercan be of different types, handle the type checking inside the callable, ensuring it always accepts an argument of typeTand returns a boolean.In this solution,
val_matchassumes thatobjcan be compared directly to the items inmatcheror tomatcheritself. You might need to adjust this logic depending on the typesTcan represent, especially ifTis not guaranteed to be comparable with the types inmatcher.General Note on Type Checking and Generics
When working with generics and type checking in Python, especially with complex class behaviors like
QueryList, it's crucial to ensure that all type annotations accurately reflect the intended use and behaviors of your class methods. This includes being precise about the types of arguments, return values, and the handling of generic type variables throughout the class. Remember that mypy's type checking is based on the static analysis of these annotations, so discrepancies between the annotations and the actual code logic will lead to warnings or errors.