typeddjango / pytest-mypy-plugins

pytest plugin for testing mypy types, stubs, and plugins
https://pypi.org/project/pytest-mypy-plugins/
MIT License
100 stars 26 forks source link

Skip templating `mypy_config` if no placeholders exist #124

Closed stdedos closed 1 year ago

stdedos commented 1 year ago

The solution to if-return on the render_template was selected, as the shortest one (vs modifying the pytest_mypy_plugins/collect.py file)

stdedos commented 1 year ago

In hoel-bagard/matplotlib-stubs@418c849 (#1), I tried to make [call-overload] and main:5: note:s disappear

___________________________________________________________________ Colormap_does_not_accept_str_bool_and_pandas_types[val="0",rt=str] ____________________________________________________________________
test/matplotlib/test_colors.yml:23: 
E   pytest_mypy_plugins.utils.TypecheckAssertionError: Invalid output: 
E   Actual:
E     main:5: error: No overload variant of "__call__" of "Colormap" matches argument type "str"  [call-overload] (diff)
E     main:5: note: Possible overload variants:     (diff)
E     main:5: note:     def __call__(self, X: Union[int, float], alpha: Optional[float], bytes: bool = ...) -> Tuple[float, float, float, float] (diff)
E     main:5: note:     def __call__(self, X: ndarray[Any, dtype[Union[int, float]]], alpha: Union[float, Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]], None] = ..., bytes: bool = ...) -> ndarray[Any, dtype[Tuple[float, float, float, float]]] (diff)
E   Expected:
E     main:5: error: No overload variant of "__call__" of "Colormap" matches argument type "str" (diff)
E   Alignment of first line difference:
E     E: ... argument type "str"
E     A: ... argument type "str"  [call-overload]
E                               ^

with these changes:

diff --git a/test/matplotlib/test_colors.yml b/test/matplotlib/test_colors.yml
index 332a379..c83cfa1 100644
--- a/test/matplotlib/test_colors.yml
+++ b/test/matplotlib/test_colors.yml
@@ -12,17 +12,15 @@
       rt: Timedelta
     - val: pd.Interval(left=0, right=1)
       rt: Interval[int]
+  mypy_config:
+    - hide_error_codes: True
+    - show_error_context: False
   main: |
     import matplotlib
     import pandas as pd

     colors = matplotlib.cm.get_cmap("viridis", 10)
-    colors({{ val }})
-  out: |  
-    main:5: error: No overload variant of "__call__" of "Colormap" matches argument type "{{ rt }}"  [call-overload]
-    main:5: note: Possible overload variants:    
-    main:5: note:     def __call__(self, X: Union[int, float], alpha: Optional[float], bytes: bool = ...) -> Tuple[float, float, float, float]
-    main:5: note:     def __call__(self, X: ndarray[Any, dtype[Union[int, float]]], alpha: Union[float, Union[_SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float, complex, str, bytes, _NestedSequence[Union[bool, int, float, complex, str, bytes]]], None] = ..., bytes: bool = ...) -> ndarray[Any, dtype[Tuple[float, float, float, float]]]
+    colors({{ val }})  # E: No overload variant of "__call__" of "Colormap" matches argument type "{{ rt }}"

 - case: Colormap_accepts_int_float
   parametrized:

My endeavor to write a less complex test sadly failed.

However, I had done the legwork already in pytest-mypy-plugins - and thought I'd submit it for consideration

sobolevn commented 1 year ago

Please, feel free to fix the docs in a separate PR! 👍

stdedos commented 1 year ago

Oh maaaaaaaaan. I figured out what was the actual problem 😓

PuDB 2022.1.3 - ?:help  n:next  s:step into  b:breakpoint  !:python command line [PROCESSING EXCEPTION - hit 'e' to examine]
   737         """Compile a node or template source code.  The `name` parameter is                                                  Variables:
   738         the load name of the template after it was joined using                                                              defer_init: False
   739         :meth:`join_path` if necessary, not the filename on the file system.                                                 filename: None
   740         the `filename` parameter is the estimated filename of the template on                                                name: None
   741         the file system.  If the template came from a database or memory this                                                raw: False
   742         can be omitted.                                                                                                      self: <jinja2.environment.Environment object at 0x7f49f5a29fa0>
   743                                                                                                                              source: [{'force_uppercase_builtins': True, '__line__': 16}, {'force_un
   744         The return value of this method is a python code object.  If the `raw`                                                 ion_syntax': True, '__line__': 17}]
   745         parameter is `True` the return value will be a string with python                                                    source_hint: None
   746         code equivalent to the bytecode returned otherwise.  This method is                                                  
   747         mainly used internally.                                                                                              
   748                                                                                                                              
   749         `defer_init` is use internally to aid the module code generator.  This                                               
   750         causes the generated code to be able to import without the global                                                    
   751         environment variable to be set.                                                                                      
   752                                                                                                                              Stack:
   753         .. versionadded:: 2.4                                                                                                   generate compiler.py:112
   754            `defer_init` parameter added.                                                                                        _generate [Environment] environment.py:689
   755         """                                                                                                                  >> compile [Environment] environment.py:761
   756         source_hint = None                                                                                                      from_string [Environment] environment.py:1105
   757         try:                                                                                                                    render_template utils.py:357
   758             if isinstance(source, str):                                                                                         collect [YamlTestFile] collect.py:135
   759                 source_hint = source                                                                                            <lambda> runner.py:372
   760                 source = self._parse(source, name, filename)                                                                    from_call runner.py:341
>  761             source = self._generate(source, name, filename, defer_init=defer_init)                                           
   762             if raw:                                                                                                          
   763                 return source                                                                                                
   764             if filename is None:                                                                                             
   765                 filename = "<template>"                                                                                      
   766             return self._compile(source, filename)                                                                           
   767         except TemplateSyntaxError:                                                                                          
   768             self.handle_exception(source=source_hint)                                                                        
   769                                                                                                                              
   770     def compile_expression(                                                                                                  
   771         self, source: str, undefined_to_none: bool = True                                                                    
   772     ) -> "TemplateExpression":                                                                                               
   773         """A handy helper method that returns a callable that accepts keyword                                                
   774         arguments that appear as variables in the expression.  If called it                                                  
   775         returns the result of the expression.                                                                                
   776                                                                                                                              
   777         This is useful if applications want to use the same rules as Jinja                                                   
   778         in template "configuration files" or similar situations.                                                             
   779                                                                                                                              
   780         Example usage:                                                                                                       
   781                                                                                                                              Breakpoints:
   782         >>> env = Environment()                                                                                              
   783         >>> expr = env.compile_expression('foo == 42')                                                                       
   784         >>> expr(foo=23)                                                                                                     
   785         False                                                                                                                
Command line: [Ctrl-X]                                                                                                              
>>> type(source)                                                                                                                    
<class 'list'>                                                                                                                      

>>>                                                                                                                      < Clear  > 

jinja "doesn't type-check enough", and "sort-of" giving a list continues okay - but also blows up down the road.

I haven't done formal analysis on the issue (and I think I won't), but my code works as a coincidence.

Also, technically, I can check the Environment, instead of the jinja.defaults

Don't create a release out of that; I'll fix it on top of documenting/asserting mypy_config input. Let's say ... sometime this week?