TL i9!dZddlZddlmZddlmZddlmZddlmZddlm Z ddl m Z dd lm Z dd l mZdd lmZmZmZdd lmZmZdd lmZmZmZddlmZddlmZGddZy)a Type inference of Python code in |jedi| is based on three assumptions: * The code uses as least side effects as possible. Jedi understands certain list/tuple/set modifications, but there's no guarantee that Jedi detects everything (list.append in different modules for example). * No magic is being used: - metaclasses - ``setattr()`` / ``__import__()`` - writing to ``globals()``, ``locals()``, ``object.__dict__`` * The programmer is not a total dick, e.g. like `this `_ :-) The actual algorithm is based on a principle I call lazy type inference. That said, the typical entry point for static analysis is calling ``infer_expr_stmt``. There's separate logic for autocompletion in the API, the inference_state is all about inferring an expression. TODO this paragraph is not what jedi does anymore, it's similar, but not the same. Now you need to understand what follows after ``infer_expr_stmt``. Let's make an example:: import datetime datetime.date.toda# <-- cursor here First of all, this module doesn't care about completion. It really just cares about ``datetime.date``. At the end of the procedure ``infer_expr_stmt`` will return the ``date`` class. To *visualize* this (simplified): - ``InferenceState.infer_expr_stmt`` doesn't do much, because there's no assignment. - ``Context.infer_node`` cares for resolving the dotted path - ``InferenceState.find_types`` searches for global definitions of datetime, which it finds in the definition of an import, by scanning the syntax tree. - Using the import logic, the datetime module is found. - Now ``find_types`` is called again by ``infer_node`` to find ``date`` inside the datetime module. Now what would happen if we wanted ``datetime.date.foo.bar``? Two more calls to ``find_types``. However the second call would be ignored, because the first one would return nothing (there's no foo attribute in ``date``). What if the import would contain another ``ExprStmt`` like this:: from foo import bar Date = bar.baz Well... You get it. Just another ``infer_expr_stmt`` recursion. It's really easy. Python can obviously get way more complicated then this. To understand tuple assignments, list comprehensions and everything else, a lot more code had to be written. Jedi has been tested very well, so you can just start modifying code. It's best to write your own test first for your "new" feature. Don't be scared of breaking stuff. As long as the tests pass, you're most likely to be fine. I need to mention now that lazy type inference is really good because it only *inferes* what needs to be *inferred*. All the statements and modules that are not used are just being ignored. N)FileIO)debug)settings)imports) recursion)inference_state_function_cache)helpers)TreeNameDefinition)ContextualizedNodeValueSetiterate_values) ClassValue FunctionValue)infer_expr_stmtcheck_tuple_assignmentstree_name_to_values)%follow_error_node_imports_if_possible)plugin_managerceZdZd dZd dZeejdZe e dZ e e dZ dZ dZd Z dd Zd Zy)InferenceStateNc||j}||_||_|j||_|j |_tjd|_ i|_ tj|_ i|_i|_i|_i|_g|_d|_t(j*|_d|_||_i|_d|_d|_|j9y)Nz3.13)versionrFT)get_environment environment script_pathget_inference_state_subprocesscompiled_subprocess get_grammargrammarparso load_grammarlatest_grammar memoize_cacher ModuleCache module_cachestub_module_cachecompiled_cacheinferred_element_counts mixed_cacheanalysisdynamic_params_depthrdynamic_paramsdo_dynamic_params_search is_analysisproject access_cacheallow_unsafe_executionsflow_analysis_enabledreset_recursion_limitations)selfr/rrs ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/jedi/inference/__init__.py__init__zInferenceState.__init__Us  !113K&&#.#M#Md#S "..0 #00@#//1!# ')$ $%!(0(?(?%  ',$%)" ((*c4tj||||S)N) prefer_stubs)rimport_module_by_names)r4 import_namessys_pathr9s r5 import_modulezInferenceState.import_moduleos -- ,|E Er7ctjd||tj5|j|}dddtjd||S#1swY"xYw)Nzexecute: %s %s) argumentszexecute result: %s in %s)rdbgincrease_indent_cm py__call__)valuer? value_sets r5executezInferenceState.executess`  "E95  % % ' >((9(=I > ,i? > >s A  A)c6d}|j|fg\}|S)Nbuiltins)r<r=)r4 module_namebuiltins_modules r5rJzInferenceState.builtins_module}s)! --{nr-Jr7c,|jd\}|S)N)typingrH)r4 typing_modules r5rMzInferenceState.typing_modules++K8 r7cjtj|_tj||_y)N)rRecursionDetectorrecursion_detectorExecutionRecursionDetectorexecution_recursion_detector)r4s r5r3z*InferenceState.reset_recursion_limitationss'"+"="="?,5,P,PQU,V)r7c <|jj|fi|S)zConvenience function)r/ _get_sys_path)r4kwargss r5 get_sys_pathzInferenceState.get_sys_paths)t||))$9&99r7c(|jd}|X|j}|dk(}|s|dk(rF|rt|||j}n t j ||j}t |gS|dk(r'|jjdv}|r t|||S|dk(r[|j|jd}t||jd} t|| } t||} t| | S|d vrtj||S|d k(r t!|||S|d k(r'|j#|j$|j& S|d k(r!|j|St)||} | | St+j,||S)NT)import_name_alwaysclassdeffuncdef expr_stmt)powertrailerfor_stmt) import_from import_name with_stmtparam)positionnamedexpr_test)get_definitiontyperparentr from_contextr r infer_nodechildrenr r r rr infer_importrpy__getattribute__rCend_posrr infer_call_of_leaf) r4contextnamedef_type_ is_classdefcis_simple_namecontainer_typescn for_typesnresults r5inferzInferenceState.infers""d";  IIE:-Key0"4$++>A%227DKKHA}$ #!%!1!19M!M!*7D$?? "")"4"4T]]15E"F'q1AB*?B? &w5.q)<<66++GT:: #*4$??'!11$**t||1TT**))$//:7DIF! ))'488r7c 2|| t|}|j}tj|dd}t |t j kDr|dt j }|r |jn |j}|jd|||d||fS)Nzutf-8replace)encodingerrors)codepathfile_io) rreadr python_bytes_to_unicodelenr_cropped_file_sizer"rparse)r4rruse_latest_grammarrrUrs r5parse_and_get_codez!InferenceState.parse_and_get_codes < ,<<>D,,TGIV t9x22 24445D);$%%w}}M$T7MfMtSSr7c,|j|i|dS)Nr)r)r4argsrUs r5rzInferenceState.parses&t&&77::r7)NN)NT)NNFN)__name__ __module__ __qualname__r6r= staticmethodrdecoraterEpropertyrrJrMr3rVr|rrrr7r5rrTs+4E^#%& #%&W:#9J26=A T;r7r)__doc__r jedi.file_iorjedirrjedi.inferencerrjedi.inference.cacherr jedi.inference.namesr jedi.inference.base_valuer r r jedi.inference.valuerrjedi.inference.syntax_treerrrjedi.inference.importsr jedi.pluginsrrrr7r5rsQ?@ "$?"3:11H's;s;r7