ipython 9.6.0__tar.gz → 9.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/completer.py +5 -2
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/guarded_eval.py +406 -22
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magic.py +143 -117
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magic_arguments.py +1 -1
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/history.py +24 -7
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/release.py +1 -1
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/shellapp.py +5 -1
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/ultratb.py +5 -2
- {ipython-9.6.0 → ipython-9.7.0}/IPython/external/pickleshare.py +8 -66
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/interactiveshell.py +1 -1
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/PyColorize.py +35 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/_sysinfo.py +1 -1
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/py3compat.py +0 -10
- {ipython-9.6.0 → ipython-9.7.0}/MANIFEST.in +0 -2
- {ipython-9.6.0/ipython.egg-info → ipython-9.7.0}/PKG-INFO +23 -23
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/details.rst +1 -1
- ipython-9.7.0/docs/source/whatsnew/development.rst +52 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version9.rst +59 -0
- {ipython-9.6.0 → ipython-9.7.0/ipython.egg-info}/PKG-INFO +23 -23
- {ipython-9.6.0 → ipython-9.7.0}/ipython.egg-info/requires.txt +20 -19
- {ipython-9.6.0 → ipython-9.7.0}/pyproject.toml +36 -25
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_completer.py +495 -5
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_guarded_eval.py +19 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_interactiveshell.py +12 -9
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_magic.py +10 -4
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_run.py +5 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_ultratb.py +7 -0
- ipython-9.6.0/docs/source/whatsnew/development.rst +0 -34
- {ipython-9.6.0 → ipython-9.7.0}/.flake8 +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/.mailmap +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/.pre-commit-config.yaml +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/COPYING.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/__main__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/alias.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/application.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/async_helpers.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/autocall.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/builtin_trap.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/compilerop.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/completerlib.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/crashhandler.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/debugger.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/debugger_backport.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/display.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/display_functions.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/display_trap.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/displayhook.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/displaypub.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/doctb.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/error.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/events.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/extensions.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/formatters.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/getipython.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/history.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/historyapp.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/hooks.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/inputtransformer2.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/interactiveshell.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/latex_symbols.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/logger.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/macro.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/ast_mod.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/auto.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/basic.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/code.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/config.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/display.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/execution.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/extension.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/logging.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/namespace.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/osm.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/packaging.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/pylab.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/magics/script.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/oinspect.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/page.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/payload.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/payloadpage.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/prefilter.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/profile/README_STARTUP +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/profileapp.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/profiledir.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/pylabtools.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/splitinput.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/tbtools.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/tips.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/core/usage.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/display.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/extensions/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/extensions/autoreload.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/extensions/deduperreload/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/extensions/deduperreload/deduperreload.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/extensions/deduperreload/deduperreload_patching.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/extensions/storemagic.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/extensions/tests/test_deduperreload.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/external/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/external/qt_for_kernel.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/external/qt_loaders.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/backgroundjobs.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/clipboard.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/deepreload.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/demo.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/display.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/editorhooks.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/guisupport.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/latextools.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/lexers.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/lib/pretty.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/paths.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/py.typed +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/sphinxext/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/sphinxext/custom_doctests.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/sphinxext/ipython_console_highlighting.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/sphinxext/ipython_directive.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/debugger.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/embed.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/ipapp.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/magics.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/prompts.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/asyncio.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/glut.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/gtk.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/gtk3.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/gtk4.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/osx.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/pyglet.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/qt.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/tk.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/pt_inputhooks/wx.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/ptutils.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/shortcuts/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/shortcuts/auto_match.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/shortcuts/auto_suggest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/terminal/shortcuts/filters.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/decorators.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/globalipapp.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/ipunittest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/Makefile +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/dtexample.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/ipdoctest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/pytest_ipdoctest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/setup.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/simple.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/simplevars.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/test_combo.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/test_example.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/test_exampleip.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/test_ipdoctest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/plugin/test_refs.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/skipdoctest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/testing/tools.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/_process_cli.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/_process_common.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/_process_emscripten.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/_process_posix.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/_process_win32.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/_process_win32_controller.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/capture.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/coloransi.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/contexts.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/data.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/decorators.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/dir2.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/docs.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/encoding.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/eventful.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/frame.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/generics.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/importstring.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/io.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/ipstruct.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/jsonutil.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/log.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/module_paths.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/openpy.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/path.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/process.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/sentinel.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/strdispatch.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/sysinfo.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/syspathcontext.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/tempdir.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/terminal.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/text.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/timing.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/tokenutil.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/IPython/utils/wildcard.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/LICENSE +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/README.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/_build_meta.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/Makefile +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/README.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/autogen_api.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/autogen_config.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/autogen_magics.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/autogen_shortcuts.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/make.cmd +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/man/ipython.1 +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/requirements.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/2.0/running-crop.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/2.0/running.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/2.0/treeview.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/2.0/user-interface.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/2.0/widgets.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_1_prompt_no_text.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_2_print_hello_suggest.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_3_print_hello_suggest.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_4_print_hello.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_d_completions.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_d_phantom.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_def_completions.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_def_phantom.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_match_parens.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/auto_suggest_second_prompt.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/8.0/pathlib_pathlib_everywhere.jpg +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/autosuggest.gif +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_dashboard.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_dashboard_cluster.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_notebook_cythonmagic.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_notebook_long_out.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_notebook_octavemagic.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_notebook_rmagic.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_notebook_script_cells.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_notebook_spectrogram.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_notebook_tooltip.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_par_tb.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_qtconsole_baboon.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipy_013_qtconsole_completer.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ipython-6-screenshot.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/jedi_type_inference_60.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/kernel_selector_screenshot.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ms_visual_studio.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/notebook_specgram.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/ptshell_features.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/qtconsole.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/qtconsole_tabbed.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_images/unicode_completion.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_static/favicon.ico +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_static/logo.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_static/theme_overrides.css +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_templates/breadcrumbs.html +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/_templates/notebook_redirect.html +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/about/history.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/about/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/about/license_and_copyright.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/api/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/conf.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/callbacks.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/custommagics.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/eventloops.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/extensions/autoreload.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/extensions/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/extensions/storemagic.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/inputtransforms.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/integrating.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/intro.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/options/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/shell_mimerenderer.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/config/shortcuts/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/coredev/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/config.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/execution.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/figs/ipy_kernel_and_terminal.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/figs/ipy_kernel_and_terminal.svg +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/figs/other_kernels.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/figs/other_kernels.svg +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/how_ipython_works.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/inputhook_app.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/kernels.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/messaging.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/pycompat.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/development/wrapperkernels.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/install/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/install/install.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/install/kernel_install.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/autoawait.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/magics.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/plotting.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/python-ipython-diff.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/reference.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/shell.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/tips.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/interactive/tutorial.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/links.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/overview.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/parallel/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/sphinx.toml +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/sphinxext.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-0.11.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-0.12.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-0.13.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-1.0.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-2.0.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-3.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-4.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-5.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-6.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-7.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/github-stats-8.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/index.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/pr/README.md +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/pr/antigravity-feature.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/pr/incompat-switching-to-perl.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version0.10.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version0.11.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version0.12.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version0.13.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version0.8.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version0.9.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version1.0.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version2.0.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version3.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version3_widget_migration.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version4.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version5.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version6.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version7.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/source/whatsnew/version8.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/sphinxext/apigen.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/sphinxext/configtraits.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/sphinxext/github.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/docs/sphinxext/magics.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/Embedding/embed_class_long.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/Embedding/embed_class_short.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/Embedding/embed_function.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/Embedding/start_ipython_config.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/IPython Kernel/example-demo.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/IPython Kernel/gui/gui-glut.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/IPython Kernel/gui/gui-gtk4.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/IPython Kernel/gui/gui-qt.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/IPython Kernel/ipython-completion.bash +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/IPython Kernel/ipython-get-history.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/IPython Kernel/ipython.desktop +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/auto_suggest_llm.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/utils/cwd_prompt.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/utils/list_pyfiles.ipy +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/examples/utils/list_subdirs.ipy +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/ipython.egg-info/SOURCES.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/ipython.egg-info/dependency_links.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/ipython.egg-info/entry_points.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/ipython.egg-info/not-zip-safe +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/ipython.egg-info/top_level.txt +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/long_description.rst +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/scripts/ipython.ico +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/scripts/ipython_nb.ico +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/setup.cfg +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/setup.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/setupbase.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/2x2.jpg +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/2x2.png +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/__init__.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/bad_all.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/conftest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/cve.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/fake_ext_dir/daft_extension.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/fake_llm.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/nonascii.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/nonascii2.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/print_argv.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/refbug.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/simpleerr.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/tclass.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test.wav +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_alias.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_application.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_async_helpers.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_autocall.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_backgroundjobs.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_capture.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_clipboard.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_compilerop.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_completerlib.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_debug_magic.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_debugger.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_decorators.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_decorators_2.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_deepreload.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_dir2.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_display.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_display_2.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_displayhook.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_editorhooks.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_embed.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_events.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_exceptiongroup_tb.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_extension.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_formatters.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_handlers.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_help.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_history.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_hooks.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_imports.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_importstring.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_inputtransformer2.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_inputtransformer2_line.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_interactivshell.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_io.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_iplib.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_ipunittest.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_latextools.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_logger.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_magic_arguments.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_magic_terminal.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_module_paths.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_oinspect.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_openpy.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_page.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_path.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_paths.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_prefilter.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_pretty.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_process.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_profile.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_pt_inputhooks.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_pycolorize.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_pylabtools.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_qt_loaders.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_shellapp.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_shortcuts.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_splitinput.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_storemagic.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_sysinfo.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_tempdir.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_text.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_tips.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_tokenutil.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_tools.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_wildcard.py +0 -0
- {ipython-9.6.0 → ipython-9.7.0}/tests/test_zzz_autoreload.py +0 -0
|
@@ -2481,7 +2481,7 @@ class IPCompleter(Completer):
|
|
|
2481
2481
|
return {
|
|
2482
2482
|
"completions": matches,
|
|
2483
2483
|
# static analysis should not suppress other matchers
|
|
2484
|
-
"suppress": False,
|
|
2484
|
+
"suppress": {_get_matcher_id(self.file_matcher)} if matches else False,
|
|
2485
2485
|
}
|
|
2486
2486
|
|
|
2487
2487
|
def _jedi_matches(
|
|
@@ -2741,9 +2741,12 @@ class IPCompleter(Completer):
|
|
|
2741
2741
|
is None
|
|
2742
2742
|
)
|
|
2743
2743
|
matches = filter(no__name, matches)
|
|
2744
|
-
|
|
2744
|
+
matches = _convert_matcher_v1_result_to_v2(
|
|
2745
2745
|
matches, type="attribute", fragment=fragment
|
|
2746
2746
|
)
|
|
2747
|
+
if matches["completions"]:
|
|
2748
|
+
matches["suppress"] = {_get_matcher_id(self.file_matcher)}
|
|
2749
|
+
return matches
|
|
2747
2750
|
except NameError:
|
|
2748
2751
|
# catches <undefined attributes>.<tab>
|
|
2749
2752
|
return SimpleMatcherResult(completions=[], suppress=False)
|
|
@@ -165,7 +165,10 @@ def _has_original_dunder_external(
|
|
|
165
165
|
value_module = getmodule(value_type)
|
|
166
166
|
if not value_module or not value_module.__name__:
|
|
167
167
|
return False
|
|
168
|
-
if
|
|
168
|
+
if (
|
|
169
|
+
value_module.__name__ == member_type.__name__
|
|
170
|
+
or value_module.__name__.startswith(member_type.__name__ + ".")
|
|
171
|
+
):
|
|
169
172
|
return True
|
|
170
173
|
if method_name == "__getattribute__":
|
|
171
174
|
# we have to short-circuit here due to an unresolved issue in
|
|
@@ -176,6 +179,18 @@ def _has_original_dunder_external(
|
|
|
176
179
|
member_method = getattr(member_type, method_name, None)
|
|
177
180
|
if member_method == method:
|
|
178
181
|
return True
|
|
182
|
+
if isinstance(member_type, ModuleType):
|
|
183
|
+
method = getattr(value_type, method_name, None)
|
|
184
|
+
for base_class in value_type.__mro__[1:]:
|
|
185
|
+
base_module = getmodule(base_class)
|
|
186
|
+
if base_module and (
|
|
187
|
+
base_module.__name__ == member_type.__name__
|
|
188
|
+
or base_module.__name__.startswith(member_type.__name__ + ".")
|
|
189
|
+
):
|
|
190
|
+
# Check if the method comes from this trusted base class
|
|
191
|
+
base_method = getattr(base_class, method_name, None)
|
|
192
|
+
if base_method is not None and base_method == method:
|
|
193
|
+
return True
|
|
179
194
|
except (AttributeError, KeyError):
|
|
180
195
|
return False
|
|
181
196
|
|
|
@@ -381,6 +396,10 @@ class EvaluationContext:
|
|
|
381
396
|
policy_overrides: dict = field(default_factory=dict)
|
|
382
397
|
#: Transient local namespace used to store mocks
|
|
383
398
|
transient_locals: dict = field(default_factory=dict)
|
|
399
|
+
#: Transients of class level
|
|
400
|
+
class_transients: dict | None = None
|
|
401
|
+
#: Instance variable name used in the method definition
|
|
402
|
+
instance_arg_name: str | None = None
|
|
384
403
|
|
|
385
404
|
def replace(self, /, **changes):
|
|
386
405
|
"""Return a new copy of the context, with specified changes"""
|
|
@@ -545,6 +564,8 @@ def _validate_policy_overrides(
|
|
|
545
564
|
def _handle_assign(node: ast.Assign, context: EvaluationContext):
|
|
546
565
|
value = eval_node(node.value, context)
|
|
547
566
|
transient_locals = context.transient_locals
|
|
567
|
+
policy = get_policy(context)
|
|
568
|
+
class_transients = context.class_transients
|
|
548
569
|
for target in node.targets:
|
|
549
570
|
if isinstance(target, (ast.Tuple, ast.List)):
|
|
550
571
|
# Handle unpacking assignment
|
|
@@ -557,20 +578,81 @@ def _handle_assign(node: ast.Assign, context: EvaluationContext):
|
|
|
557
578
|
|
|
558
579
|
# Before starred
|
|
559
580
|
for i in range(star_or_last_idx):
|
|
560
|
-
|
|
581
|
+
# Check for self.x assignment
|
|
582
|
+
if _is_instance_attribute_assignment(targets[i], context):
|
|
583
|
+
class_transients[targets[i].attr] = values[i]
|
|
584
|
+
else:
|
|
585
|
+
transient_locals[targets[i].id] = values[i]
|
|
561
586
|
|
|
562
587
|
# Starred if exists
|
|
563
588
|
if starred:
|
|
564
589
|
end = len(values) - (len(targets) - star_or_last_idx - 1)
|
|
565
|
-
|
|
566
|
-
star_or_last_idx
|
|
567
|
-
|
|
590
|
+
if _is_instance_attribute_assignment(
|
|
591
|
+
targets[star_or_last_idx], context
|
|
592
|
+
):
|
|
593
|
+
class_transients[targets[star_or_last_idx].attr] = values[
|
|
594
|
+
star_or_last_idx:end
|
|
595
|
+
]
|
|
596
|
+
else:
|
|
597
|
+
transient_locals[targets[star_or_last_idx].value.id] = values[
|
|
598
|
+
star_or_last_idx:end
|
|
599
|
+
]
|
|
568
600
|
|
|
569
601
|
# After starred
|
|
570
602
|
for i in range(star_or_last_idx + 1, len(targets)):
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
603
|
+
if _is_instance_attribute_assignment(targets[i], context):
|
|
604
|
+
class_transients[targets[i].attr] = values[
|
|
605
|
+
len(values) - (len(targets) - i)
|
|
606
|
+
]
|
|
607
|
+
else:
|
|
608
|
+
transient_locals[targets[i].id] = values[
|
|
609
|
+
len(values) - (len(targets) - i)
|
|
610
|
+
]
|
|
611
|
+
elif isinstance(target, ast.Subscript):
|
|
612
|
+
if isinstance(target.value, ast.Name):
|
|
613
|
+
name = target.value.id
|
|
614
|
+
container = transient_locals.get(name)
|
|
615
|
+
if container is None:
|
|
616
|
+
container = context.locals.get(name)
|
|
617
|
+
if container is None:
|
|
618
|
+
container = context.globals.get(name)
|
|
619
|
+
if container is None:
|
|
620
|
+
raise NameError(
|
|
621
|
+
f"{name} not found in locals, globals, nor builtins"
|
|
622
|
+
)
|
|
623
|
+
storage_dict = transient_locals
|
|
624
|
+
storage_key = name
|
|
625
|
+
elif isinstance(
|
|
626
|
+
target.value, ast.Attribute
|
|
627
|
+
) and _is_instance_attribute_assignment(target.value, context):
|
|
628
|
+
attr = target.value.attr
|
|
629
|
+
container = class_transients.get(attr, None)
|
|
630
|
+
if container is None:
|
|
631
|
+
raise NameError(f"{attr} not found in class transients")
|
|
632
|
+
storage_dict = class_transients
|
|
633
|
+
storage_key = attr
|
|
634
|
+
else:
|
|
635
|
+
return
|
|
636
|
+
|
|
637
|
+
key = eval_node(target.slice, context)
|
|
638
|
+
attributes = (
|
|
639
|
+
dict.fromkeys(dir(container))
|
|
640
|
+
if policy.can_call(container.__dir__)
|
|
641
|
+
else {}
|
|
642
|
+
)
|
|
643
|
+
items = {}
|
|
644
|
+
|
|
645
|
+
if policy.can_get_item(container, None):
|
|
646
|
+
try:
|
|
647
|
+
items = dict(container.items())
|
|
648
|
+
except Exception:
|
|
649
|
+
pass
|
|
650
|
+
|
|
651
|
+
items[key] = value
|
|
652
|
+
duck_container = _Duck(attributes=attributes, items=items)
|
|
653
|
+
storage_dict[storage_key] = duck_container
|
|
654
|
+
elif _is_instance_attribute_assignment(target, context):
|
|
655
|
+
class_transients[target.attr] = value
|
|
574
656
|
else:
|
|
575
657
|
transient_locals[target.id] = value
|
|
576
658
|
return None
|
|
@@ -590,6 +672,30 @@ def _extract_args_and_kwargs(node: ast.Call, context: EvaluationContext):
|
|
|
590
672
|
return args, kwargs
|
|
591
673
|
|
|
592
674
|
|
|
675
|
+
def _is_instance_attribute_assignment(
|
|
676
|
+
target: ast.AST, context: EvaluationContext
|
|
677
|
+
) -> bool:
|
|
678
|
+
"""Return True if target is an attribute access on the instance argument."""
|
|
679
|
+
return (
|
|
680
|
+
context.class_transients is not None
|
|
681
|
+
and context.instance_arg_name is not None
|
|
682
|
+
and isinstance(target, ast.Attribute)
|
|
683
|
+
and isinstance(getattr(target, "value", None), ast.Name)
|
|
684
|
+
and getattr(target.value, "id", None) == context.instance_arg_name
|
|
685
|
+
)
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
def _get_coroutine_attributes() -> dict[str, Optional[object]]:
|
|
689
|
+
async def _dummy():
|
|
690
|
+
return None
|
|
691
|
+
|
|
692
|
+
coro = _dummy()
|
|
693
|
+
try:
|
|
694
|
+
return {attr: getattr(coro, attr, None) for attr in dir(coro)}
|
|
695
|
+
finally:
|
|
696
|
+
coro.close()
|
|
697
|
+
|
|
698
|
+
|
|
593
699
|
def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
|
|
594
700
|
"""Evaluate AST node in provided context.
|
|
595
701
|
|
|
@@ -626,10 +732,13 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
|
|
|
626
732
|
for child_node in node.body:
|
|
627
733
|
result = eval_node(child_node, context)
|
|
628
734
|
return result
|
|
629
|
-
if isinstance(node, ast.FunctionDef):
|
|
630
|
-
|
|
735
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
736
|
+
is_async = isinstance(node, ast.AsyncFunctionDef)
|
|
737
|
+
func_locals = context.transient_locals.copy()
|
|
738
|
+
func_context = context.replace(transient_locals=func_locals)
|
|
631
739
|
is_property = False
|
|
632
|
-
|
|
740
|
+
is_static = False
|
|
741
|
+
is_classmethod = False
|
|
633
742
|
for decorator_node in node.decorator_list:
|
|
634
743
|
try:
|
|
635
744
|
decorator = eval_node(decorator_node, context)
|
|
@@ -639,42 +748,165 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
|
|
|
639
748
|
continue
|
|
640
749
|
if decorator is property:
|
|
641
750
|
is_property = True
|
|
751
|
+
elif decorator is staticmethod:
|
|
752
|
+
is_static = True
|
|
753
|
+
elif decorator is classmethod:
|
|
754
|
+
is_classmethod = True
|
|
755
|
+
|
|
756
|
+
if func_context.class_transients is not None:
|
|
757
|
+
if not is_static and not is_classmethod:
|
|
758
|
+
func_context.instance_arg_name = (
|
|
759
|
+
node.args.args[0].arg if node.args.args else None
|
|
760
|
+
)
|
|
642
761
|
|
|
643
762
|
return_type = eval_node(node.returns, context=context)
|
|
644
763
|
|
|
764
|
+
for child_node in node.body:
|
|
765
|
+
eval_node(child_node, func_context)
|
|
766
|
+
|
|
645
767
|
if is_property:
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
768
|
+
if return_type is not None:
|
|
769
|
+
context.transient_locals[node.name] = _resolve_annotation(
|
|
770
|
+
return_type, context
|
|
771
|
+
)
|
|
772
|
+
else:
|
|
773
|
+
return_value = _infer_return_value(node, func_context)
|
|
774
|
+
context.transient_locals[node.name] = return_value
|
|
775
|
+
|
|
649
776
|
return None
|
|
650
777
|
|
|
651
778
|
def dummy_function(*args, **kwargs):
|
|
652
779
|
pass
|
|
653
780
|
|
|
654
|
-
|
|
781
|
+
if return_type is not None:
|
|
782
|
+
dummy_function.__annotations__["return"] = return_type
|
|
783
|
+
else:
|
|
784
|
+
inferred_return = _infer_return_value(node, func_context)
|
|
785
|
+
if inferred_return is not None:
|
|
786
|
+
dummy_function.__inferred_return__ = inferred_return
|
|
787
|
+
|
|
655
788
|
dummy_function.__name__ = node.name
|
|
656
789
|
dummy_function.__node__ = node
|
|
790
|
+
dummy_function.__is_async__ = is_async
|
|
657
791
|
context.transient_locals[node.name] = dummy_function
|
|
658
792
|
return None
|
|
793
|
+
if isinstance(node, ast.Lambda):
|
|
794
|
+
|
|
795
|
+
def dummy_function(*args, **kwargs):
|
|
796
|
+
pass
|
|
797
|
+
|
|
798
|
+
dummy_function.__inferred_return__ = eval_node(node.body, context)
|
|
799
|
+
return dummy_function
|
|
659
800
|
if isinstance(node, ast.ClassDef):
|
|
660
801
|
# TODO support class decorators?
|
|
661
802
|
class_locals = {}
|
|
662
|
-
|
|
803
|
+
outer_locals = context.locals.copy()
|
|
804
|
+
outer_locals.update(context.transient_locals)
|
|
805
|
+
class_context = context.replace(
|
|
806
|
+
transient_locals=class_locals, locals=outer_locals
|
|
807
|
+
)
|
|
808
|
+
class_context.class_transients = class_locals
|
|
663
809
|
for child_node in node.body:
|
|
664
810
|
eval_node(child_node, class_context)
|
|
665
811
|
bases = tuple([eval_node(base, context) for base in node.bases])
|
|
666
812
|
dummy_class = type(node.name, bases, class_locals)
|
|
667
813
|
context.transient_locals[node.name] = dummy_class
|
|
668
814
|
return None
|
|
815
|
+
if isinstance(node, ast.Await):
|
|
816
|
+
value = eval_node(node.value, context)
|
|
817
|
+
if hasattr(value, "__awaited_type__"):
|
|
818
|
+
return value.__awaited_type__
|
|
819
|
+
return value
|
|
820
|
+
if isinstance(node, ast.While):
|
|
821
|
+
loop_locals = context.transient_locals.copy()
|
|
822
|
+
loop_context = context.replace(transient_locals=loop_locals)
|
|
823
|
+
|
|
824
|
+
result = None
|
|
825
|
+
for stmt in node.body:
|
|
826
|
+
result = eval_node(stmt, loop_context)
|
|
827
|
+
|
|
828
|
+
policy = get_policy(context)
|
|
829
|
+
merged_locals = _merge_dicts_by_key(
|
|
830
|
+
[loop_locals, context.transient_locals.copy()], policy
|
|
831
|
+
)
|
|
832
|
+
context.transient_locals.update(merged_locals)
|
|
833
|
+
|
|
834
|
+
return result
|
|
835
|
+
if isinstance(node, ast.For):
|
|
836
|
+
try:
|
|
837
|
+
iterable = eval_node(node.iter, context)
|
|
838
|
+
except Exception:
|
|
839
|
+
iterable = None
|
|
840
|
+
|
|
841
|
+
sample = None
|
|
842
|
+
if iterable is not None:
|
|
843
|
+
try:
|
|
844
|
+
if policy.can_call(getattr(iterable, "__iter__", None)):
|
|
845
|
+
sample = next(iter(iterable))
|
|
846
|
+
except Exception:
|
|
847
|
+
sample = None
|
|
848
|
+
|
|
849
|
+
loop_locals = context.transient_locals.copy()
|
|
850
|
+
loop_context = context.replace(transient_locals=loop_locals)
|
|
851
|
+
|
|
852
|
+
if sample is not None:
|
|
853
|
+
try:
|
|
854
|
+
fake_assign = ast.Assign(
|
|
855
|
+
targets=[node.target], value=ast.Constant(value=sample)
|
|
856
|
+
)
|
|
857
|
+
_handle_assign(fake_assign, loop_context)
|
|
858
|
+
except Exception:
|
|
859
|
+
pass
|
|
860
|
+
|
|
861
|
+
result = None
|
|
862
|
+
for stmt in node.body:
|
|
863
|
+
result = eval_node(stmt, loop_context)
|
|
864
|
+
|
|
865
|
+
policy = get_policy(context)
|
|
866
|
+
merged_locals = _merge_dicts_by_key(
|
|
867
|
+
[loop_locals, context.transient_locals.copy()], policy
|
|
868
|
+
)
|
|
869
|
+
context.transient_locals.update(merged_locals)
|
|
870
|
+
|
|
871
|
+
return result
|
|
872
|
+
if isinstance(node, ast.If):
|
|
873
|
+
branches = []
|
|
874
|
+
current = node
|
|
875
|
+
result = None
|
|
876
|
+
while True:
|
|
877
|
+
branch_locals = context.transient_locals.copy()
|
|
878
|
+
branch_context = context.replace(transient_locals=branch_locals)
|
|
879
|
+
for stmt in current.body:
|
|
880
|
+
result = eval_node(stmt, branch_context)
|
|
881
|
+
branches.append(branch_locals)
|
|
882
|
+
if not current.orelse:
|
|
883
|
+
break
|
|
884
|
+
elif len(current.orelse) == 1 and isinstance(current.orelse[0], ast.If):
|
|
885
|
+
# It's an elif - continue loop
|
|
886
|
+
current = current.orelse[0]
|
|
887
|
+
else:
|
|
888
|
+
# It's an else block - process and break
|
|
889
|
+
else_locals = context.transient_locals.copy()
|
|
890
|
+
else_context = context.replace(transient_locals=else_locals)
|
|
891
|
+
for stmt in current.orelse:
|
|
892
|
+
result = eval_node(stmt, else_context)
|
|
893
|
+
branches.append(else_locals)
|
|
894
|
+
break
|
|
895
|
+
branches.append(context.transient_locals.copy())
|
|
896
|
+
policy = get_policy(context)
|
|
897
|
+
merged_locals = _merge_dicts_by_key(branches, policy)
|
|
898
|
+
context.transient_locals.update(merged_locals)
|
|
899
|
+
return result
|
|
669
900
|
if isinstance(node, ast.Assign):
|
|
670
901
|
return _handle_assign(node, context)
|
|
671
902
|
if isinstance(node, ast.AnnAssign):
|
|
672
|
-
if
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
903
|
+
if node.simple:
|
|
904
|
+
value = _resolve_annotation(eval_node(node.annotation, context), context)
|
|
905
|
+
context.transient_locals[node.target.id] = value
|
|
906
|
+
# Handle non-simple annotated assignments only for self.x: type = value
|
|
907
|
+
if _is_instance_attribute_assignment(node.target, context):
|
|
908
|
+
value = _resolve_annotation(eval_node(node.annotation, context), context)
|
|
909
|
+
context.class_transients[node.target.attr] = value
|
|
678
910
|
return None
|
|
679
911
|
if isinstance(node, ast.Expression):
|
|
680
912
|
return eval_node(node.body, context)
|
|
@@ -792,6 +1024,12 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
|
|
|
792
1024
|
if isinstance(node, ast.Name):
|
|
793
1025
|
return _eval_node_name(node.id, context)
|
|
794
1026
|
if isinstance(node, ast.Attribute):
|
|
1027
|
+
if (
|
|
1028
|
+
context.class_transients is not None
|
|
1029
|
+
and isinstance(node.value, ast.Name)
|
|
1030
|
+
and node.value.id == context.instance_arg_name
|
|
1031
|
+
):
|
|
1032
|
+
return context.class_transients.get(node.attr)
|
|
795
1033
|
value = eval_node(node.value, context)
|
|
796
1034
|
if policy.can_get_attr(value, node.attr):
|
|
797
1035
|
return getattr(value, node.attr)
|
|
@@ -821,7 +1059,17 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
|
|
|
821
1059
|
return overridden_return_type
|
|
822
1060
|
return _create_duck_for_heap_type(func)
|
|
823
1061
|
else:
|
|
1062
|
+
inferred_return = getattr(func, "__inferred_return__", NOT_EVALUATED)
|
|
824
1063
|
return_type = _eval_return_type(func, node, context)
|
|
1064
|
+
if getattr(func, "__is_async__", False):
|
|
1065
|
+
awaited_type = (
|
|
1066
|
+
inferred_return if inferred_return is not None else return_type
|
|
1067
|
+
)
|
|
1068
|
+
coroutine_duck = _Duck(attributes=_get_coroutine_attributes())
|
|
1069
|
+
coroutine_duck.__awaited_type__ = awaited_type
|
|
1070
|
+
return coroutine_duck
|
|
1071
|
+
if inferred_return is not NOT_EVALUATED:
|
|
1072
|
+
return inferred_return
|
|
825
1073
|
if return_type is not NOT_EVALUATED:
|
|
826
1074
|
return return_type
|
|
827
1075
|
raise GuardRejection(
|
|
@@ -838,6 +1086,119 @@ def eval_node(node: Union[ast.AST, None], context: EvaluationContext):
|
|
|
838
1086
|
return None
|
|
839
1087
|
|
|
840
1088
|
|
|
1089
|
+
def _merge_dicts_by_key(dicts: list, policy: EvaluationPolicy):
|
|
1090
|
+
"""Merge multiple dictionaries, combining values for each key."""
|
|
1091
|
+
if len(dicts) == 1:
|
|
1092
|
+
return dicts[0]
|
|
1093
|
+
|
|
1094
|
+
all_keys = set()
|
|
1095
|
+
for d in dicts:
|
|
1096
|
+
all_keys.update(d.keys())
|
|
1097
|
+
|
|
1098
|
+
merged = {}
|
|
1099
|
+
for key in all_keys:
|
|
1100
|
+
values = [d[key] for d in dicts if key in d]
|
|
1101
|
+
if values:
|
|
1102
|
+
merged[key] = _merge_values(values, policy)
|
|
1103
|
+
|
|
1104
|
+
return merged
|
|
1105
|
+
|
|
1106
|
+
|
|
1107
|
+
def _merge_values(values, policy: EvaluationPolicy):
|
|
1108
|
+
"""Recursively merge multiple values, combining attributes and dict items."""
|
|
1109
|
+
if len(values) == 1:
|
|
1110
|
+
return values[0]
|
|
1111
|
+
|
|
1112
|
+
types = {type(v) for v in values}
|
|
1113
|
+
merged_items = None
|
|
1114
|
+
key_values = {}
|
|
1115
|
+
attributes = set()
|
|
1116
|
+
for v in values:
|
|
1117
|
+
if policy.can_call(v.__dir__):
|
|
1118
|
+
attributes.update(dir(v))
|
|
1119
|
+
try:
|
|
1120
|
+
if policy.can_call(v.items):
|
|
1121
|
+
try:
|
|
1122
|
+
for k, val in v.items():
|
|
1123
|
+
key_values.setdefault(k, []).append(val)
|
|
1124
|
+
except Exception as e:
|
|
1125
|
+
pass
|
|
1126
|
+
elif policy.can_call(v.keys):
|
|
1127
|
+
try:
|
|
1128
|
+
for k in v.keys():
|
|
1129
|
+
key_values.setdefault(k, []).append(None)
|
|
1130
|
+
except Exception as e:
|
|
1131
|
+
pass
|
|
1132
|
+
except Exception as e:
|
|
1133
|
+
pass
|
|
1134
|
+
|
|
1135
|
+
if key_values:
|
|
1136
|
+
merged_items = {
|
|
1137
|
+
k: _merge_values(vals, policy) if vals[0] is not None else None
|
|
1138
|
+
for k, vals in key_values.items()
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
if len(types) == 1:
|
|
1142
|
+
t = next(iter(types))
|
|
1143
|
+
if t not in (dict,) and not (
|
|
1144
|
+
hasattr(next(iter(values)), "__getitem__")
|
|
1145
|
+
and (
|
|
1146
|
+
hasattr(next(iter(values)), "items")
|
|
1147
|
+
or hasattr(next(iter(values)), "keys")
|
|
1148
|
+
)
|
|
1149
|
+
):
|
|
1150
|
+
if t in (list, set, tuple):
|
|
1151
|
+
return t
|
|
1152
|
+
return values[0]
|
|
1153
|
+
|
|
1154
|
+
return _Duck(attributes=dict.fromkeys(attributes), items=merged_items)
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
def _infer_return_value(node: ast.FunctionDef, context: EvaluationContext):
|
|
1158
|
+
"""Infer the return value(s) of a function by evaluating all return statements."""
|
|
1159
|
+
return_values = _collect_return_values(node.body, context)
|
|
1160
|
+
|
|
1161
|
+
if not return_values:
|
|
1162
|
+
return None
|
|
1163
|
+
if len(return_values) == 1:
|
|
1164
|
+
return return_values[0]
|
|
1165
|
+
|
|
1166
|
+
policy = get_policy(context)
|
|
1167
|
+
return _merge_values(return_values, policy)
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
def _collect_return_values(body, context):
|
|
1171
|
+
"""Recursively collect return values from a list of AST statements."""
|
|
1172
|
+
return_values = []
|
|
1173
|
+
for stmt in body:
|
|
1174
|
+
if isinstance(stmt, ast.Return):
|
|
1175
|
+
if stmt.value is None:
|
|
1176
|
+
continue
|
|
1177
|
+
try:
|
|
1178
|
+
value = eval_node(stmt.value, context)
|
|
1179
|
+
if value is not None and value is not NOT_EVALUATED:
|
|
1180
|
+
return_values.append(value)
|
|
1181
|
+
except Exception:
|
|
1182
|
+
pass
|
|
1183
|
+
if isinstance(
|
|
1184
|
+
stmt, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef, ast.Lambda)
|
|
1185
|
+
):
|
|
1186
|
+
continue
|
|
1187
|
+
elif hasattr(stmt, "body") and isinstance(stmt.body, list):
|
|
1188
|
+
return_values.extend(_collect_return_values(stmt.body, context))
|
|
1189
|
+
if isinstance(stmt, ast.Try):
|
|
1190
|
+
for h in stmt.handlers:
|
|
1191
|
+
if hasattr(h, "body"):
|
|
1192
|
+
return_values.extend(_collect_return_values(h.body, context))
|
|
1193
|
+
if hasattr(stmt, "orelse"):
|
|
1194
|
+
return_values.extend(_collect_return_values(stmt.orelse, context))
|
|
1195
|
+
if hasattr(stmt, "finalbody"):
|
|
1196
|
+
return_values.extend(_collect_return_values(stmt.finalbody, context))
|
|
1197
|
+
if hasattr(stmt, "orelse") and isinstance(stmt.orelse, list):
|
|
1198
|
+
return_values.extend(_collect_return_values(stmt.orelse, context))
|
|
1199
|
+
return return_values
|
|
1200
|
+
|
|
1201
|
+
|
|
841
1202
|
def _eval_return_type(func: Callable, node: ast.Call, context: EvaluationContext):
|
|
842
1203
|
"""Evaluate return type of a given callable function.
|
|
843
1204
|
|
|
@@ -1063,46 +1424,69 @@ set_non_mutating_methods = set(dir(set)) & set(dir(frozenset))
|
|
|
1063
1424
|
|
|
1064
1425
|
|
|
1065
1426
|
dict_keys: type[collections.abc.KeysView] = type({}.keys())
|
|
1427
|
+
dict_values: type = type({}.values())
|
|
1428
|
+
dict_items: type = type({}.items())
|
|
1066
1429
|
|
|
1067
1430
|
NUMERICS = {int, float, complex}
|
|
1068
1431
|
|
|
1069
1432
|
ALLOWED_CALLS = {
|
|
1070
1433
|
bytes,
|
|
1071
1434
|
*_list_methods(bytes),
|
|
1435
|
+
bytes.__iter__,
|
|
1072
1436
|
dict,
|
|
1073
1437
|
*_list_methods(dict, dict_non_mutating_methods),
|
|
1438
|
+
dict.__iter__,
|
|
1439
|
+
dict_keys.__iter__,
|
|
1440
|
+
dict_values.__iter__,
|
|
1441
|
+
dict_items.__iter__,
|
|
1074
1442
|
dict_keys.isdisjoint,
|
|
1075
1443
|
list,
|
|
1076
1444
|
*_list_methods(list, list_non_mutating_methods),
|
|
1445
|
+
list.__iter__,
|
|
1077
1446
|
set,
|
|
1078
1447
|
*_list_methods(set, set_non_mutating_methods),
|
|
1448
|
+
set.__iter__,
|
|
1079
1449
|
frozenset,
|
|
1080
1450
|
*_list_methods(frozenset),
|
|
1451
|
+
frozenset.__iter__,
|
|
1081
1452
|
range,
|
|
1453
|
+
range.__iter__,
|
|
1082
1454
|
str,
|
|
1083
1455
|
*_list_methods(str),
|
|
1456
|
+
str.__iter__,
|
|
1084
1457
|
tuple,
|
|
1085
1458
|
*_list_methods(tuple),
|
|
1459
|
+
tuple.__iter__,
|
|
1086
1460
|
bool,
|
|
1087
1461
|
*_list_methods(bool),
|
|
1088
1462
|
*NUMERICS,
|
|
1089
1463
|
*[method for numeric_cls in NUMERICS for method in _list_methods(numeric_cls)],
|
|
1090
1464
|
collections.deque,
|
|
1091
1465
|
*_list_methods(collections.deque, list_non_mutating_methods),
|
|
1466
|
+
collections.deque.__iter__,
|
|
1092
1467
|
collections.defaultdict,
|
|
1093
1468
|
*_list_methods(collections.defaultdict, dict_non_mutating_methods),
|
|
1469
|
+
collections.defaultdict.__iter__,
|
|
1094
1470
|
collections.OrderedDict,
|
|
1095
1471
|
*_list_methods(collections.OrderedDict, dict_non_mutating_methods),
|
|
1472
|
+
collections.OrderedDict.__iter__,
|
|
1096
1473
|
collections.UserDict,
|
|
1097
1474
|
*_list_methods(collections.UserDict, dict_non_mutating_methods),
|
|
1475
|
+
collections.UserDict.__iter__,
|
|
1098
1476
|
collections.UserList,
|
|
1099
1477
|
*_list_methods(collections.UserList, list_non_mutating_methods),
|
|
1478
|
+
collections.UserList.__iter__,
|
|
1100
1479
|
collections.UserString,
|
|
1101
1480
|
*_list_methods(collections.UserString, dir(str)),
|
|
1481
|
+
collections.UserString.__iter__,
|
|
1102
1482
|
collections.Counter,
|
|
1103
1483
|
*_list_methods(collections.Counter, dict_non_mutating_methods),
|
|
1484
|
+
collections.Counter.__iter__,
|
|
1104
1485
|
collections.Counter.elements,
|
|
1105
1486
|
collections.Counter.most_common,
|
|
1487
|
+
object.__dir__,
|
|
1488
|
+
type.__dir__,
|
|
1489
|
+
_Duck.__dir__,
|
|
1106
1490
|
}
|
|
1107
1491
|
|
|
1108
1492
|
BUILTIN_GETATTR: set[MayHaveGetattr] = {
|