ML idZddlmZddlmZddlmZmZmZm Z m Z ddl m Z m Z ddlmZddlmZddlmZdd lmZdd lmZmZmZmZmZmZmZmZdd lm Z dd l!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(er dd l)m*Z*ddl+m,Z,e GddZ-Gdde Z.e dGddZ/e GddZ0e GddZ1Gdde Z2Gdde Z3Gdd e Z4Gd!d"e Z5Gd#d$e Z6Gd%d&e Z7Gd'd(e Z8Gd)d*e Z9e dGd+d,e/Z:e d-Z;Gd.d/e:Zr2ct)zBConstruct an instance of a generic type with given type arguments.r))r,namer6s r/named_generic_typez)CheckerPluginInterface.named_generic_typer1r2ct)z(Checks the type of the given expression.r))r,noder\s r/get_expression_typez*CheckerPluginInterface.get_expression_typer1r2)rAzlist[Type | None])r-zstr | ErrorMessager.rr&r@rAzErrorInfo | None)r`r?r6rCrArN)rcrr\ Type | NonerAr) rDrErFrGrHpropertyrr\r0rardrIr2r/rXrXs   I""TX"%",3"AQ" "" """"r2rXceZdZUdZded<ded<ded<ded <ed"d#d Zed$d Zed"d%d Zed&dZ ed'dZ ed(dZ e d)dd d d*dZ ed dddd d+dZ ed,dZed-dZed.dZe d) d/dZed"d0dZed1dZed2dZed3dZeed4dZeed4d Zed5d!Zy )6SemanticAnalyzerPluginInterfacezInterface for accessing semantic analyzer functionality in plugins. Methods docstrings contain only basic info. Look for corresponding implementation docstrings in semanal.py for more details. # TODO: clean-up lookup functions. dict[str, MypyFile]modulesrr$r? cur_mod_idr r-Nct)zBConstruct an instance of a builtin type with given type arguments.r)r4s r/r7z*SemanticAnalyzerPluginInterface.named_typer1r2ct)z,Legacy function -- use named_type() instead.r))r,fully_qualified_names r/ builtin_typez,SemanticAnalyzerPluginInterface.builtin_typer]r2ct)aConstruct an instance of a type with given type arguments. Return None if a type could not be constructed for the qualified type name. This is possible when the qualified name includes a module name and the module has not been imported. r)r4s r/named_type_or_nonez2SemanticAnalyzerPluginInterface.named_type_or_none "!r2ctrer))r,r`basetype_or_fallbacklines r/basic_new_typeinfoz2SemanticAnalyzerPluginInterface.basic_new_typeinfo(!!r2ct)zParse True/False literals.r)r,exprs r/ parse_boolz*SemanticAnalyzerPluginInterface.parse_bool,r1r2cy)zParse string literals.NrIrzs r/parse_str_literalz1SemanticAnalyzerPluginInterface.parse_str_literal1sr2F)blockerr&ctr(r))r,r-r.seriousrr&s r/r0z$SemanticAnalyzerPluginInterface.fail5s "!r2T) tvar_scopeallow_tuple_literalallow_unbound_tvarsreport_invalid_typesct)zAnalyze an unbound type. Return None if some part of the type is not ready yet. In this case the current target being analyzed will be deferred and analyzed again. r))r,r9rrrrs r/ anal_typez)SemanticAnalyzerPluginInterface.anal_typeBs ""!r2ct)zCGenerate type of first argument of class methods from type of self.r))r, self_types r/ class_typez*SemanticAnalyzerPluginInterface.class_typeUr1r2ct)z[Lookup a symbol by its fully qualified name. Raise an error if not found. r)rTs r/rz6SemanticAnalyzerPluginInterface.lookup_fully_qualifiedZ "!r2ct)zXLookup a symbol by its fully qualified name. Return None if not found. r)rTs r/lookup_fully_qualified_or_nonez>SemanticAnalyzerPluginInterface.lookup_fully_qualified_or_nonebrr2ct)z|Lookup symbol using a name in current scope. This follows Python local->non-local->global->builtins rules. r))r,r`r.suppress_errorss r/lookup_qualifiedz0SemanticAnalyzerPluginInterface.lookup_qualifiedjrsr2ct)aSpecify semantic dependencies for generated methods/variables. If the symbol with full name given by trigger is found to be stale by mypy, then the body of node with full name given by target will be re-checked. By default, this is the node that is currently analyzed. For example, the dataclass plugin adds a generated __init__ method with a signature that depends on types of attributes in ancestor classes. If any attribute in an ancestor class gets stale (modified), we need to reprocess the subclasses (and thus regenerate __init__ methods). This is used by fine-grained incremental mode (mypy daemon). See mypy/server/deps.py for more details. r))r,triggertargets r/add_plugin_dependencyz5SemanticAnalyzerPluginInterface.add_plugin_dependencyts "!r2ct)zFAdd node to global symbol table (or to nearest class if there is one).r))r,r`symbols r/add_symbol_table_nodez5SemanticAnalyzerPluginInterface.add_symbol_table_noder1r2ct)zFMake qualified name using current module and enclosing class (if any).r))r,r`s r/qualified_namez.SemanticAnalyzerPluginInterface.qualified_namer1r2ct)zCall this to defer the processing of the current node. This will request an additional iteration of semantic analysis. r)r[s r/deferz%SemanticAnalyzerPluginInterface.deferrr2ct)z1Is this the final iteration of semantic analysis?r)r[s r/final_iterationz/SemanticAnalyzerPluginInterface.final_iterationr]r2ctrer)r[s r/ is_stub_filez,SemanticAnalyzerPluginInterface.is_stub_filer1r2ctrer))r,rvalueis_finals r/analyze_simple_literal_typez;SemanticAnalyzerPluginInterface.analyze_simple_literal_typerxr2re)r5r?r6list[Type] | NonerAr)ror?rAr)r5r?r6rrAzInstance | None)r`r?rurrvintrAr)r{rrAz bool | None)r{rrA str | None)F) r-r?r.rrboolrrr&r@rArB) r9rrzTypeVarLikeScope | NonerrrrrrrArf)rrrAr)r5r?rArrU)r`r?r.rrrrArV)rr?rrrArB)r`r?rrrAr)r`r?rAr?)rArB)rAr)rrrrrArf)rDrErFrGrHrr7rprrrwr|r~r0rrrrrrrrrrgrrrrIr2r/ririsa! O """" """"""%%  " !% "  " " "  " "  " " /3$)$)%)" " , " " """#" ""$""""""?D""%"8<" """""""""""""""""r2ric,eZdZUded<ded<ded<y)ReportConfigContextr?idrYris_checkNrOrIr2r/rrs G INr2rc6eZdZUded<ded<ded<ded<y ) FunctionSigContextlist[list[Expression]]r6rdefault_signaturerrMrXrNNrOrIr2r/rrs  ##  r2rc^eZdZUded<ded<ded<ded<d ed <d ed <d ed<ded<y)FunctionContextlist[list[Type]] arg_typeslist[list[ArgKind]] arg_kindslist[str | None]callee_arg_nameslist[list[str | None]] arg_namesrdefault_return_typerr6rrMrXrNNrOrIr2r/rrs6""'&&%   r2rc@eZdZUded<ded<ded<ded<d ed <y ) MethodSigContextrrLrr6rrrrMrXrNNrOrIr2r/rrs   ##  r2rcheZdZUded<ded<ded<ded<d ed <d ed <d ed<ded<ded<y) MethodContextrrLrrrrrrrrrrrr6rrMrXrNNrOrIr2r/rrs8 ""&&%%   r2rc@eZdZUded<ded<ded<ded<d ed <y ) AttributeContextrrLrdefault_attr_typer is_lvaluerrMrXrNNrOrIr2r/rrs O  r2rc,eZdZUded<ded<ded<y)ClassDefContextrclsrreasonrirNNrOrIr2r/rrs M  ((r2rc,eZdZUded<ded<ded<y)DynamicClassDefContextrcallr?r`rirNNrOrIr2r/rrs N I ((r2rceZdZdZddZddZddZddZddZddZ ddZ dd Z dd Z dd Z dd Zdd Zd dZ d!dZd dZd dZ d dZ d"dZy)#PluginaBase class of all type checker plugins. This defines a no-op plugin. Subclasses can override some methods to provide some actual functionality. All get_ methods are treated as pure functions (you should assume that results might be cached). A plugin should return None from a get_ method to give way to other plugins. Look at the comments of various *Context objects for additional information on various hooks. cB||_|j|_d|_yre)r$python_version_modules)r,r$s r/__init__zPlugin.__init__s  %4459 r2c||_yre)r)r,rks r/ set_moduleszPlugin.set_moduless  r2cJ|jJt||jSre)rrrTs r/rzPlugin.lookup_fully_qualified!s#}}(((%h >>r2cy)aGet representation of configuration data for a module. The data must be encodable as JSON and will be stored in the cache metadata for the module. A mismatch between the cached values and the returned will result in that module's cache being invalidated and the module being rechecked. This can be called twice for each module, once after loading the cache to check if it is valid and once while writing new cache information. If is_check in the context is true, then the return of this call will be checked against the cached version. Otherwise the call is being made to determine what to put in the cache. This can be used to allow consulting extra cache files in certain complex situations. This can be used to incorporate external configuration information that might require changes to typechecking. NrI)r,r.s r/report_config_datazPlugin.report_config_data%s*r2cgS)a;Customize dependencies for a module. This hook allows adding in new dependencies for a module. It is called after parsing a file but before analysis. This can be useful if a library has dependencies that are dynamic based on configuration information, for example. Returns a list of (priority, module name, line number) tuples. The line number can be -1 when there is not a known real line number. Priorities are defined in mypy.build (but maybe shouldn't be). 10 is a good choice for priority. rI)r,files r/get_additional_depszPlugin.get_additional_deps<s  r2cy)a+Customize behaviour of the type analyzer for given full names. This method is called during the semantic analysis pass whenever mypy sees an unbound type. For example, while analysing this code: from lib import Special, Other var: Special def func(x: Other[int]) -> None: ... this method will be called with 'lib.Special', and then with 'lib.Other'. The callback returned by plugin must return an analyzed type, i.e. an instance of `mypy.types.Type`. NrIrTs r/get_type_analyze_hookzPlugin.get_type_analyze_hookM r2cy)aXAdjust the signature of a function. This method is called before type checking a function call. Plugin may infer a better type for the function. from lib import Class, do_stuff do_stuff(42) Class() This method will be called with 'lib.do_stuff' and then with 'lib.Class'. NrIrTs r/get_function_signature_hookz"Plugin.get_function_signature_hook_r2cy)aAdjust the return type of a function call. This method is called after type checking a call. Plugin may adjust the return type inferred by mypy, and/or emit some error messages. Note, this hook is also called for class instantiation calls, so that in this example: from lib import Class, do_stuff do_stuff(42) Class() This method will be called with 'lib.do_stuff' and then with 'lib.Class'. NrIrTs r/get_function_hookzPlugin.get_function_hookpsr2cy)aNAdjust the signature of a method. This method is called before type checking a method call. Plugin may infer a better type for the method. The hook is also called for special Python dunder methods except __init__ and __new__ (use get_function_hook to customize class instantiation). This function is called with the method full name using the class where it was _defined_. For example, in this code: from lib import Special class Base: def method(self, arg: Any) -> Any: ... class Derived(Base): ... var: Derived var.method(42) x: Special y = x[0] this method is called with '__main__.Base.method', and then with 'lib.Special.__getitem__'. NrIrTs r/get_method_signature_hookz Plugin.get_method_signature_hooks8r2cy)zAdjust return type of a method call. This is the same as get_function_hook(), but is called with the method full name (again, using the class where the method is defined). NrIrTs r/get_method_hookzPlugin.get_method_hooks r2cy)a8Adjust type of an instance attribute. This method is called with attribute full name using the class of the instance where the attribute was defined (or Var.info.fullname for generated attributes). For classes without __getattr__ or __getattribute__, this hook is only called for names of fields/properties (but not methods) that exist in the instance MRO. For classes that implement __getattr__ or __getattribute__, this hook is called for all fields/properties, including nonexistent ones (but still not methods). For example: class Base: x: Any def __getattr__(self, attr: str) -> Any: ... class Derived(Base): ... var: Derived var.x var.y get_attribute_hook is called with '__main__.Base.x' and '__main__.Base.y'. However, if we had not implemented __getattr__ on Base, you would only get the callback for 'var.x'; 'var.y' would produce an error without calling the hook. NrIrTs r/get_attribute_hookzPlugin.get_attribute_hooks:r2cy)a{ Adjust type of a class attribute. This method is called with attribute full name using the class where the attribute was defined (or Var.info.fullname for generated attributes). For example: class Cls: x: Any Cls.x get_class_attribute_hook is called with '__main__.Cls.x' as fullname. NrIrTs r/get_class_attribute_hookzPlugin.get_class_attribute_hookrr2cy)aUpdate class definition for given class decorators. The plugin can modify a TypeInfo _in place_ (for example add some generated methods to the symbol table). This hook is called after the class body was semantically analyzed, but *there may still be placeholders* (typically caused by forward references). NOTE: Usually get_class_decorator_hook_2 is the better option, since it guarantees that there are no placeholders. The hook is called with full names of all class decorators. The hook can be called multiple times per class, so it must be idempotent. NrIrTs r/get_class_decorator_hookzPlugin.get_class_decorator_hookrr2cy)aUpdate class definition for given class decorators. Similar to get_class_decorator_hook, but this runs in a later pass when placeholders have been resolved. The hook can return False if some base class hasn't been processed yet using class hooks. It causes all class hooks (that are run in this same pass) to be invoked another time for the file(s) currently being processed. The hook can be called multiple times per class, so it must be idempotent. NrIrTs r/get_class_decorator_hook_2z!Plugin.get_class_decorator_hook_2rr2cy)a2Update class definition for given declared metaclasses. Same as get_class_decorator_hook() but for metaclasses. Note: this hook will be only called for explicit metaclasses, not for inherited ones. TODO: probably it should also be called on inherited metaclasses. NrIrTs r/get_metaclass_hookzPlugin.get_metaclass_hooksr2cy)a Update class definition for given base classes. Same as get_class_decorator_hook() but for base classes. Base classes don't need to refer to TypeInfos, if a base class refers to a variable with Any type, this hook will still be called. NrIrTs r/get_base_class_hookzPlugin.get_base_class_hooksr2cy)zCustomize MRO for given classes. The plugin can modify the class MRO _in place_. This method is called with the class full name before its body was semantically analyzed. NrIrTs r/get_customize_class_mro_hookz#Plugin.get_customize_class_mro_hooksr2cy)aSemantically analyze a dynamic class definition. This plugin hook allows one to semantically analyze dynamic class definitions like: from lib import dynamic_class X = dynamic_class('X', []) For such definition, this hook will be called with 'lib.dynamic_class'. The plugin should create the corresponding TypeInfo, and place it into a relevant symbol table, e.g. using ctx.api.add_symbol_table_node(). NrIrTs r/get_dynamic_class_hookzPlugin.get_dynamic_class_hookrr2N)r$rrArBrkrjrArBrUr.rrArrrrAzlist[tuple[int, str, int]]r5r?rAz+Callable[[AnalyzeTypeContext], Type] | Noner5r?rAz3Callable[[FunctionSigContext], FunctionLike] | Noner5r?rAz(Callable[[FunctionContext], Type] | Noner5r?rAz1Callable[[MethodSigContext], FunctionLike] | Noner5r?rAz&Callable[[MethodContext], Type] | Noner5r?rAz)Callable[[AttributeContext], Type] | Noner5r?rAz(Callable[[ClassDefContext], None] | Noner5r?rAz(Callable[[ClassDefContext], bool] | Noner5r?rAz/Callable[[DynamicClassDefContext], None] | None)rDrErFrGrrrrrrrrrrrrrrrrrrrIr2r/rrs 9 ?."$ <"  :<>$$ 1$  1 8r2rTceZdZdZdfd ZddZddZddZddZ ddZ ddZ dd Z dd Z dd Z dd Zdd Z ddZddZddZ ddZ d dZd!dZxZS)" ChainedPluginzA plugin that represents a sequence of chained plugins. Each lookup method returns the hook for the first plugin that reports a match. This class should not be subclassed -- use Plugin as the base class for all plugins. c2t||||_y)zrInitialize chained plugin. Assume that the child plugins aren't mutated (results may be cached). N)superr_plugins)r,r$plugins __class__s r/rzChainedPlugin.__init__:s ! r2cH|jD]}|j|yre)rr)r,rkplugins r/rzChainedPlugin.set_modulesBs#mm (F   w ' (r2c|jDcgc]}|j|}}td|Dr|SdScc}w)Nc3$K|]}|du ywrerI).0xs r/ z3ChainedPlugin.report_config_data..Hs!EA!4-!Es)rrany)r,r.r  config_datas r/rz ChainedPlugin.report_config_dataFsBDHMMR&v005R R!!E!EE{O4OSs?clg}|jD]"}|j|j|$|Sre)rextendr)r,rdepsr s r/rz!ChainedPlugin.get_additional_depsJs6mm :F KK2248 9 : r2cT|jD]}|j|}||cSyre)rrr,r5r hooks r/rz#ChainedPlugin.get_type_analyze_hookPs5mm F//9D  r2cT|jD]}|j|}||cSyre)rrrs r/rz)ChainedPlugin.get_function_signature_hookXs7mm F55h?D  r2c,|jfdS)Nc&|jSre)rr r5s r/z1ChainedPlugin.get_function_hook..csf.F.Fx.Pr2 _find_hookrTs `r/rzChainedPlugin.get_function_hookbsPQQr2cT|jD]}|j|}||cSyre)rrrs r/rz'ChainedPlugin.get_method_signature_hookes7mm F33H=D  r2cT|jD]}|j|}||cSyre)rrrs r/rzChainedPlugin.get_method_hookos5mm F))(3D  r2cT|jD]}|j|}||cSyre)rrrs r/rz ChainedPlugin.get_attribute_hookws5mm F,,X6D  r2c,|jfdS)Nc&|jSre)rrs r/rz8ChainedPlugin.get_class_attribute_hook..f.M.Mh.Wr2rrTs `r/rz&ChainedPlugin.get_class_attribute_hookWXXr2c,|jfdS)Nc&|jSre)rrs r/rz8ChainedPlugin.get_class_decorator_hook..r$r2rrTs `r/rz&ChainedPlugin.get_class_decorator_hookr%r2c,|jfdS)Nc&|jSre)rrs r/rz:ChainedPlugin.get_class_decorator_hook_2..sf.O.OPX.Yr2rrTs `r/rz(ChainedPlugin.get_class_decorator_hook_2sYZZr2c,|jfdS)Nc&|jSre)rrs r/rz2ChainedPlugin.get_metaclass_hook..sf.G.G.Qr2rrTs `r/rz ChainedPlugin.get_metaclass_hooksQRRr2c,|jfdS)Nc&|jSre)rrs r/rz3ChainedPlugin.get_base_class_hook..sf.H.H.Rr2rrTs `r/rz!ChainedPlugin.get_base_class_hooksRSSr2c,|jfdS)Nc&|jSre)rrs r/rz.sf.Q.QRZ.[r2rrTs `r/rz*ChainedPlugin.get_customize_class_mro_hooks[\\r2c,|jfdS)Nc&|jSre)rrs r/rz6ChainedPlugin.get_dynamic_class_hook..sf.K.KH.Ur2rrTs `r/rz$ChainedPlugin.get_dynamic_class_hooksUVVr2cB|jD]}||}||cSyre)r)r,lookupr rs r/rzChainedPlugin._find_hooks.mm F&>D  r2)r$rrz list[Plugin]rArBrrrrrrrrrrrr)r3zCallable[[Plugin], T]rAzT | None)rDrErFrGrrrrrrrrrrrrrrrrrr __classcell__)rs@r/rr.s (P  <R :YY[[ 1[ ST]] 1] WW 8W r2rN)=rG __future__rabcrtypingrrrrr mypy_extensionsr r mypy.errorcodesr mypy.errorsr mypy.lookuprmypy.message_registryr mypy.nodesrrrrrrrr mypy.optionsr mypy.typesrrrrrrr mypy.messagesr mypy.tvar_scoper!r#rKrRrXrirrrrrrrrrrrrIr2r/rBsotl#DD-%!..   !,0!"!"!"J%%  .""/"*!"!"!"Ha"a"a"L*   j . z   J   z )j))Z)  .`_`/`F  CLqFqr2