How do I tell the type checker that any subclass of ast.expr is ok?
              
              #1996
            
            
          Replies: 2 comments 6 replies
-
| 
         The complaint of the type checker is perfectly valid, since what you're doing is not type safe. I think what's tripping you up here is variance. While a return type is covariant, i.e. you can assign a function with a return type that is a subtype of the original function, the inverse is true for argument types, since they are contravariant. Consider the following example for covariance and contravariance: Or in other terms  What you can do however to solve this is to make  def funcAttribute[T: ast.expr](action: Callable[[T], T]) -> Callable[[hasDOTfunc], hasDOTfunc]:This way it will accept any callable that processes any node type that is either   | 
  
Beta Was this translation helpful? Give feedback.
-
| 
         I greatly appreciate how much information you have given me. While I think I understand the stack and how the interpreter handles identifiers, objects, and execution, type checking is still a black box to me. Therefore, I struggle to understand where the disconnections are. Understanding different options is challenging, too. I am working through what you wrote to understand the terms of art and technical options. I've also decided to make this less complicated by requiring Python >= 3.12 in the package. Disorganized thoughts, reactions, and information:"Type safe" is a strange term of art to me. When I or other people use the package, I want the type checkers (and language servers) to be helpful guides. With type checkers, I too often feel like I'm a student being "taught" in a 1935 Catholic school by a nun holding a paddle. Prototype of an old idea to subclass composable methods so that typing information can extend beyond the top level of the ast node.class ImaCallToName(ast.Call):
    func: ast.NameI made that subclass prototype before I made class ClassIsAndAttribute:
    ...
    @staticmethod
    def funcIs(astClass: type[hasDOTfunc], attributeCondition: Callable[[ast.expr], bool]) -> Callable[[ast.AST], TypeGuard[hasDOTfunc] | bool]:
        def workhorse(node: ast.AST) -> TypeGuard[hasDOTfunc] | bool:
            return isinstance(node, astClass) and attributeCondition(node.func)
        return workhorse
    ...I can't remember how I used it, but it's in the repo, of course (in mapFolding, here's a commit that includes it). I used the class in a TypeGuard antecedent, and ... (I can't communicate very well right now.) In short, it seemed to work very well. If identifier,  class IfThis:
    ...
    @staticmethod
    def isCallToName(node: ast.AST) -> TypeGuard[ImaCallToName]:
        return Be.Call(node) and Be.Name(DOT.func(node))
    ...If I used the above antecedent, and used the  That exact way of implementing is a combinatorics nightmare, though. To cover all cases, the quantity of necessary classes = sum of (for each class: for each attribute: attribute * number of valid types). If an attribute has type  TypeGuard / TypeIsI don't know if I am using TypeGuard correctly or to its full potential. I have no clue how to use TypeIs. Other Python toolsWith help from this forum, I implemented my first generic after many failed attempts. I have implemented TypeVar with some success exactly twice despite dozens of attempts. Protocol? pfft. A little contextI didn't mention in this thread that I don't have formal training as a programmer or professional programming experience. I started with line basic on a Vic-20 when I was 10 years old, but I am not a programmer. I did get a 53rd-percentile score on the Comp Sci GRE Subject Exam 20 years ago, which is strong evidence that I know the difference between a programmer and a person with a lot of computer knowledge. I worked in IT for 9 years, but sys/net admin, webmaster!, and teaching.  | 
  
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm so confused and frustrated that I don't know if I am asking the right questions.
Here is an example problem:
The relevant code
Offending statement
From this module.
The function
From this module.
The types
Mostly from this module.
One "fix"
Without cast, the type is effectively
Callable[[ast.Name], ast.Name]. SinceNameis a subclass ofexpr, I want the type checker to tell me that this is a valid statement. I mean,castis not a fix here because there isn't an error. The problem is that I haven't defined something in such a way that the type checker understands thatCallable[[ast.expr], ast.expr]includes subclasses ofast.expr.Beta Was this translation helpful? Give feedback.
All reactions