schema icon indicating copy to clipboard operation
schema copied to clipboard

Type checker reports error when using the `Use` class in a boolean operator

Open PleasantFuban opened this issue 1 year ago • 7 comments

Here is a minimal example:

schema = Schema({
    'party': And(str, Use(str.lower), lambda s: s in ('alice', 'bob'))
})

This code works fine. However, the type checker reports an error saying that a Use instance cannot be used as an argument of And(). This is true in both VS Code (which uses pyright by default) and PyCharm.

I'm using similar validation rules in many places. As a result, my code is full of # type: ignores because otherwise I will have to disable type checking completely.

Is it possible to solve this issue?

PleasantFuban avatar Jul 23 '24 04:07 PleasantFuban

I am not able to reproduce your issue. Is mypy also complaining ? what version of python/schema are you using ?

mutricyl avatar Aug 22 '24 09:08 mutricyl

Mypy does not complain in that minimal example (even when in strict mode), but does complain when moving And out of the schema:

And(str, Use(str.lower), lambda s: s in ('alice', 'bob'))
# Mypy reports: Argument 2 to "And" has incompatible type "Use"; expected "Callable[..., Any]"
# VS Code (pyright) reports: The type 'Use' is incompatible with the types 'Schema' and '(...) -> Any'
# PyCharm reports something similar to VS Code

{'party': And(str, Use(str.lower), lambda s: s in ('alice', 'bob'))}
# Mypy still complains

Schema({'party': And(str, Use(str.lower), lambda s: s in ('alice', 'bob'))})
# Mypy does not report anything

I haven't used Mypy before, so I'm not sure if it is a bug.

I'm using schema 0.7.7 on Python 3.12. Mypy's version 1.11.1.

PleasantFuban avatar Aug 23 '24 04:08 PleasantFuban

ok, I now have the same issue. No solution yet but as a dirty workaround you can replace

Use(str.lower)

with

eval("Use(str.lower)")

mutricyl avatar Aug 23 '24 14:08 mutricyl

ok, I now have the same issue. No solution yet but as a dirty workaround you can replace

Use(str.lower)

with

eval("Use(str.lower)")

That's really ugly. Why not just ignore the error?

# type: ignore

HorridModz avatar Aug 24 '24 17:08 HorridModz

@mutricyl By the way, not to criticize, but I noticed your markdown code snippet looks like this (copy and pasted from your comment):

> ```python
> print("Hello World!")
> ```

Those greater than symbols are unnecessary. Just typing ``` is sufficient:

```python
print("Hello World!")
```

Hope this helps!

HorridModz avatar Aug 24 '24 17:08 HorridModz

ok, I now have the same issue. No solution yet but as a dirty workaround you can replace

Use(str.lower)

with

eval("Use(str.lower)")

Understood, thank you. Now I've put all schemas in a single file, so I can just disable type checking for that file. I'm comfortable with this.

PleasantFuban avatar Aug 26 '24 02:08 PleasantFuban

I agree that the eval trick is ugly. You can narrow the type ignore to the specific issue : # type: ignore[call-arg] likewise if pyright complains: # pyright: ignore[<whateverPyrightIssueName>]

Apparently mypy does not consider Use as being a callable. I have added a __call__ function to Use class and it looks to solve the issue.

class Use:
 
(...)

    def __call__(self, *args: Any, **kwds: Any) -> Any:
        pass

However I still have an issue mixing And and Or.

mutricyl avatar Aug 26 '24 14:08 mutricyl