[
  {
    "path": ".build",
    "content": "{\n\t\"automatic_order\": false,\n\t\"iterations\": 1,\n\t\"mods_load_order\":\n\t[\n\t\t\"tests/test_tests_running.py\",\n\t\t\"lib/utils.py\",\n\t\t\"lib/kernel.py\",\n\t\t\"helium.py\",\n\t\t\"lib/__init__.py\",\n\t\t\"lib/client/__init__.py\",\n\t\t\"lib/client/decorator.py\",\n\t\t\"lib/client/jupyter_client/channelsabc.py\",\n\t\t\"lib/client/jupyter_client/threaded.py\",\n\t\t\"lib/client/jupyter_client/restarter.py\",\n\t\t\"lib/client/jupyter_client/__init__.py\",\n\t\t\"lib/client/jupyter_client/client.py\",\n\t\t\"lib/client/jupyter_client/managerabc.py\",\n\t\t\"lib/client/jupyter_client/adapter.py\",\n\t\t\"lib/client/jupyter_client/localinterfaces.py\",\n\t\t\"lib/client/jupyter_client/win_interrupt.py\",\n\t\t\"lib/client/jupyter_client/_version.py\",\n\t\t\"lib/client/jupyter_client/connect.py\",\n\t\t\"lib/client/jupyter_client/kernelspec.py\",\n\t\t\"lib/client/jupyter_client/launcher.py\",\n\t\t\"lib/client/jupyter_client/session.py\",\n\t\t\"lib/client/jupyter_client/multikernelmanager.py\",\n\t\t\"lib/client/jupyter_client/jsonutil.py\",\n\t\t\"lib/client/jupyter_client/manager.py\",\n\t\t\"lib/client/jupyter_client/kernelspecapp.py\",\n\t\t\"lib/client/jupyter_client/runapp.py\",\n\t\t\"lib/client/jupyter_client/consoleapp.py\",\n\t\t\"lib/client/jupyter_client/channels.py\",\n\t\t\"lib/client/jupyter_client/clientabc.py\",\n\t\t\"lib/client/jupyter_client/blocking/__init__.py\",\n\t\t\"lib/client/jupyter_client/blocking/client.py\",\n\t\t\"lib/client/jupyter_client/blocking/channels.py\",\n\t\t\"lib/client/jupyter_client/ioloop/restarter.py\",\n\t\t\"lib/client/jupyter_client/ioloop/__init__.py\",\n\t\t\"lib/client/jupyter_client/ioloop/manager.py\",\n\t\t\"lib/client/jupyter_client/tests/__init__.py\",\n\t\t\"lib/client/jupyter_client/tests/signalkernel.py\",\n\t\t\"lib/client/jupyter_client/tests/test_multikernelmanager.py\",\n\t\t\"lib/client/jupyter_client/tests/test_client.py\",\n\t\t\"lib/client/jupyter_client/tests/test_connect.py\",\n\t\t\"lib/client/jupyter_client/tests/test_session.py\",\n\t\t\"lib/client/jupyter_client/tests/test_adapter.py\",\n\t\t\"lib/client/jupyter_client/tests/test_kernelspec.py\",\n\t\t\"lib/client/jupyter_client/tests/test_public_api.py\",\n\t\t\"lib/client/jupyter_client/tests/test_localinterfaces.py\",\n\t\t\"lib/client/jupyter_client/tests/test_jsonutil.py\",\n\t\t\"lib/client/jupyter_client/tests/test_kernelmanager.py\",\n\t\t\"lib/client/jupyter_client/tests/utils.py\",\n\t\t\"lib/client/jupyter_client/tests/test_kernelapp.py\",\n\t\t\"lib/client/jupyter_core/__init__.py\",\n\t\t\"lib/client/jupyter_core/__main__.py\",\n\t\t\"lib/client/jupyter_core/migrate.py\",\n\t\t\"lib/client/jupyter_core/troubleshoot.py\",\n\t\t\"lib/client/jupyter_core/application.py\",\n\t\t\"lib/client/jupyter_core/paths.py\",\n\t\t\"lib/client/jupyter_core/version.py\",\n\t\t\"lib/client/jupyter_core/command.py\",\n\t\t\"lib/client/jupyter_core/utils/__init__.py\",\n\t\t\"lib/client/jupyter_core/utils/shutil_which.py\",\n\t\t\"lib/client/jupyter_core/tests/__init__.py\",\n\t\t\"lib/client/jupyter_core/tests/test_paths.py\",\n\t\t\"lib/client/jupyter_core/tests/test_application.py\",\n\t\t\"lib/client/jupyter_core/tests/test_migrate.py\",\n\t\t\"lib/client/jupyter_core/tests/mocking.py\",\n\t\t\"lib/client/jupyter_core/tests/test_command.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython_empty/profile_default/ipython_notebook_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython_empty/profile_default/ipython_kernel_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython_empty/profile_default/ipython_console_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython_empty/profile_default/ipython_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython_empty/profile_default/ipython_nbconvert_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython/profile_default/ipython_notebook_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython/profile_default/ipython_kernel_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython/profile_default/ipython_console_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython/profile_default/ipython_config.py\",\n\t\t\"lib/client/jupyter_core/tests/dotipython/profile_default/ipython_nbconvert_config.py\",\n\t\t\"lib/client/traitlets/log.py\",\n\t\t\"lib/client/traitlets/traitlets.py\",\n\t\t\"lib/client/traitlets/__init__.py\",\n\t\t\"lib/client/traitlets/_version.py\",\n\t\t\"lib/client/traitlets/utils/getargspec.py\",\n\t\t\"lib/client/traitlets/utils/__init__.py\",\n\t\t\"lib/client/traitlets/utils/importstring.py\",\n\t\t\"lib/client/traitlets/utils/bunch.py\",\n\t\t\"lib/client/traitlets/utils/sentinel.py\",\n\t\t\"lib/client/traitlets/utils/tests/__init__.py\",\n\t\t\"lib/client/traitlets/utils/tests/test_bunch.py\",\n\t\t\"lib/client/traitlets/utils/tests/test_importstring.py\",\n\t\t\"lib/client/traitlets/config/__init__.py\",\n\t\t\"lib/client/traitlets/config/configurable.py\",\n\t\t\"lib/client/traitlets/config/application.py\",\n\t\t\"lib/client/traitlets/config/loader.py\",\n\t\t\"lib/client/traitlets/config/manager.py\",\n\t\t\"lib/client/traitlets/config/tests/test_configurable.py\",\n\t\t\"lib/client/traitlets/config/tests/__init__.py\",\n\t\t\"lib/client/traitlets/config/tests/test_loader.py\",\n\t\t\"lib/client/traitlets/config/tests/test_application.py\",\n\t\t\"lib/client/traitlets/tests/_warnings.py\",\n\t\t\"lib/client/traitlets/tests/__init__.py\",\n\t\t\"lib/client/traitlets/tests/test_traitlets_enum.py\",\n\t\t\"lib/client/traitlets/tests/test_traitlets.py\",\n\t\t\"lib/client/traitlets/tests/utils.py\",\n\t\t\"lib/client/ipython_genutils/__init__.py\",\n\t\t\"lib/client/ipython_genutils/importstring.py\",\n\t\t\"lib/client/ipython_genutils/ipstruct.py\",\n\t\t\"lib/client/ipython_genutils/path.py\",\n\t\t\"lib/client/ipython_genutils/_version.py\",\n\t\t\"lib/client/ipython_genutils/py3compat.py\",\n\t\t\"lib/client/ipython_genutils/encoding.py\",\n\t\t\"lib/client/ipython_genutils/tempdir.py\",\n\t\t\"lib/client/ipython_genutils/text.py\",\n\t\t\"lib/client/ipython_genutils/tests/__init__.py\",\n\t\t\"lib/client/ipython_genutils/tests/test_text.py\",\n\t\t\"lib/client/ipython_genutils/tests/test_tempdir.py\",\n\t\t\"lib/client/ipython_genutils/tests/test_path.py\",\n\t\t\"lib/client/ipython_genutils/tests/test_importstring.py\",\n\t\t\"lib/client/ipython_genutils/testing/__init__.py\",\n\t\t\"lib/client/ipython_genutils/testing/decorators.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy_extensions.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8_docstrings.py\",\n\t\t\".venv/lib/python3.8/site-packages/filelock.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8_eradicate.py\",\n\t\t\".venv/lib/python3.8/site-packages/typing_extensions.py\",\n\t\t\".venv/lib/python3.8/site-packages/easy_install.py\",\n\t\t\".venv/lib/python3.8/site-packages/cfgv.py\",\n\t\t\".venv/lib/python3.8/site-packages/toml.py\",\n\t\t\".venv/lib/python3.8/site-packages/black.py\",\n\t\t\".venv/lib/python3.8/site-packages/nodeenv.py\",\n\t\t\".venv/lib/python3.8/site-packages/pycodestyle.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8_blind_except.py\",\n\t\t\".venv/lib/python3.8/site-packages/appdirs.py\",\n\t\t\".venv/lib/python3.8/site-packages/eradicate.py\",\n\t\t\".venv/lib/python3.8/site-packages/_black_version.py\",\n\t\t\".venv/lib/python3.8/site-packages/blackd.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8_comprehensions.py\",\n\t\t\".venv/lib/python3.8/site-packages/mccabe.py\",\n\t\t\".venv/lib/python3.8/site-packages/six.py\",\n\t\t\".venv/lib/python3.8/site-packages/entrypoints.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/nodes.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/fastparse2.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/errorcodes.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/gclogger.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_typeddict.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/stubgenc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/message_registry.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/literals.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/tvar_scope.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_shared.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/applytype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/ipc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_infer.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/stats.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_newtype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/errors.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/expandtype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/checker.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/meet.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/build.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/constraints.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/fscache.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/git.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/stubdoc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/api.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/traverser.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/fswatcher.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/main.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/fastparse.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/modulefinder.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/find_sources.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_pass1.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugin.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/infer.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/scope.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typestate.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_enum.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/mixedtraverser.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/bogus_type.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/argmap.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/options.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/visitor.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/stubutil.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/binder.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typeanal.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/strconv.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typeops.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/freetree.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/config_parser.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/parse.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/suggestions.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/sitepkgs.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/checkstrformat.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/dmypy_util.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/dmypy_server.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/stubgen.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/indirection.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/type_visitor.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_main.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/renaming.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/types.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_classprop.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/checkmember.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/erasetype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/reachability.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/state.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/report.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/maptype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/subtypes.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/metastore.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/fixup.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_typeargs.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/messages.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/checkexpr.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/sametypes.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/split_namespace.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/join.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/memprofile.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/exprtotype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/util.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/lookup.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/semanal_namedtuple.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/solve.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/sharedparse.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/moduleinspect.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/moduleinfo.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/dmypy_os.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typetraverser.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/treetransform.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/mro.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/version.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typevars.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/defaults.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typeshed/tests/mypy_selftest.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typeshed/tests/mypy_test.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typeshed/tests/check_consistent.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/typeshed/tests/pytype_test.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testmoduleinfo.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testgraph.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testsamples.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testfinegrained.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testerrorstream.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testdaemon.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testinfer.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testmerge.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testpep561.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/collect.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testmodulefinder.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testdiff.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/visitors.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testcmdline.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testsubtypes.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/data.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testcheck.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testtransform.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/config.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testformatter.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testsemanal.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testdeps.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testpythoneval.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testtypes.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testreports.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/typefixture.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/update.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testfinegrainedcache.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/helpers.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testapi.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/teststubgen.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testsolve.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testparse.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testargs.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testipc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testtypegen.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/test/testmypyc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/mergecheck.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/deps.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/target.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/astdiff.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/trigger.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/aststrip.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/update.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/objgraph.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/subexpr.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/server/astmerge.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugins/attrs.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugins/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugins/common.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugins/dataclasses.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugins/enums.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugins/ctypes.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/plugins/default.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/dmypy/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/dmypy/client.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypy/dmypy/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/py31compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/extern/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/appdirs.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/six.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/_compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/__about__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/_structures.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/requirements.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/utils.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/specifiers.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/version.py\",\n\t\t\".venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/markers.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/hook.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/staged_files_only.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/envcontext.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/output.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/git.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/error_handler.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/main.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/make_archives.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/xargs.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/color.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/five.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/logging_handler.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/prefix.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/parse_shebang.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/store.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/constants.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/util.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/repository.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/clientlib.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/color_windows.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/file_lock.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/docker.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/python.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/rust.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/docker_image.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/pcre.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/ruby.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/python_venv.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/script.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/conda.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/pygrep.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/helpers.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/node.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/golang.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/all.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/fail.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/system.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/languages/swift.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/resources/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/resources/empty_template_setup.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/hook_impl.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/run.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/clean.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/try_repo.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/sample_config.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/install_uninstall.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/autoupdate.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/gc.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/init_templatedir.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/commands/migrate_config.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/meta_hooks/identity.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/meta_hooks/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/meta_hooks/check_hooks_apply.py\",\n\t\t\".venv/lib/python3.8/site-packages/pre_commit/meta_hooks/check_useless_excludes.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/error.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/info.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/pyenv_cfg.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/session.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/dirs.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/report.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/version.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/via_template.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/activator.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/batch/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/fish/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/powershell/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/cshell/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/python/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/python/activate_this.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/bash/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/activation/xonsh/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/zipapp.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/lock.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/six.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/subprocess/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/subprocess/_win_subprocess.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/path/_sync.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/path/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/path/_permission.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/path/_pathlib/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/util/path/_pathlib/via_os_path.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/run/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/run/plugin/discovery.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/run/plugin/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/run/plugin/seeders.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/run/plugin/activators.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/run/plugin/creators.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/run/plugin/base.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/discover.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/py_info.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/builtin.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/cached_py_info.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/py_spec.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/windows/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/discovery/windows/pep514.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/config/convert.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/config/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/config/ini.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/config/env_var.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/config/cli/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/config/cli/parser.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/seeder.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/via_app_data/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/via_app_data/via_app_data.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/via_app_data/pip_install/symlink.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/via_app_data/pip_install/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/via_app_data/pip_install/copy.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/via_app_data/pip_install/base.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/embed/base_embed.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/embed/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/embed/pip_invoke.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/embed/wheels/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/seed/embed/wheels/acquire.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/debug.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/describe.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/creator.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/venv.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/api.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/via_global_self_do.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/ref.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/builtin_way.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/cpython/cpython2.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/cpython/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/cpython/common.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/pypy/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/pypy/pypy2.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/pypy/common.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/python2/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/python2/site.py\",\n\t\t\".venv/lib/python3.8/site-packages/virtualenv/create/via_global_ref/builtin/python2/python2.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/nodes.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/error.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/representer.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/scanner.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/serializer.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/resolver.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/reader.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/events.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/emitter.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/composer.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/loader.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/parser.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/tokens.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/cyaml.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/constructor.py\",\n\t\t\".venv/lib/python3.8/site-packages/yaml/dumper.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/exceptions.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/status_codes.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/cmdoptions.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/basecommand.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/pep425tags.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/wheel.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/baseparser.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/locations.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/index.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/download.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/compat/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/compat/dictconfig.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/setuptools_build.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/build.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/deprecation.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/ui.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/logging.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/outdated.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/glibc.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/encoding.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/appdirs.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/hashes.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/packaging.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/utils/filesystem.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/operations/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/operations/freeze.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/operations/check.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/vcs/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/vcs/git.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/vcs/mercurial.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/vcs/bazaar.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/vcs/subversion.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/install.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/completion.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/help.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/hash.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/wheel.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/search.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/list.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/show.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/freeze.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/check.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/download.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/commands/uninstall.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/_vendor/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/models/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/models/index.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/req/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/req/req_set.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/req/req_install.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/req/req_file.py\",\n\t\t\".venv/lib/python3.8/site-packages/pip/req/req_uninstall.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/exceptions.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/emitfunc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/prebuildvisitor.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_tuple.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/crash.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/genops.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/errors.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/common.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/sametype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/build.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/emitwrapper.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/subtype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/genops_for.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/options.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_misc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_dict.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_primitive.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/emitclass.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_set.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/analysis.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/namegen.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_str.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/emit.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/refcount.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/emitmodule.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/uninit.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_exc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/rt_subtype.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_int.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/ops_list.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/cstring.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_external.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_refcount.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/testutil.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_namegen.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_emitfunc.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_genops.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_commandline.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/config.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_exceptions.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_analysis.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_run.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_tuplename.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_emit.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_serialization.py\",\n\t\t\".venv/lib/python3.8/site-packages/mypyc/test/test_emitwrapper.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/checker.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/api.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/reporter.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/messages.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/scripts/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/scripts/pyflakes.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_code_segment.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_builtin.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_api.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_return_with_arguments_inside_generator.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_checker.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_is_literal.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_doctests.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_other.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_imports.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_type_annotations.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_undefined_names.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/test_dict.py\",\n\t\t\".venv/lib/python3.8/site-packages/pyflakes/test/harness.py\",\n\t\t\".venv/lib/python3.8/site-packages/regex/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/regex/test_regex.py\",\n\t\t\".venv/lib/python3.8/site-packages/regex/regex.py\",\n\t\t\".venv/lib/python3.8/site-packages/regex/_regex_core.py\",\n\t\t\".venv/lib/python3.8/site-packages/aspy/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/aspy/yaml/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/exceptions.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/testing.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/_termui_impl.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/formatting.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/_compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/core.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/termui.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/globals.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/parser.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/types.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/decorators.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/utils.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/_unicodefun.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/_winconsole.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/_bashcomplete.py\",\n\t\t\".venv/lib/python3.8/site-packages/click/_textwrap.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/scripts.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/metadata.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/wheel.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/index.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/resources.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/database.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/manifest.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/util.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/locators.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/version.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/markers.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/_backport/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/_backport/shutil.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/_backport/misc.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.py\",\n\t\t\".venv/lib/python3.8/site-packages/distlib/_backport/tarfile.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/pattern.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/pathspec.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/util.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/patterns/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/patterns/gitwildmatch.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/tests/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/tests/test_util.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/tests/test_pathspec.py\",\n\t\t\".venv/lib/python3.8/site-packages/pathspec/tests/test_gitwildmatch.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/site-patch.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/py33compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/py31compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/archive_util.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/launch.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/glob.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/namespaces.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/dep_util.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/config.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/msvc.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/windows_support.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/pep425tags.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/wheel.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/py36compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/glibc.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/extension.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/depends.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/ssl_support.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/unicode_utils.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/sandbox.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/build_meta.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/dist.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/package_index.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/py27compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/monkey.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/version.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/lib2to3_ex.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/install.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/install_lib.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/register.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/install_egg_info.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/upload.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/build_py.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/bdist_wininst.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/test.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/alias.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/easy_install.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/upload_docs.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/egg_info.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/build_clib.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/install_scripts.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/rotate.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/saveopts.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/py36compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/sdist.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/bdist_egg.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/dist_info.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/setopt.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/develop.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/bdist_rpm.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/command/build_ext.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/extern/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/pyparsing.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/six.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/_compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/__about__.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/_structures.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/requirements.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/utils.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/specifiers.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/version.py\",\n\t\t\".venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/markers.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/exceptions.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/style_guide.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/checker.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/processor.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/statistics.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/utils.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/defaults.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/debug.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/setuptools_command.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/git.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/options.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/application.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/mercurial.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/cli.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/main/vcs.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/options/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/options/config.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/options/manager.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/options/aggregator.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/formatting/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/formatting/base.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/formatting/default.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/api/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/api/legacy.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/plugins/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/plugins/pyflakes.py\",\n\t\t\".venv/lib/python3.8/site-packages/flake8/plugins/manager.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/wordlists.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/checker.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/config.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/parser.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/violations.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/cli.py\",\n\t\t\".venv/lib/python3.8/site-packages/pydocstyle/utils.py\",\n\t\t\".venv/lib/python3.8/site-packages/identify/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/identify/identify.py\",\n\t\t\".venv/lib/python3.8/site-packages/identify/cli.py\",\n\t\t\".venv/lib/python3.8/site-packages/identify/interpreters.py\",\n\t\t\".venv/lib/python3.8/site-packages/identify/extensions.py\",\n\t\t\".venv/lib/python3.8/site-packages/identify/vendor/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/identify/vendor/licenses.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/exceptions.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/validators.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/_version_info.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/filters.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/_compat.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/converters.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/_funcs.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/_config.py\",\n\t\t\".venv/lib/python3.8/site-packages/attr/_make.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pytree.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pygram.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/literals.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/grammar.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/conv.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/pgen.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/driver.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/parse.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/tokenize.py\",\n\t\t\".venv/lib/python3.8/site-packages/blib2to3/pgen2/token.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/swedish_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/basque_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/norwegian_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/english_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/finnish_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/portuguese_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/lithuanian_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/danish_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/romanian_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/catalan_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/greek_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/german_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/dutch_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/spanish_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/hungarian_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/italian_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/russian_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/french_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/turkish_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/irish_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/porter_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/indonesian_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/tamil_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/nepali_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/basestemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/arabic_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/among.py\",\n\t\t\".venv/lib/python3.8/site-packages/snowballstemmer/hindi_stemmer.py\",\n\t\t\".venv/lib/python3.8/site-packages/toml/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/toml/encoder.py\",\n\t\t\".venv/lib/python3.8/site-packages/toml/decoder.py\",\n\t\t\".venv/lib/python3.8/site-packages/toml/tz.py\",\n\t\t\".venv/lib/python3.8/site-packages/toml/ordered.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/pie_slice.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/pylama_isort.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/__main__.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/hooks.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/main.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/settings.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/isort.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/utils.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/finders.py\",\n\t\t\".venv/lib/python3.8/site-packages/isort/natural.py\",\n\t\t\".venv/lib/python3.8/site-packages/typed_ast/__init__.py\",\n\t\t\".venv/lib/python3.8/site-packages/typed_ast/ast3.py\",\n\t\t\".venv/lib/python3.8/site-packages/typed_ast/conversions.py\",\n\t\t\".venv/lib/python3.8/site-packages/typed_ast/ast27.py\",\n\t\t\".venv/lib/python3.8/site-packages/typed_ast/tests/test_basics.py\",\n\t\t\"tests/test_cell_handling.py\",\n\t\t\"tests/_helpers.py\"\n\t]\n}\n"
  },
  {
    "path": ".codecov.yml",
    "content": "ignore:\n  - \"lib/client\"  # ignore folders and all its contents\n"
  },
  {
    "path": ".flake8",
    "content": "[flake8]\nignore =\n    # whitespace before ':'\n    E203,\n    # missing docstrings\n    D100,D101,D102,D103,D104,D105,D106,D107,\n    D203,\n    W503\nexclude =\n    .git,\n    .venv,\n    __pycache__,\n    build,\n    dist,\n    docs/source/conf.py,\n    lib,\n    old\nmax-line-length= 88\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non: [push]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        python-version: [3.8]\n\n    steps:\n    - uses: actions/checkout@v2\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions/setup-python@v1\n      with:\n        python-version: ${{ matrix.python-version }}\n    - name: Install dependencies\n      run: |\n        python -m pip install --upgrade pip\n        pip install flake8 flake8-blind-except flake8-comprehensions flake8-docstrings flake8-eradicate\n    - name: Lint with flake8\n      run: |\n        flake8 .\n"
  },
  {
    "path": ".gitignore",
    "content": "# Python Stuff\n*.pyc\n.venv/\n\n# Sublime Stuff\n*.sublime-project\n*.sublime-workspace\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "# See https://pre-commit.com for more information\n# See https://pre-commit.com/hooks.html for more hooks\ndefault_stages: [push]\ndefault_language_version:\n    python: python3.8\nexclude: \"lib/client\"\n\nrepos:\n-   repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: v2.4.0\n    hooks:\n    -   id: check-added-large-files\n    -   id: check-ast\n    -   id: check-case-conflict\n    -   id: check-merge-conflict\n    -   id: check-toml\n    -   id: check-yaml\n\n-   repo: local\n    hooks:\n    -   id: black\n        name: black\n        entry: black\n        language: system\n        types: [python]\n    -   id: flake8\n        name: flake8\n        entry: flake8\n        language: system\n        types: [python]\n        args: [--config, pyproject.toml]\n    -   id: isort\n        name: isort\n        entry: isort\n        language: system\n        types: [python]\n"
  },
  {
    "path": ".python-version",
    "content": "3.8\n"
  },
  {
    "path": "CONTRIBUTORS.md",
    "content": "This package would not exist without the original work done by NEGORO Tetsuya (https://github.com/ngr-t).\n"
  },
  {
    "path": "Default.sublime-commands",
    "content": "[\n  {\n    \"caption\": \"Helium: Connect Kernel\",\n    \"command\": \"helium_connect_kernel\"\n  },\n  {\n    \"caption\": \"Helium: Start Kernel\",\n    \"command\": \"helium_start_kernel\"\n  },\n  {\n    \"caption\": \"Helium: Shutdown Kernel\",\n    \"command\": \"helium_shutdown_kernel\"\n  },\n  {\n    \"caption\": \"Helium: Restart Kernel\",\n    \"command\": \"helium_restart_kernel\"\n  },\n  {\n    \"caption\": \"Helium: Interrupt Kernel\",\n    \"command\": \"helium_interrupt_kernel\"\n  },\n  {\n    \"caption\": \"Helium: Execute Block\",\n    \"command\": \"helium_execute_block\"\n  },\n  {\n    \"caption\": \"Helium: Execute Cell\",\n    \"command\": \"helium_execute_cell\"\n  },\n  {\n    \"caption\": \"Helium: Execute Cell and Move\",\n    \"command\": \"helium_execute_cell\", \"args\":\n    {\n      \"move_cursor\": \"True\"\n    }\n  },\n  {\n    \"caption\": \"Helium: List Kernels\",\n    \"command\": \"helium_list_kernels\"\n  },\n  {\n    \"caption\": \"Helium: Get Object Inspection\",\n    \"command\": \"helium_get_object_inspection\"\n  },\n  {\n    \"caption\": \"Helium: Clear All Cells\",\n    \"command\": \"helium_clear_all_cells\"\n  },\n  {\n    \"caption\": \"Helium: Settings\",\n    \"command\": \"edit_settings\", \"args\":\n    {\n      \"base_file\": \"${packages}/Helium/Helium.sublime-settings\",\n      \"default\": \"{\\n  \\\"connections\\\": [\\n    $0\\n  ]\\n}\"\n    }\n  }\n]\n"
  },
  {
    "path": "Default.sublime-keymap",
    "content": "[\n    {\"keys\": [\"ctrl+alt+enter\"], \"command\": \"helium_execute_cell\", \"args\": {\"move_cursor\": \"True\"}}\n]\n"
  },
  {
    "path": "Helium.sublime-settings",
    "content": "{\n  \"cell_delimiter_pattern\": \"^(#\\\\s?%%)|(# <codecell>)\\\\s*$\",\n  // Regex pattern to find code cell blocks delimiters\n  // The default value hits the patterns below.\n  // #%%\n  // # %%\n  // # <codecell>\n\n  // Whether use Helium' autocomplete powered by Jupyter kernel.\n  \"complete\": true,\n\n  // Timeout to get completion (in seconds).\n  \"complete_timeout\": 0.5,\n\n  // Set to true to show output in current view, like Jupyter\n  \"inline_output\": false,\n\n  // Set true to show the executed code in the output\n  \"output_code\": false,\n\n  // \"image_size\" controls the size of the image. It can take one three values:\n  //     \"original\":         The image is displayed with its original size.\n  //     \"resize_to_window\": The image is rescaled to match the size of the window.\n  //     \"optimal\":          The image is either resized or has its original size,\n  //                         whichever is smaller.\n  // The default is \"optimal\".\n  \"image_size\": \"optimal\",\n\n  // If you use kernels located in the directory other than default search path\n  // (see http://jupyter-client.readthedocs.io/en/stable/kernels.html#kernel-specs),\n  // set their path as below.\n  // \"jupyter_path\": \"/path/to/kernel\"\n}\n"
  },
  {
    "path": "Helium.sublime-syntax",
    "content": "%YAML 1.2\n---\nname: Helium IPython\nscope: source.helium.output\n\nvariables:\n  command_start: \"In\\\\[\\\\d+\\\\]:\"\n  error_start:   \"Error\\\\[[^\\\\]]+\\\\]:\"   # Not sure what should go inside the brackets of Error\n  streams:       \"\\\\(stdout|display data|stderr\\\\):\"\n\ncontexts:\n\n\n  main:\n    - match: |-\n        \\b({{command_start}})\n      comment: Cell contents formatted in python\n      name: cell.content\n      embed:  scope:source.python\n      escape: (?={{streams}}|{{command_start}}|{{error_start}}) # Outputs are formatted\n      captures:\n        1: markup.bold\n\n    - match: |-\n        ({{streams}})\n      name: streams\n      comment: Streams' names in bold\n      captures:\n        1: markup.italic \n"
  },
  {
    "path": "LICENSE.TXT",
    "content": "Helium package is licensed under GNU GENERAL PUBLIC LICENSE Version 2.\nYEAR: 2016-2018\nCOPYRIGHT HOLDER: NEGORO Tetsuya\n\nThis package includes libraries below.\n\n  - ipython_genutils\n  - jupyter_core\n  - traitlets\n  - decorator\n\nThis package includes a modified version of library below.\n\n  - jupyter_client\n\nipython_genutils is licensed under the terms of the Modified BSD License (also known as New or Revised or 3-Clause BSD), as follows:\n\n  - Copyright (c) 2001-, IPython Development Team\n\njupyter_core is licensed under the terms of the Modified BSD License (also known as New or Revised or 3-Clause BSD).\n\n  - Copyright (c) 2015-, Jupyter Development Team\n\njupyter_client is licensed under the terms of the Modified BSD License (also known as New or Revised or 3-Clause BSD), as follows:\n\n  - Copyright (c) 2001-2015, IPython Development Team\n  - Copyright (c) 2015-, Jupyter Development Team\n\ntraitlets is licensed under the terms of the Modified BSD License (also known as New or Revised or 3-Clause BSD), as follows:\n\n  - Copyright (c) 2001-, IPython Development Team\n\ndecorator is licensed under BSD 2-Clause \"Simplified\" License.\n\n  - Copyright (c) 2005-2018, Michele Simionato\n\n\nBSD 2-Clause License\n----\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n  Redistributions of source code must retain the above copyright\n  notice, this list of conditions and the following disclaimer.\n  Redistributions in bytecode form must reproduce the above copyright\n  notice, this list of conditions and the following disclaimer in\n  the documentation and/or other materials provided with the\n  distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS\nOF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\nUSE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGE.\n\n\nthe Modified BSD License:\n----\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\nNeither the name of the IPython Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Main.sublime-menu",
    "content": "[\n    {\n        \"caption\": \"Preferences\",\n        \"mnemonic\": \"n\",\n        \"id\": \"preferences\",\n        \"children\":\n        [\n            {\n                \"caption\": \"Package Settings\",\n                \"mnemonic\": \"P\",\n                \"id\": \"package-settings\",\n                \"children\":\n                [\n                    {\n                        \"caption\": \"Helium\",\n                        \"children\":\n                        [\n                            {\n                                \"command\": \"open_file\", \"args\":\n                                {\n                                    \"file\": \"${packages}/Helium/Helium.sublime-settings\"\n                                },\n                                \"caption\": \"Settings – Default\"\n                            },\n                            {\n                                \"command\": \"open_file\", \"args\":\n                                {\n                                    \"file\": \"${packages}/User/Helium.sublime-settings\"\n                                },\n                                \"caption\": \"Settings – User\"\n                            },\n                        ]\n                    }\n                ]\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "README.md",
    "content": "Helium package for Sublime Text\n===\n\nHelium is a package for Sublime Text, which provides in-editor code execution and autocomplete in interaction with Jupyter kernels.\nThe concept of an editor extension communicating Jupyter kernels is inspired by @nteract's splendid Atom package [Hydrogen](https://github.com/nteract/Hydrogen). I want something like it in Sublime Text, too.\n\nAny feedback is highly welcome. I hope this package will help your life with ST3!\n\n![Introduction image](raw/images/README/animated.gif)\n\n\n## Installation\n\nNow this package is under the package control channel!\n\nYou can install it with Package Control plugin, run `Package Control: Install Package`, then choose `Helium` from the package list.\n\n\n## Usage\n\n\n### Connecting to Jupyter kernels\n\n#### 1. The most basic way, start a kernelspec installed locally, as a subprocess of ST3 (the process stops when Sublime stops)\n\n  1. Run `Helium: connect kernel` command.\n  2. Choose `New kernel`.\n  3. Choose the kernelspec you want to run.\n\n\n#### 2. Connect to the kernel already runnning and connected to Helium\n\n  1. Run `Helium: connect kernel` command.\n  2. Choose the kernel you want to connect.\n\n#### 3. Connect to a kernel already running under some other Jupyter app (such as Notebook)\n\n  1. Get connection info of the kernel. The way to get connection info differ among kernels, see the doc of each kernel (in ipython kernel, you can get it by `%connect_info` magic.)\n  2. Run `Helium: connect kernel` command.\n  3. Choose `New kernel`.\n  4. Choose `(Enter connection info)`.\n  5. Enter the connection info (Helium accepts a path or connection info itself).\n\n\n#### Using Python kernel installed via Conda\n\nPython kernel installed via Conda is not found by Jupyter by default. You should add the path to kernel into the `jupyter_path` entry of the config file.\n\n\n### Execution\n\nExecute code by `Helium: Execute Block` (whose command name is `helium_execute_block`).\n\n#### Code cell\n\nRegions surrounded by `# %%` or `# <codecell>` (you can configure it in `cell_delimiter_pattern` option item) are considered as \"code cells\".\n\nYou can execute a region by `Helium: Execute cell` (`helium_execute_cell`) or `Helium: Execute Cell and Move` command.\nEach cell has a clickable \"Run Cell\" phantom that appears next to the cell markers to run the cell.\n\n### Object inspection\n\nGet Object Inspection by `Helium: Get Object Inspection` (whose command name is `helium_get_object_inspection`).\n\n### Autocomplete\n\nYou should be able to get autocomplete from the kernel from the time you connected. If you don't want autocomplete, set `\"complete\"` as `false` in setting file.\n\n### Other kernel manipulations\n\nYou can restart, shutdown, and interrupt process via `Helium: Restart Kernel`, `Helium: Shutdown Kernel`, `Helium: Interrupt Kernel` commands.\n\nYou can also run these command as a submenu of `Helium: List Kernels` command.\n\n\n## Motivation of development\n\n### Why using Jupyter?\n\nWe can execute code, retrieve results including images, get completions and object inspections by the Jupyter protocol regardless of the interpreter implementation of languages if it has Jupyter kernel.\nIf we try to do that by directly running interpreters there should be several interpreter-specific problems, but we can entrust the kernel maintainers on language-specific problems by using Jupyter.\n\n\n### Why not using Jupyter Notebook?\n\nI admit Jupyter Notebook is a powerful tool for instantly sharing small analysis work, exploring data or APIs, or making executable tutorials. Yes, I often use it, too.\nHowever, in my opinion, it is not suited for projects with large code bases.\nI want to jumpt across files instantly, make modules organized (not saved as `.ipynb`s), kick scripts with various parameters, and make project code more reusable and reproducible... but still I want to edit them with interactive feedback.\n"
  },
  {
    "path": "dependencies.json",
    "content": "{\n\t\"windows\": {\n\t\t\"<4000\": [\n\t\t\t\"dateutil\",\n\t\t\t\"enum\",\n\t\t\t\"python-six\",\n\t\t\t\"pyzmq\"\n\t\t],\n\t\t\">=4000\": [\n\t\t\t\"dateutil\",\n\t\t\t\"python-six\",\n\t\t\t\"pyzmq\",\n\t\t\t\"tornado\"\n\t\t]\n\t},\n\t\"osx\": {\n\t\t\"<4000\": [\n\t\t\t\"dateutil\",\n\t\t\t\"enum\",\n\t\t\t\"pexpect\",\n\t\t\t\"ptyprocess\",\n\t\t\t\"python-six\",\n\t\t\t\"pyzmq\"\n\t\t],\n\t\t\">=4000\": [\n\t\t\t\"dateutil\",\n\t\t\t\"pexpect\",\n\t\t\t\"ptyprocess\",\n\t\t\t\"python-six\",\n\t\t\t\"pyzmq\",\n\t\t\t\"tornado\"\n\t\t]\n\t},\n\t\"linux\": {\n\t\t\"<4000\": [\n\t\t\t\"dateutil\",\n\t\t\t\"enum\",\n\t\t\t\"pexpect\",\n\t\t\t\"ptyprocess\",\n\t\t\t\"python-six\",\n\t\t\t\"pyzmq\"\n\t\t],\n\t\t\">=4000\": [\n\t\t\t\"dateutil\",\n\t\t\t\"pexpect\",\n\t\t\t\"ptyprocess\",\n\t\t\t\"python-six\",\n\t\t\t\"pyzmq\",\n\t\t\t\"tornado\"\n\t\t]\n\t}\n}"
  },
  {
    "path": "helium.py",
    "content": "\"\"\"Helium package for Sublime Text 3.\n\nThe package provides code execution and completion in interaction with Jupyter.\n\nCopyright (c) 2016-2018, NEGORO Tetsuya (https://github.com/ngr-t)\n\"\"\"\n\nimport json\nimport os\nimport re\nimport uuid\nfrom functools import partial\nfrom logging import INFO, StreamHandler, getLogger\nfrom os.path import expanduser\n\nimport sublime\nfrom sublime_plugin import EventListener, TextCommand, ViewEventListener\n\nfrom .lib.kernel import MAX_PHANTOMS, KernelConnection\nfrom .lib.utils import add_path, chain_callbacks, get_cell\n\nwith add_path(os.path.join(os.path.dirname(__file__), \"lib/client\")):\n    # Import jupyter_client related functions and classes.\n    # Temporarily insert `lib` into sys.path not to affect other packages.\n    from jupyter_client.connect import tunnel_to_kernel\n    from jupyter_client.kernelspec import find_kernel_specs\n    from jupyter_client.manager import KernelManager\n\n\n# Logger setting\nHELIUM_LOGGER = getLogger(__name__)\nHANDLER = StreamHandler()\nHANDLER.setLevel(INFO)\n\n\nif len(HELIUM_LOGGER.handlers) == 0:\n    HELIUM_LOGGER.setLevel(INFO)\n    HELIUM_LOGGER.addHandler(HANDLER)\n\n# Regex patterns to extract code lines.\nINDENT_PATTERN = re.compile(r\"^([ \\t]*)\")\n\n\n# TODO: move CSS into separate file\nRUN_CELL_PHANTOM = \"\"\"<body id=\"helium-runCell\">\n  <style>\n    .runCell {\n        text-decoration: none;\n        color: color(var(--bluish) alpha(0.33));\n        font-style: italic;\n    }\n  </style>\n  <a class='runCell' href='runCell'>Run cell</a>\n</body>\n\"\"\"\n\nRUN_CELL_PHANTOM_ID = \"HeliumRunCell\"\n\n\nORG_JUPYTER_PATH = os.environ.get(\"JUPYTER_PATH\")\n\n\ndef _refresh_jupyter_path():\n    additional_jupyter_path = sublime.load_settings(\"Helium.sublime-settings\").get(\n        \"jupyter_path\"\n    )\n    os.environ[\"JUPYTER_PATH\"] = \":\".join(\n        [\n            path\n            for path in [ORG_JUPYTER_PATH, additional_jupyter_path]\n            if path is not None\n        ]\n    )\n\n\nclass ViewManager(object):\n    \"\"\"Manage the relation of views and kernels.\"\"\"\n\n    view_kernel_table = {}\n\n    def __new__(cls, *args, **kwargs):\n        if not hasattr(cls, \"__instance__\"):\n            cls.__instance__ = super(ViewManager, object).__new__(cls, *args, **kwargs)\n        return cls.__instance__\n\n    def __init__(self, *args, **kwargs):\n        pass\n\n    @classmethod\n    def connect_kernel(cls, buffer_id, lang, kernel_id):\n        \"\"\"Connect view to kernel.\"\"\"\n        kernel = HeliumKernelManager.get_kernel(kernel_id)\n        cls.view_kernel_table[buffer_id] = kernel\n        inline_output = sublime.load_settings(\"Helium.sublime-settings\").get(\n            \"inline_output\"\n        )\n        if not inline_output:\n            kernel.activate_view()\n\n    @classmethod\n    def remove_view(cls, buffer_id):\n        \"\"\"Remove view from manager.\"\"\"\n        if buffer_id in cls.view_kernel_table:\n            del cls.view_kernel_table[buffer_id]\n\n    @classmethod\n    def get_kernel_for_view(cls, buffer_id) -> KernelConnection:\n        \"\"\"Get Kernel instance corresponding to the buffer_id.\"\"\"\n        return cls.view_kernel_table[buffer_id]\n\n\nclass HeliumKernelManager(object):\n    \"\"\"Manage Jupyter kernels.\"\"\"\n\n    # The key is a tuple consisted of the name of kernelspec and kernel ID,\n    # the value is a KernelConnection instance correspond to it.\n    kernels = {}\n    logger = HELIUM_LOGGER\n\n    def __new__(cls, *args, **kwargs):\n        \"\"\"Make this class a singleton.\"\"\"\n        if not hasattr(cls, \"__instance__\"):\n            cls.__instance__ = super(HeliumKernelManager, object).__new__(\n                cls, *args, **kwargs\n            )\n        return cls.__instance__\n\n    @classmethod\n    def list_kernelspecs(cls):\n        \"\"\"Get the kernelspecs.\"\"\"\n        _refresh_jupyter_path()\n        return find_kernel_specs()\n\n    @classmethod\n    def list_kernels(cls):\n        \"\"\"Get the list of kernels.\"\"\"\n        return [\n            {\"name\": cls.get_kernel(kernel_id).lang, \"id\": kernel_id}\n            for kernel_id in cls.kernels.keys()\n            if cls.get_kernel(kernel_id).is_alive()\n        ]\n\n    @classmethod\n    def list_kernel_reprs(cls):\n        \"\"\"Get the list of representations of kernels.\"\"\"\n\n        def get_repr(kernel):\n            key = (kernel[\"name\"], kernel[\"id\"])\n            try:\n                return cls.kernels[key].repr\n            except KeyError:\n                return \"[{lang}] {kernel_id}\".format(\n                    lang=kernel[\"name\"], kernel_id=kernel[\"id\"]\n                )\n\n        return list(map(get_repr, cls.list_kernels()))\n\n    @classmethod\n    def get_kernel(cls, kernel_id, connection_name=None):\n        \"\"\"Get KernelConnection object.\"\"\"\n        return cls.kernels[kernel_id]\n\n    @classmethod\n    def start_kernel(\n        cls, kernelspec_name=None, connection_info=None, connection_name=None, cwd=None\n    ):\n        \"\"\"Start kernel and return a `Kernel` instance.\"\"\"\n        kernel_id = uuid.uuid4()\n        if not cwd:\n            cwd = expanduser(\"~\")\n\n        if kernelspec_name:\n            kernel_manager = KernelManager(kernel_name=kernelspec_name)\n            kernel_manager.start_kernel(cwd=cwd)\n        elif connection_info:\n            kernel_manager = KernelManager()\n            kernel_manager.load_connection_info(connection_info)\n            # `KernelManager.kernel_name` is not automatically set from connection info.\n            kernel_manager.kernel_name = connection_info.get(\"kernel_name\", \"\")\n        else:\n            raise Exception(\n                \"You must specify any of {`kernelspec_name`, `connection_info`}.\"\n            )\n        kernel = KernelConnection(\n            kernel_id,\n            kernel_manager,\n            cls,\n            connection_name=connection_name,\n            logger=cls.logger,\n        )\n        cls.kernels[kernel_id] = kernel\n        return kernel\n\n    @classmethod\n    def shutdown_kernel(cls, kernel_id):\n        \"\"\"Shutdown kernel.\"\"\"\n        cls.get_kernel(kernel_id).shutdown_kernel()\n\n    @classmethod\n    def restart_kernel(cls, kernel_id):\n        \"\"\"Restart kernel.\"\"\"\n        cls.get_kernel(kernel_id).restart_kernel()\n\n    @classmethod\n    def interrupt_kernel(cls, kernel_id):\n        \"\"\"Interrupt kernel.\"\"\"\n        cls.get_kernel(kernel_id).interrupt_kernel()\n\n\n@chain_callbacks\ndef _enter_connection_info(window, continue_cb):\n    connection_info_str = yield partial(\n        window.show_input_panel,\n        \"Enter connection info or the path to connection file.\",\n        \"\",\n        on_change=None,\n        on_cancel=None,\n    )\n    try:\n        continue_cb(json.loads(connection_info_str))\n    except ValueError:\n        try:\n            with open(connection_info_str) as infs:\n                continue_cb(json.loads(infs.read()))\n        except FileNotFoundError:\n            sublime.message_dialog(\n                \"The input string was neither a valid JSON string nor a file path.\"\n            )\n            raise\n\n\n@chain_callbacks\ndef _start_kernel(window, view, continue_cb=lambda: None, *, logger=HELIUM_LOGGER):\n    kernelspecs = HeliumKernelManager.list_kernelspecs()\n    menu_items = list(kernelspecs.keys()) + [\n        \"(Enter connection info)\",\n    ]\n    index = yield partial(window.show_quick_panel, menu_items)\n\n    cwd = None\n\n    if view:\n        cwd = expanduser(\"~\")\n    if view and view.file_name():\n        cwd = os.path.dirname(view.file_name())\n\n    if index == -1:\n        return\n    elif index == len(kernelspecs):\n        # Create a kernel from connection info.\n        connection_info = yield partial(_enter_connection_info, window)\n        connection_name = yield partial(\n            window.show_input_panel,\n            \"connection name\",\n            \"\",\n            on_change=None,\n            on_cancel=None,\n        )\n\n        if connection_name == \"\":\n            connection_name = None\n\n        kernel = HeliumKernelManager.start_kernel(\n            connection_info=connection_info, connection_name=connection_name, cwd=cwd\n        )\n    elif index == len(kernelspecs) + 1:\n        # Create a kernel with SSH tunneling.\n        servers = sublime.load_settings(\"Helium.sublime-settings\").get(\"ssh_servers\")\n        if not servers:\n            sublime.message_dialog(\n                \"Please set `ssh_servers` item of the config file via `Helium: ` \"\n                \"to connect SSH servers.\"\n            )\n            return\n        menu_items = list(servers.keys())\n        server_index = yield partial(window.show_quick_panel, menu_items)\n        server = servers[menu_items[server_index]]\n        connection_info = yield partial(_enter_connection_info, window)\n        shell_port, iopub_port, stdin_port, hb_port = tunnel_to_kernel(\n            connection_info, server[\"server\"], server.get(\"key\", None)\n        )\n        new_ports = {\n            \"shell_port\": shell_port,\n            \"iopub_port\": iopub_port,\n            \"stdin_port\": stdin_port,\n            \"hb_port\": hb_port,\n        }\n        connection_info.update(new_ports)\n        connection_name = yield partial(\n            window.show_input_panel,\n            \"connection name\",\n            \"\",\n            on_change=None,\n            on_cancel=None,\n        )\n        kernel = HeliumKernelManager.start_kernel(\n            connection_info=connection_info, connection_name=connection_name\n        )\n    else:\n        # Create a kernel from the kernelspec name.\n        selected_kernelspec = menu_items[index]\n        connection_name = yield partial(\n            window.show_input_panel,\n            \"connection name\",\n            \"\",\n            on_change=None,\n            on_cancel=None,\n        )\n        if connection_name == \"\":\n            connection_name = None\n        kernel = HeliumKernelManager.start_kernel(\n            kernelspec_name=selected_kernelspec,\n            connection_name=connection_name,\n            cwd=cwd,\n        )\n    ViewManager.connect_kernel(view.buffer_id(), kernel.lang, kernel.kernel_id)\n    if view.file_name():\n        view_name = view.file_name()\n    else:\n        view_name = view.name()\n    log_info_msg = (\n        \"Connected view '{view_name}(id: {buffer_id})'\" \"to kernel {kernel_id}.\"\n    ).format(\n        view_name=view_name, buffer_id=view.buffer_id(), kernel_id=kernel.kernel_id\n    )\n    logger.info(log_info_msg)\n\n    continue_cb()\n\n\nclass HeliumStartKernel(TextCommand):\n    \"\"\"Start a kernel and connect view to it.\"\"\"\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        \"\"\"Command definition.\"\"\"\n        _start_kernel(sublime.active_window(), self.view)\n        self.view.run_command(\"helium_clear_all_cells\")\n\n\n# TODO: Make this an enum\nclass ListKernelsSubcommands(object):\n\n    connect = \"Connect\"\n    rename = \"Rename\"\n    interrupt = \"Interrupt\"\n    restart = \"Restart\"\n    shutdown = \"Shutdown\"\n    back = \"Back to the kernel list\"\n\n\n@chain_callbacks\ndef _list_kernels(window, view, *, logger=HELIUM_LOGGER):\n    sc = ListKernelsSubcommands\n    selected_kernel = yield partial(\n        _show_kernel_selection_menu, window, view, add_new=True\n    )\n    subcommands = [\n        sc.connect,\n        sc.rename,\n        sc.interrupt,\n        sc.restart,\n        sc.shutdown,\n        sc.back,\n    ]\n    try:\n        if (\n            selected_kernel[\"id\"]\n            == ViewManager.get_kernel_for_view(view.buffer_id()).kernel_id\n        ):\n            subcommands = [sc.rename, sc.interrupt, sc.restart, sc.shutdown, sc.back]\n    except KeyError:\n        # No kernel is connected\n        # `subcommands` includes \"Connect\"\n        pass\n    index = yield partial(window.show_quick_panel, subcommands)\n    if index == -1:\n        return\n    elif subcommands[index] is sc.connect:\n        # Connect\n        ViewManager.connect_kernel(\n            view.buffer_id(), selected_kernel[\"name\"], selected_kernel[\"id\"]\n        )\n        if view.file_name():\n            view_name = view.file_name()\n        else:\n            view_name = view.name()\n        log_info_msg = (\n            \"Connected view '{view_name}(id: {buffer_id})'\" \"to kernel {kernel_id}.\"\n        ).format(\n            view_name=view_name,\n            buffer_id=view.buffer_id(),\n            kernel_id=selected_kernel[\"id\"],\n        )\n        logger.info(log_info_msg)\n    elif subcommands[index] is sc.rename:\n        # Rename\n        conn = HeliumKernelManager.get_kernel(selected_kernel[\"id\"])\n        curr_name = conn.connection_name if conn.connection_name is not None else \"\"\n        new_name = yield partial(\n            window.show_input_panel,\n            \"New name\",\n            curr_name,\n            on_change=None,\n            on_cancel=None,\n        )\n        conn.connection_name = new_name\n    elif subcommands[index] is sc.interrupt:\n        # Interrupt\n        HeliumKernelManager.interrupt_kernel(selected_kernel[\"id\"])\n        log_info_msg = (\"Interrupted kernel {kernel_id}.\").format(\n            kernel_id=selected_kernel[\"id\"]\n        )\n        logger.info(log_info_msg)\n    elif subcommands[index] is sc.restart:\n        # Restart\n        HeliumKernelManager.restart_kernel(selected_kernel[\"id\"])\n        log_info_msg = (\"Restarted kernel {kernel_id}.\").format(\n            kernel_id=selected_kernel[\"id\"]\n        )\n        logger.info(log_info_msg)\n    elif subcommands[index] is sc.shutdown:\n        # Shutdown\n        HeliumKernelManager.shutdown_kernel(selected_kernel[\"id\"])\n        log_info_msg = (\"Shutdown kernel {kernel_id}.\").format(\n            kernel_id=selected_kernel[\"id\"]\n        )\n        logger.info(log_info_msg)\n    elif subcommands[index] is sc.back:\n        # Back to the kernel list\n        yield _list_kernels(window, view)\n    sublime.set_timeout_async(lambda: StatusBar(view), 0)\n\n\nclass HeliumListKernels(TextCommand):\n    \"\"\"Command that shows the list of kernels and do some action for chosen kernels.\"\"\"\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        _list_kernels(sublime.active_window(), self.view)\n\n\n@chain_callbacks\ndef _connect_kernel(window, view, *, continue_cb=lambda: None, logger=HELIUM_LOGGER):\n    kernel_list = HeliumKernelManager.list_kernels()\n    menu_items = [\n        \"[{lang}] {kernel_id}\".format(lang=kernel[\"name\"], kernel_id=kernel[\"id\"])\n        for kernel in kernel_list\n    ]\n    menu_items += [\"New kernel\"]\n\n    index = yield partial(window.show_quick_panel, menu_items)\n\n    if index == -1:\n        return\n    elif index == len(kernel_list):\n        yield partial(_start_kernel, window, view)\n    else:\n        selected_kernel = kernel_list[index]\n        ViewManager.connect_kernel(\n            view.buffer_id(), selected_kernel[\"name\"], selected_kernel[\"id\"]\n        )\n        if view.file_name():\n            view_name = view.file_name()\n        else:\n            view_name = view.name()\n\n        update_run_cell_phantoms(view)\n\n        log_info_msg = (\n            \"Connected view '{view_name}(id: {buffer_id})' to kernel {kernel_id}.\"\n        ).format(\n            view_name=view_name,\n            buffer_id=view.buffer_id(),\n            kernel_id=selected_kernel[\"id\"],\n        )\n        logger.info(log_info_msg)\n    sublime.set_timeout_async(lambda: StatusBar(view), 0)\n    continue_cb()\n\n\nclass HeliumConnectKernel(TextCommand):\n    \"\"\"Connect to Jupyter kernel.\"\"\"\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        \"\"\"Command definition.\"\"\"\n        _connect_kernel(sublime.active_window(), self.view, logger=logger)\n        self.view.run_command(\"helium_clear_all_cells\")\n\n\n@chain_callbacks\ndef _show_kernel_selection_menu(window, view, cb, *, add_new=False):\n    # Get the kernel ID related to `view` if exists.\n    try:\n        current_kernel_id = ViewManager.get_kernel_for_view(view.buffer_id()).kernel_id\n    except KeyError:\n        # TODO fix to use property of views.\n        result = re.match(r\"\\*Helium Output\\* .*?\\(\\[.*?\\] ([\\w-]*)\\)\", view.name())\n        if result:\n            current_kernel_id = result.group(1)\n        else:\n            current_kernel_id = \"\"\n\n    # It's better to pass the list of (connection_name, kernel_id) tuples\n    # to improve the appearane of the menu.\n    kernel_list = HeliumKernelManager.list_kernels()\n    menu_items = [\n        \"* \" + repr if kernel[\"id\"] == current_kernel_id else repr\n        for repr, kernel in zip(HeliumKernelManager.list_kernel_reprs(), kernel_list)\n    ]\n    if add_new:\n        menu_items += [\"New kernel\"]\n    index = yield partial(window.show_quick_panel, menu_items)\n    if index == -1:\n        selected_kernel = None\n    elif index == len(kernel_list):\n        yield partial(_start_kernel, window, view)\n    else:\n        selected_kernel = kernel_list[index]\n    cb(selected_kernel)\n\n\n@chain_callbacks\ndef _interrupt_kernel(window, view, *, continue_cb=lambda: None, logger=HELIUM_LOGGER):\n    selected_kernel = yield partial(_show_kernel_selection_menu, window, view)\n    if selected_kernel is not None:\n        HeliumKernelManager.interrupt_kernel(selected_kernel[\"id\"])\n        log_info_msg = (\"Interrupted kernel {kernel_id}.\").format(\n            kernel_id=selected_kernel[\"id\"]\n        )\n        logger.info(log_info_msg)\n    continue_cb()\n\n\nclass HeliumInterruptKernel(TextCommand):\n    \"\"\"Interrupt Jupyter kernel.\"\"\"\n\n    def is_enabled(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n        except KeyError:\n            return False\n        return HeliumKernelManager.get_kernel(kernel.kernel_id).is_alive()\n\n    def is_visible(self, *, logger=HELIUM_LOGGER):\n        return self.is_enabled()\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        \"\"\"Command definition.\"\"\"\n        _interrupt_kernel(sublime.active_window(), self.view, logger=logger)\n\n\n@chain_callbacks\ndef _restart_kernel(window, view, *, continue_cb=lambda: None, logger=HELIUM_LOGGER):\n    selected_kernel = yield partial(_show_kernel_selection_menu, window, view)\n    if selected_kernel is not None:\n        HeliumKernelManager.restart_kernel(selected_kernel[\"id\"])\n        log_info_msg = (\"Restarted kernel {kernel_id}.\").format(\n            kernel_id=selected_kernel[\"id\"]\n        )\n        logger.info(log_info_msg)\n    continue_cb()\n\n\nclass HeliumRestartKernel(TextCommand):\n    \"\"\"Restart Jupyter kernel.\"\"\"\n\n    def is_enabled(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n        except KeyError:\n            return False\n        return HeliumKernelManager.get_kernel(kernel.kernel_id).is_alive()\n\n    def is_visible(self, *, logger=HELIUM_LOGGER):\n        return self.is_enabled()\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        \"\"\"Command definition.\"\"\"\n        _restart_kernel(sublime.active_window(), self.view, logger=logger)\n        self.view.run_command(\"helium_clear_all_cells\")\n\n\n@chain_callbacks\ndef _shutdown_kernel(window, view, *, continue_cb=lambda: None, logger=HELIUM_LOGGER):\n    selected_kernel = yield partial(_show_kernel_selection_menu, window, view)\n    if selected_kernel is not None:\n        HeliumKernelManager.shutdown_kernel(selected_kernel[\"id\"])\n        log_info_msg = (\"Shutdown kernel {kernel_id}.\").format(\n            kernel_id=selected_kernel[\"id\"]\n        )\n        logger.info(log_info_msg)\n    ViewManager.remove_view(view.buffer_id())\n    view.set_status(\"helium_connected_kernel\", \"\")\n    continue_cb()\n\n\nclass HeliumShutdownKernel(TextCommand):\n    \"\"\"Shutdown Jupyter kernel.\"\"\"\n\n    def is_enabled(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n        except KeyError:\n            return False\n        return HeliumKernelManager.get_kernel(kernel.kernel_id).is_alive()\n\n    def is_visible(self, *, logger=HELIUM_LOGGER):\n        return self.is_enabled()\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        \"\"\"Command definition.\"\"\"\n        _shutdown_kernel(sublime.active_window(), self.view, logger=logger)\n\n\nclass HeliumRunCellManager(ViewEventListener):\n    \"\"\"Manage 'Run cell' phantoms.\"\"\"\n\n    def __init__(self, view):\n        self.view = view\n        self.timeout_scheduled = False\n        self.needs_update = False\n\n    def on_modified(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n            if not kernel.is_alive():\n                return\n        except KeyError:\n            return\n\n        # Call update_run_cell_phantoms(), but not any more than 10 times a second\n        if self.timeout_scheduled:\n            self.needs_update = True\n        else:\n            sublime.set_timeout(lambda: self.handle_timeout(), 100)\n            self.timeout_scheduled = True\n            update_run_cell_phantoms(self.view, logger=logger)\n\n    def handle_timeout(self):\n        self.timeout_scheduled = False\n        if self.needs_update:\n            self.needs_update = False\n            update_run_cell_phantoms(self.view)\n\n\ndef update_run_cell_phantoms(view, *, logger=HELIUM_LOGGER):\n    \"\"\"Add \"Run Cell\" links to each code cell.\"\"\"\n    # find all cell delimiters:\n    cell_delimiter_pattern = sublime.load_settings(\"Helium.sublime-settings\").get(\n        \"cell_delimiter_pattern\"\n    )\n    limits = view.find_all(cell_delimiter_pattern)\n    # append a virtual delimiter at EOF\n    limits.append(sublime.Region(view.size(), view.size()))\n\n    # remove existing Run cell phantoms, we'll recreate all of them\n    view.erase_phantoms(RUN_CELL_PHANTOM_ID)\n\n    for i in range(len(limits) - 1):\n        code_region = sublime.Region(limits[i].end() + 1, limits[i + 1].begin() + 0)\n        phantom_region = sublime.Region(limits[i].end(), limits[i].end())\n        view.add_phantom(\n            RUN_CELL_PHANTOM_ID,\n            phantom_region,\n            RUN_CELL_PHANTOM,\n            sublime.LAYOUT_INLINE,\n            on_navigate=lambda href, view=view, region=code_region: _execute_cell(\n                view, region\n            ),\n        )\n\n\ndef get_line(view: sublime.View, row: int) -> str:\n    \"\"\"Get the code line under the cursor.\"\"\"\n    point = view.text_point(row, 0)\n    line_region = view.line(point)\n    return view.substr(line_region)\n\n\ndef get_indent(view: sublime.View, row: int) -> str:\n    line = get_line(view, row)\n    return INDENT_PATTERN.match(line).group()\n\n\ndef get_block(view: sublime.View, s: sublime.Region) -> (str, sublime.Region):\n    \"\"\"Get the code block under the cursor.\n\n    The code block is the lines satisfying the following conditions:\n\n      - Includes the line under the cursor.\n      - Includes no blank line.\n      - More indented than that of the line under the cursor.\n\n    If `s` is a selected region, the code block is it.\n    \"\"\"\n    if not s.empty():\n        return (view.substr(s), s)\n    view_end_row = view.rowcol(view.size())[0]\n    current_row = view.rowcol(s.begin())[0]\n    current_indent = get_indent(view, current_row)\n    start_point = 0\n    for first_row in range(current_row, -1, -1):\n        indent = get_indent(view, first_row)\n        if (\n            not indent.startswith(current_indent)\n            or get_line(view, first_row).strip() == \"\"\n        ):\n            start_point = view.text_point(first_row + 1, 0)\n            break\n    end_point = view.size()\n    for last_row in range(current_row, view_end_row + 1):\n        indent = get_indent(view, last_row)\n        if (\n            not indent.startswith(current_indent)\n            or get_line(view, last_row).strip() == \"\"\n        ):\n            end_point = view.text_point(last_row, 0) - 1\n            break\n    block_region = sublime.Region(start_point, end_point)\n    return (view.substr(block_region), block_region)\n\n\n@chain_callbacks\ndef _execute_block(view, *, logger=HELIUM_LOGGER):\n    try:\n        kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n    except KeyError:\n        sublime.message_dialog(\"No kernel is connected to this view.\")\n        yield lambda cb: _connect_kernel(sublime.active_window(), view, continue_cb=cb)\n        kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n\n    pre_code = []\n    for s in view.sel():\n        code, region = get_block(view, s)\n        if code == pre_code:\n            continue\n        kernel.execute_code(code, region, view)\n        log_info_msg = \"Executed code {code} with kernel {kernel_id}\".format(\n            code=code, kernel_id=kernel.kernel_id\n        )\n        logger.info(log_info_msg)\n        pre_code = code\n\n\n@chain_callbacks\ndef _execute_cell(view, region: sublime.Region, *, logger=HELIUM_LOGGER):\n    try:\n        kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n    except KeyError:\n        sublime.message_dialog(\"No kernel is connected to this view.\")\n        yield lambda cb: _connect_kernel(sublime.active_window(), view, continue_cb=cb)\n        kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n\n    code, cell = get_cell(view, region, logger=logger)\n    kernel.execute_code(code, cell, view)\n    log_info_msg = \"Executed code {code} with kernel {kernel_id}\".format(\n        code=code, kernel_id=kernel.kernel_id\n    )\n    logger.info(log_info_msg)\n\n\nclass HeliumExecuteBlock(TextCommand):\n    \"\"\"Execute code.\"\"\"\n\n    def is_enabled(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n        except KeyError:\n            return False\n        return HeliumKernelManager.get_kernel(kernel.kernel_id).is_alive()\n\n    def is_visible(self, *, logger=HELIUM_LOGGER):\n        return self.is_enabled()\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        \"\"\"Command definition.\"\"\"\n        _execute_block(self.view, logger=logger)\n\n\nclass HeliumExecuteCell(TextCommand):\n    \"\"\"Execute code cell.\"\"\"\n\n    def is_enabled(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n        except KeyError:\n            return False\n        return kernel.is_alive()\n\n    def is_visible(self, *, logger=HELIUM_LOGGER):\n        return self.is_enabled()\n\n    def run(self, edit, move_cursor=False, *, logger=HELIUM_LOGGER):\n        \"\"\"If move_cursor is true, move the cursor to the next cell after execution.\"\"\"\n        for s in self.view.sel():\n            _execute_cell(self.view, s, logger=logger)\n\n        if move_cursor:\n            _, cell = get_cell(self.view, self.view.sel()[-1], logger=logger)\n            pt = sublime.Region(cell.end() + 1, cell.end() + 1)\n            self.view.sel().clear()\n            self.view.sel().add(pt)\n            # TODO: scroll to cursor after phantoms after Jupyter callback\n            # rather than fixed time\n            sublime.set_timeout(lambda: self.view.show(pt), 500)\n\n\nclass HeliumClearAllCells(TextCommand):\n    \"\"\"Clear all phantoms.\"\"\"\n\n    def is_enabled(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n\n            # if view has an attached kernel, return its status\n            return kernel.is_alive()\n        except KeyError:\n            # if view doesn't have an attached kernel, check if view was created by\n            # kernel\n            parent_view = self._get_parent_view()\n            return parent_view is not None\n\n    def is_visible(self, *, logger=HELIUM_LOGGER):\n        return self.is_enabled()\n\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        # get correct kernel\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n        except KeyError:\n            view = self._get_parent_view()\n            kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n\n        def cb():\n            if kernel._show_inline_output:\n                for k in range(MAX_PHANTOMS):\n                    self.view.erase_phantom_by_id(k)\n            else:\n                kernel.get_view().close()\n                kernel.activate_view()\n\n        # clear the old phantoms async\n        sublime.set_timeout_async(cb, 0)\n\n    def _get_parent_view(self) -> sublime.View:\n        for window in sublime.windows():\n            for view in window.views():\n                try:\n                    kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n                except KeyError:\n                    continue\n\n                if kernel.get_view() == self.view:\n                    return view\n        return None\n\n\nclass StatusBar(object):\n    \"\"\"Status Bar with animation.\n\n    This class is based on the one by @randy3k.\n    \"\"\"\n\n    def __init__(self, view, width=10, interval=500):\n        self.view = view\n        self.width = width\n        self.buffer_id = view.buffer_id()\n        self.interval = interval\n        self.pos = 0\n        try:\n            self.kernel = ViewManager.get_kernel_for_view(self.buffer_id)\n            self.start()\n        except KeyError:\n            # When view is not connected.\n            self.stop()\n\n    def start(self):\n        self.update()\n\n    def stop(self):\n        self.view.set_status(\"helium_connected_kernel\", \"\")\n\n    def update(self, pos=0):\n        # `pos` can't be a property of `StatusBar` because it's not updated\n        # when `update()` is called by `sublime.set_timeout[_async]()`.\n        if self.buffer_id != sublime.active_window().active_view().buffer_id():\n            # Stop when view is unfocused.\n            self.stop()\n            return\n        execution_state = self.kernel.execution_state\n        if execution_state == \"dead\":\n            # Stop when kernel is dead.\n            self.view.set_status(\"helium_connected_kernel\", \"\")\n            return\n        elif execution_state == \"busy\":\n            pos = pos % (2 * self.width)\n            before = min(pos, (2 * self.width) - pos)\n            after = self.width - before\n            progress_bar = \" [{}={}]\".format(\" \" * before, \" \" * after)\n        else:\n            # Make progress bar always start with pos=0.\n            pos = -1\n            progress_bar = \"\"\n        status = (\n            \"{repr} (state: {execution_state})\".format(\n                repr=self.kernel.repr, execution_state=self.kernel.execution_state\n            )\n            + progress_bar\n        )\n        self.view.set_status(\"helium_connected_kernel\", status)\n        sublime.set_timeout_async(lambda: self.update(pos + 1), self.interval)\n\n\nclass HeliumStatusUpdater(ViewEventListener):\n    \"\"\"Listen to the heartbeat of kernel and update status of view.\"\"\"\n\n    def on_activated_async(self):\n        sublime.set_timeout_async(lambda: StatusBar(self.view), 0)\n\n\nclass HeliumGetObjectInspection(TextCommand):\n    \"\"\"Get object inspection.\"\"\"\n\n    def is_enabled(self, *, logger=HELIUM_LOGGER):\n        try:\n            kernel = ViewManager.get_kernel_for_view(self.view.buffer_id())\n        except KeyError:\n            return False\n        return HeliumKernelManager.get_kernel(kernel.kernel_id).is_alive()\n\n    def is_visible(self, *, logger=HELIUM_LOGGER):\n        return self.is_enabled()\n\n    @chain_callbacks\n    def run(self, edit, *, logger=HELIUM_LOGGER):\n        view = self.view\n        try:\n            kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n        except KeyError:\n            sublime.message_dialog(\"No kernel is connected to this view.\")\n            yield lambda cb: _connect_kernel(\n                sublime.active_window(), view, continue_cb=cb\n            )\n            kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n\n        pre_code = []\n        for s in view.sel():\n            code, region = get_block(view, s)\n            cursor_pos = s.end() - region.begin()\n            if code == pre_code:\n                continue\n            kernel.get_inspection(code, cursor_pos)\n            log_info_msg = (\n                \"Requested object inspection for code {code} with kernel {kernel_id}\"\n            ).format(code=code, kernel_id=kernel.kernel_id)\n\n            logger.info(log_info_msg)\n            pre_code = code\n\n\nclass HeliumCompleter(EventListener):\n    \"\"\"Completer.\"\"\"\n\n    def on_query_completions(self, view, prefix, locations, *, logger=HELIUM_LOGGER):\n        \"\"\"Get completions from the Jupyter kernel.\"\"\"\n        use_complete = sublime.load_settings(\"Helium.sublime-settings\").get(\"complete\")\n        if not use_complete:\n            return None\n        timeout = sublime.load_settings(\"Helium.sublime-settings\").get(\n            \"complete_timeout\"\n        )\n        try:\n            kernel = ViewManager.get_kernel_for_view(view.buffer_id())\n            location = locations[0]\n            code = view.substr(view.line(location))\n            log_info_msg = (\n                \"Requested completion for code {code} with kernel {kernel_id}\"\n            ).format(code=code, kernel_id=kernel.kernel_id)\n            logger.info(log_info_msg)\n            _, col = view.rowcol(location)\n            return kernel.get_complete(code, col, timeout)\n        except Exception:  # noqa\n            return None\n"
  },
  {
    "path": "lib/__init__.py",
    "content": ""
  },
  {
    "path": "lib/client/__init__.py",
    "content": ""
  },
  {
    "path": "lib/client/decorator.py",
    "content": "# #########################     LICENSE     ############################ #\n\n# Copyright (c) 2005-2018, Michele Simionato\n# All rights reserved.\n\n# Redistribution and use in source and binary forms, with or without\n# modification, are permitted provided that the following conditions are\n# met:\n\n#   Redistributions of source code must retain the above copyright\n#   notice, this list of conditions and the following disclaimer.\n#   Redistributions in bytecode form must reproduce the above copyright\n#   notice, this list of conditions and the following disclaimer in\n#   the documentation and/or other materials provided with the\n#   distribution.\n\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n# \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n# HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS\n# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\n# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\n# DAMAGE.\n\n\"\"\"\nDecorator module, see http://pypi.python.org/pypi/decorator\nfor the documentation.\n\"\"\"\nfrom __future__ import print_function\n\nimport re\nimport sys\nimport inspect\nimport operator\nimport itertools\nimport collections\n\n__version__ = '4.4.2'\n\nif sys.version_info >= (3,):\n    from inspect import getfullargspec\n\n    def get_init(cls):\n        return cls.__init__\nelse:\n    FullArgSpec = collections.namedtuple(\n        'FullArgSpec', 'args varargs varkw defaults '\n        'kwonlyargs kwonlydefaults annotations')\n\n    def getfullargspec(f):\n        \"A quick and dirty replacement for getfullargspec for Python 2.X\"\n        return FullArgSpec._make(inspect.getargspec(f) + ([], None, {}))\n\n    def get_init(cls):\n        return cls.__init__.__func__\n\ntry:\n    iscoroutinefunction = inspect.iscoroutinefunction\nexcept AttributeError:\n    # let's assume there are no coroutine functions in old Python\n    def iscoroutinefunction(f):\n        return False\ntry:\n    from inspect import isgeneratorfunction\nexcept ImportError:\n    # assume no generator function in old Python versions\n    def isgeneratorfunction(caller):\n        return False\n\n\nDEF = re.compile(r'\\s*def\\s*([_\\w][_\\w\\d]*)\\s*\\(')\n\n\n# basic functionality\nclass FunctionMaker(object):\n    \"\"\"\n    An object with the ability to create functions with a given signature.\n    It has attributes name, doc, module, signature, defaults, dict and\n    methods update and make.\n    \"\"\"\n\n    # Atomic get-and-increment provided by the GIL\n    _compile_count = itertools.count()\n\n    # make pylint happy\n    args = varargs = varkw = defaults = kwonlyargs = kwonlydefaults = ()\n\n    def __init__(self, func=None, name=None, signature=None,\n                 defaults=None, doc=None, module=None, funcdict=None):\n        self.shortsignature = signature\n        if func:\n            # func can be a class or a callable, but not an instance method\n            self.name = func.__name__\n            if self.name == '<lambda>':  # small hack for lambda functions\n                self.name = '_lambda_'\n            self.doc = func.__doc__\n            self.module = func.__module__\n            if inspect.isfunction(func):\n                argspec = getfullargspec(func)\n                self.annotations = getattr(func, '__annotations__', {})\n                for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',\n                          'kwonlydefaults'):\n                    setattr(self, a, getattr(argspec, a))\n                for i, arg in enumerate(self.args):\n                    setattr(self, 'arg%d' % i, arg)\n                allargs = list(self.args)\n                allshortargs = list(self.args)\n                if self.varargs:\n                    allargs.append('*' + self.varargs)\n                    allshortargs.append('*' + self.varargs)\n                elif self.kwonlyargs:\n                    allargs.append('*')  # single star syntax\n                for a in self.kwonlyargs:\n                    allargs.append('%s=None' % a)\n                    allshortargs.append('%s=%s' % (a, a))\n                if self.varkw:\n                    allargs.append('**' + self.varkw)\n                    allshortargs.append('**' + self.varkw)\n                self.signature = ', '.join(allargs)\n                self.shortsignature = ', '.join(allshortargs)\n                self.dict = func.__dict__.copy()\n        # func=None happens when decorating a caller\n        if name:\n            self.name = name\n        if signature is not None:\n            self.signature = signature\n        if defaults:\n            self.defaults = defaults\n        if doc:\n            self.doc = doc\n        if module:\n            self.module = module\n        if funcdict:\n            self.dict = funcdict\n        # check existence required attributes\n        assert hasattr(self, 'name')\n        if not hasattr(self, 'signature'):\n            raise TypeError('You are decorating a non function: %s' % func)\n\n    def update(self, func, **kw):\n        \"Update the signature of func with the data in self\"\n        func.__name__ = self.name\n        func.__doc__ = getattr(self, 'doc', None)\n        func.__dict__ = getattr(self, 'dict', {})\n        func.__defaults__ = self.defaults\n        func.__kwdefaults__ = self.kwonlydefaults or None\n        func.__annotations__ = getattr(self, 'annotations', None)\n        try:\n            frame = sys._getframe(3)\n        except AttributeError:  # for IronPython and similar implementations\n            callermodule = '?'\n        else:\n            callermodule = frame.f_globals.get('__name__', '?')\n        func.__module__ = getattr(self, 'module', callermodule)\n        func.__dict__.update(kw)\n\n    def make(self, src_templ, evaldict=None, addsource=False, **attrs):\n        \"Make a new function from a given template and update the signature\"\n        src = src_templ % vars(self)  # expand name and signature\n        evaldict = evaldict or {}\n        mo = DEF.search(src)\n        if mo is None:\n            raise SyntaxError('not a valid function template\\n%s' % src)\n        name = mo.group(1)  # extract the function name\n        names = set([name] + [arg.strip(' *') for arg in\n                              self.shortsignature.split(',')])\n        for n in names:\n            if n in ('_func_', '_call_'):\n                raise NameError('%s is overridden in\\n%s' % (n, src))\n\n        if not src.endswith('\\n'):  # add a newline for old Pythons\n            src += '\\n'\n\n        # Ensure each generated function has a unique filename for profilers\n        # (such as cProfile) that depend on the tuple of (<filename>,\n        # <definition line>, <function name>) being unique.\n        filename = '<decorator-gen-%d>' % next(self._compile_count)\n        try:\n            code = compile(src, filename, 'single')\n            exec(code, evaldict)\n        except Exception:\n            print('Error in generated code:', file=sys.stderr)\n            print(src, file=sys.stderr)\n            raise\n        func = evaldict[name]\n        if addsource:\n            attrs['__source__'] = src\n        self.update(func, **attrs)\n        return func\n\n    @classmethod\n    def create(cls, obj, body, evaldict, defaults=None,\n               doc=None, module=None, addsource=True, **attrs):\n        \"\"\"\n        Create a function from the strings name, signature and body.\n        evaldict is the evaluation dictionary. If addsource is true an\n        attribute __source__ is added to the result. The attributes attrs\n        are added, if any.\n        \"\"\"\n        if isinstance(obj, str):  # \"name(signature)\"\n            name, rest = obj.strip().split('(', 1)\n            signature = rest[:-1]  # strip a right parens\n            func = None\n        else:  # a function\n            name = None\n            signature = None\n            func = obj\n        self = cls(func, name, signature, defaults, doc, module)\n        ibody = '\\n'.join('    ' + line for line in body.splitlines())\n        caller = evaldict.get('_call_')  # when called from `decorate`\n        if caller and iscoroutinefunction(caller):\n            body = ('async def %(name)s(%(signature)s):\\n' + ibody).replace(\n                'return', 'return await')\n        else:\n            body = 'def %(name)s(%(signature)s):\\n' + ibody\n        return self.make(body, evaldict, addsource, **attrs)\n\n\ndef decorate(func, caller, extras=()):\n    \"\"\"\n    decorate(func, caller) decorates a function using a caller.\n    If the caller is a generator function, the resulting function\n    will be a generator function.\n    \"\"\"\n    evaldict = dict(_call_=caller, _func_=func)\n    es = ''\n    for i, extra in enumerate(extras):\n        ex = '_e%d_' % i\n        evaldict[ex] = extra\n        es += ex + ', '\n\n    if '3.5' <= sys.version < '3.6':\n        # with Python 3.5 isgeneratorfunction returns True for all coroutines\n        # however we know that it is NOT possible to have a generator\n        # coroutine in python 3.5: PEP525 was not there yet\n        generatorcaller = isgeneratorfunction(\n            caller) and not iscoroutinefunction(caller)\n    else:\n        generatorcaller = isgeneratorfunction(caller)\n    if generatorcaller:\n        fun = FunctionMaker.create(\n            func, \"for res in _call_(_func_, %s%%(shortsignature)s):\\n\"\n                  \"    yield res\" % es, evaldict, __wrapped__=func)\n    else:\n        fun = FunctionMaker.create(\n            func, \"return _call_(_func_, %s%%(shortsignature)s)\" % es,\n            evaldict, __wrapped__=func)\n    if hasattr(func, '__qualname__'):\n        fun.__qualname__ = func.__qualname__\n    return fun\n\n\ndef decorator(caller, _func=None):\n    \"\"\"decorator(caller) converts a caller function into a decorator\"\"\"\n    if _func is not None:  # return a decorated function\n        # this is obsolete behavior; you should use decorate instead\n        return decorate(_func, caller)\n    # else return a decorator function\n    defaultargs, defaults = '', ()\n    if inspect.isclass(caller):\n        name = caller.__name__.lower()\n        doc = 'decorator(%s) converts functions/generators into ' \\\n            'factories of %s objects' % (caller.__name__, caller.__name__)\n    elif inspect.isfunction(caller):\n        if caller.__name__ == '<lambda>':\n            name = '_lambda_'\n        else:\n            name = caller.__name__\n        doc = caller.__doc__\n        nargs = caller.__code__.co_argcount\n        ndefs = len(caller.__defaults__ or ())\n        defaultargs = ', '.join(caller.__code__.co_varnames[nargs-ndefs:nargs])\n        if defaultargs:\n            defaultargs += ','\n        defaults = caller.__defaults__\n    else:  # assume caller is an object with a __call__ method\n        name = caller.__class__.__name__.lower()\n        doc = caller.__call__.__doc__\n    evaldict = dict(_call=caller, _decorate_=decorate)\n    dec = FunctionMaker.create(\n        '%s(func, %s)' % (name, defaultargs),\n        'if func is None: return lambda func:  _decorate_(func, _call, (%s))\\n'\n        'return _decorate_(func, _call, (%s))' % (defaultargs, defaultargs),\n        evaldict, doc=doc, module=caller.__module__, __wrapped__=caller)\n    if defaults:\n        dec.__defaults__ = (None,) + defaults\n    return dec\n\n\n# ####################### contextmanager ####################### #\n\ntry:  # Python >= 3.2\n    from contextlib import _GeneratorContextManager\nexcept ImportError:  # Python >= 2.5\n    from contextlib import GeneratorContextManager as _GeneratorContextManager\n\n\nclass ContextManager(_GeneratorContextManager):\n    def __call__(self, func):\n        \"\"\"Context manager decorator\"\"\"\n        return FunctionMaker.create(\n            func, \"with _self_: return _func_(%(shortsignature)s)\",\n            dict(_self_=self, _func_=func), __wrapped__=func)\n\n\ninit = getfullargspec(_GeneratorContextManager.__init__)\nn_args = len(init.args)\nif n_args == 2 and not init.varargs:  # (self, genobj) Python 2.7\n    def __init__(self, g, *a, **k):\n        return _GeneratorContextManager.__init__(self, g(*a, **k))\n    ContextManager.__init__ = __init__\nelif n_args == 2 and init.varargs:  # (self, gen, *a, **k) Python 3.4\n    pass\nelif n_args == 4:  # (self, gen, args, kwds) Python 3.5\n    def __init__(self, g, *a, **k):\n        return _GeneratorContextManager.__init__(self, g, a, k)\n    ContextManager.__init__ = __init__\n\n_contextmanager = decorator(ContextManager)\n\n\ndef contextmanager(func):\n    # Enable Pylint config: contextmanager-decorators=decorator.contextmanager\n    return _contextmanager(func)\n\n\n# ############################ dispatch_on ############################ #\n\ndef append(a, vancestors):\n    \"\"\"\n    Append ``a`` to the list of the virtual ancestors, unless it is already\n    included.\n    \"\"\"\n    add = True\n    for j, va in enumerate(vancestors):\n        if issubclass(va, a):\n            add = False\n            break\n        if issubclass(a, va):\n            vancestors[j] = a\n            add = False\n    if add:\n        vancestors.append(a)\n\n\n# inspired from simplegeneric by P.J. Eby and functools.singledispatch\ndef dispatch_on(*dispatch_args):\n    \"\"\"\n    Factory of decorators turning a function into a generic function\n    dispatching on the given arguments.\n    \"\"\"\n    assert dispatch_args, 'No dispatch args passed'\n    dispatch_str = '(%s,)' % ', '.join(dispatch_args)\n\n    def check(arguments, wrong=operator.ne, msg=''):\n        \"\"\"Make sure one passes the expected number of arguments\"\"\"\n        if wrong(len(arguments), len(dispatch_args)):\n            raise TypeError('Expected %d arguments, got %d%s' %\n                            (len(dispatch_args), len(arguments), msg))\n\n    def gen_func_dec(func):\n        \"\"\"Decorator turning a function into a generic function\"\"\"\n\n        # first check the dispatch arguments\n        argset = set(getfullargspec(func).args)\n        if not set(dispatch_args) <= argset:\n            raise NameError('Unknown dispatch arguments %s' % dispatch_str)\n\n        typemap = {}\n\n        def vancestors(*types):\n            \"\"\"\n            Get a list of sets of virtual ancestors for the given types\n            \"\"\"\n            check(types)\n            ras = [[] for _ in range(len(dispatch_args))]\n            for types_ in typemap:\n                for t, type_, ra in zip(types, types_, ras):\n                    if issubclass(t, type_) and type_ not in t.mro():\n                        append(type_, ra)\n            return [set(ra) for ra in ras]\n\n        def ancestors(*types):\n            \"\"\"\n            Get a list of virtual MROs, one for each type\n            \"\"\"\n            check(types)\n            lists = []\n            for t, vas in zip(types, vancestors(*types)):\n                n_vas = len(vas)\n                if n_vas > 1:\n                    raise RuntimeError(\n                        'Ambiguous dispatch for %s: %s' % (t, vas))\n                elif n_vas == 1:\n                    va, = vas\n                    mro = type('t', (t, va), {}).mro()[1:]\n                else:\n                    mro = t.mro()\n                lists.append(mro[:-1])  # discard t and object\n            return lists\n\n        def register(*types):\n            \"\"\"\n            Decorator to register an implementation for the given types\n            \"\"\"\n            check(types)\n\n            def dec(f):\n                check(getfullargspec(f).args, operator.lt, ' in ' + f.__name__)\n                typemap[types] = f\n                return f\n            return dec\n\n        def dispatch_info(*types):\n            \"\"\"\n            An utility to introspect the dispatch algorithm\n            \"\"\"\n            check(types)\n            lst = []\n            for anc in itertools.product(*ancestors(*types)):\n                lst.append(tuple(a.__name__ for a in anc))\n            return lst\n\n        def _dispatch(dispatch_args, *args, **kw):\n            types = tuple(type(arg) for arg in dispatch_args)\n            try:  # fast path\n                f = typemap[types]\n            except KeyError:\n                pass\n            else:\n                return f(*args, **kw)\n            combinations = itertools.product(*ancestors(*types))\n            next(combinations)  # the first one has been already tried\n            for types_ in combinations:\n                f = typemap.get(types_)\n                if f is not None:\n                    return f(*args, **kw)\n\n            # else call the default implementation\n            return func(*args, **kw)\n\n        return FunctionMaker.create(\n            func, 'return _f_(%s, %%(shortsignature)s)' % dispatch_str,\n            dict(_f_=_dispatch), register=register, default=func,\n            typemap=typemap, vancestors=vancestors, ancestors=ancestors,\n            dispatch_info=dispatch_info, __wrapped__=func)\n\n    gen_func_dec.__name__ = 'dispatch_on' + dispatch_str\n    return gen_func_dec\n"
  },
  {
    "path": "lib/client/decorator_version",
    "content": "4.4.2\n"
  },
  {
    "path": "lib/client/ipython_genutils/__init__.py",
    "content": "from ._version import __version__, version_info\n"
  },
  {
    "path": "lib/client/ipython_genutils/_version.py",
    "content": "version_info = (0, 2, 0)\n__version__ = '.'.join(map(str, version_info))\n"
  },
  {
    "path": "lib/client/ipython_genutils/encoding.py",
    "content": "# coding: utf-8\n\"\"\"\nUtilities for dealing with text encodings\n\"\"\"\n\n#-----------------------------------------------------------------------------\n#  Copyright (C) 2008-2012  The IPython Development Team\n#\n#  Distributed under the terms of the BSD License.  The full license is in\n#  the file COPYING, distributed as part of this software.\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\nimport sys\nimport locale\nimport warnings\n\n# to deal with the possibility of sys.std* not being a stream at all\ndef get_stream_enc(stream, default=None):\n    \"\"\"Return the given stream's encoding or a default.\n\n    There are cases where ``sys.std*`` might not actually be a stream, so\n    check for the encoding attribute prior to returning it, and return\n    a default if it doesn't exist or evaluates as False. ``default``\n    is None if not provided.\n    \"\"\"\n    if not hasattr(stream, 'encoding') or not stream.encoding:\n        return default\n    else:\n        return stream.encoding\n\n# Less conservative replacement for sys.getdefaultencoding, that will try\n# to match the environment.\n# Defined here as central function, so if we find better choices, we\n# won't need to make changes all over IPython.\ndef getdefaultencoding(prefer_stream=True):\n    \"\"\"Return IPython's guess for the default encoding for bytes as text.\n    \n    If prefer_stream is True (default), asks for stdin.encoding first,\n    to match the calling Terminal, but that is often None for subprocesses.\n    \n    Then fall back on locale.getpreferredencoding(),\n    which should be a sensible platform default (that respects LANG environment),\n    and finally to sys.getdefaultencoding() which is the most conservative option,\n    and usually ASCII on Python 2 or UTF8 on Python 3.\n    \"\"\"\n    enc = None\n    if prefer_stream:\n        enc = get_stream_enc(sys.stdin)\n    if not enc or enc=='ascii':\n        try:\n            # There are reports of getpreferredencoding raising errors\n            # in some cases, which may well be fixed, but let's be conservative here.\n            enc = locale.getpreferredencoding()\n        except Exception:\n            pass\n    enc = enc or sys.getdefaultencoding()\n    # On windows `cp0` can be returned to indicate that there is no code page.\n    # Since cp0 is an invalid encoding return instead cp1252 which is the\n    # Western European default.\n    if enc == 'cp0':\n        warnings.warn(\n            \"Invalid code page cp0 detected - using cp1252 instead.\"\n            \"If cp1252 is incorrect please ensure a valid code page \"\n            \"is defined for the process.\", RuntimeWarning)\n        return 'cp1252'\n    return enc\n\nDEFAULT_ENCODING = getdefaultencoding()\n"
  },
  {
    "path": "lib/client/ipython_genutils/importstring.py",
    "content": "# encoding: utf-8\n\"\"\"\nA simple utility to import something by its string name.\n\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\n\ndef import_item(name):\n    \"\"\"Import and return ``bar`` given the string ``foo.bar``.\n\n    Calling ``bar = import_item(\"foo.bar\")`` is the functional equivalent of\n    executing the code ``from foo import bar``.\n\n    Parameters\n    ----------\n    name : string\n      The fully qualified name of the module/package being imported.\n\n    Returns\n    -------\n    mod : module object\n       The module that was imported.\n    \"\"\"\n    \n    parts = name.rsplit('.', 1)\n    if len(parts) == 2:\n        # called with 'foo.bar....'\n        package, obj = parts\n        module = __import__(package, fromlist=[obj])\n        try:\n            pak = getattr(module, obj)\n        except AttributeError:\n            raise ImportError('No module named %s' % obj)\n        return pak\n    else:\n        # called with un-dotted string\n        return __import__(parts[0])\n"
  },
  {
    "path": "lib/client/ipython_genutils/ipstruct.py",
    "content": "# encoding: utf-8\n\"\"\"A dict subclass that supports attribute style access.\n\nCan probably be replaced by types.SimpleNamespace from Python 3.3\n\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\n__all__ = ['Struct']\n\n\nclass Struct(dict):\n    \"\"\"A dict subclass with attribute style access.\n\n    This dict subclass has a a few extra features:\n\n    * Attribute style access.\n    * Protection of class members (like keys, items) when using attribute\n      style access.\n    * The ability to restrict assignment to only existing keys.\n    * Intelligent merging.\n    * Overloaded operators.\n    \"\"\"\n    _allownew = True\n    def __init__(self, *args, **kw):\n        \"\"\"Initialize with a dictionary, another Struct, or data.\n\n        Parameters\n        ----------\n        args : dict, Struct\n            Initialize with one dict or Struct\n        kw : dict\n            Initialize with key, value pairs.\n\n        Examples\n        --------\n\n        >>> s = Struct(a=10,b=30)\n        >>> s.a\n        10\n        >>> s.b\n        30\n        >>> s2 = Struct(s,c=30)\n        >>> sorted(s2.keys())\n        ['a', 'b', 'c']\n        \"\"\"\n        object.__setattr__(self, '_allownew', True)\n        dict.__init__(self, *args, **kw)\n\n    def __setitem__(self, key, value):\n        \"\"\"Set an item with check for allownew.\n\n        Examples\n        --------\n\n        >>> s = Struct()\n        >>> s['a'] = 10\n        >>> s.allow_new_attr(False)\n        >>> s['a'] = 10\n        >>> s['a']\n        10\n        >>> try:\n        ...     s['b'] = 20\n        ... except KeyError:\n        ...     print('this is not allowed')\n        ...\n        this is not allowed\n        \"\"\"\n        if not self._allownew and key not in self:\n            raise KeyError(\n                \"can't create new attribute %s when allow_new_attr(False)\" % key)\n        dict.__setitem__(self, key, value)\n\n    def __setattr__(self, key, value):\n        \"\"\"Set an attr with protection of class members.\n\n        This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to\n        :exc:`AttributeError`.\n\n        Examples\n        --------\n\n        >>> s = Struct()\n        >>> s.a = 10\n        >>> s.a\n        10\n        >>> try:\n        ...     s.get = 10\n        ... except AttributeError:\n        ...     print(\"you can't set a class member\")\n        ...\n        you can't set a class member\n        \"\"\"\n        # If key is an str it might be a class member or instance var\n        if isinstance(key, str):\n            # I can't simply call hasattr here because it calls getattr, which\n            # calls self.__getattr__, which returns True for keys in\n            # self._data.  But I only want keys in the class and in\n            # self.__dict__\n            if key in self.__dict__ or hasattr(Struct, key):\n                raise AttributeError(\n                    'attr %s is a protected member of class Struct.' % key\n                )\n        try:\n            self.__setitem__(key, value)\n        except KeyError as e:\n            raise AttributeError(e)\n\n    def __getattr__(self, key):\n        \"\"\"Get an attr by calling :meth:`dict.__getitem__`.\n\n        Like :meth:`__setattr__`, this method converts :exc:`KeyError` to\n        :exc:`AttributeError`.\n\n        Examples\n        --------\n\n        >>> s = Struct(a=10)\n        >>> s.a\n        10\n        >>> type(s.get)\n        <... 'builtin_function_or_method'>\n        >>> try:\n        ...     s.b\n        ... except AttributeError:\n        ...     print(\"I don't have that key\")\n        ...\n        I don't have that key\n        \"\"\"\n        try:\n            result = self[key]\n        except KeyError:\n            raise AttributeError(key)\n        else:\n            return result\n\n    def __iadd__(self, other):\n        \"\"\"s += s2 is a shorthand for s.merge(s2).\n\n        Examples\n        --------\n\n        >>> s = Struct(a=10,b=30)\n        >>> s2 = Struct(a=20,c=40)\n        >>> s += s2\n        >>> sorted(s.keys())\n        ['a', 'b', 'c']\n        \"\"\"\n        self.merge(other)\n        return self\n\n    def __add__(self,other):\n        \"\"\"s + s2 -> New Struct made from s.merge(s2).\n\n        Examples\n        --------\n\n        >>> s1 = Struct(a=10,b=30)\n        >>> s2 = Struct(a=20,c=40)\n        >>> s = s1 + s2\n        >>> sorted(s.keys())\n        ['a', 'b', 'c']\n        \"\"\"\n        sout = self.copy()\n        sout.merge(other)\n        return sout\n\n    def __sub__(self,other):\n        \"\"\"s1 - s2 -> remove keys in s2 from s1.\n\n        Examples\n        --------\n\n        >>> s1 = Struct(a=10,b=30)\n        >>> s2 = Struct(a=40)\n        >>> s = s1 - s2\n        >>> s\n        {'b': 30}\n        \"\"\"\n        sout = self.copy()\n        sout -= other\n        return sout\n\n    def __isub__(self,other):\n        \"\"\"Inplace remove keys from self that are in other.\n\n        Examples\n        --------\n\n        >>> s1 = Struct(a=10,b=30)\n        >>> s2 = Struct(a=40)\n        >>> s1 -= s2\n        >>> s1\n        {'b': 30}\n        \"\"\"\n        for k in other.keys():\n            if k in self:\n                del self[k]\n        return self\n\n    def __dict_invert(self, data):\n        \"\"\"Helper function for merge.\n\n        Takes a dictionary whose values are lists and returns a dict with\n        the elements of each list as keys and the original keys as values.\n        \"\"\"\n        outdict = {}\n        for k,lst in data.items():\n            if isinstance(lst, str):\n                lst = lst.split()\n            for entry in lst:\n                outdict[entry] = k\n        return outdict\n\n    def dict(self):\n        return self\n\n    def copy(self):\n        \"\"\"Return a copy as a Struct.\n\n        Examples\n        --------\n\n        >>> s = Struct(a=10,b=30)\n        >>> s2 = s.copy()\n        >>> type(s2) is Struct\n        True\n        \"\"\"\n        return Struct(dict.copy(self))\n\n    def hasattr(self, key):\n        \"\"\"hasattr function available as a method.\n\n        Implemented like has_key.\n\n        Examples\n        --------\n\n        >>> s = Struct(a=10)\n        >>> s.hasattr('a')\n        True\n        >>> s.hasattr('b')\n        False\n        >>> s.hasattr('get')\n        False\n        \"\"\"\n        return key in self\n\n    def allow_new_attr(self, allow = True):\n        \"\"\"Set whether new attributes can be created in this Struct.\n\n        This can be used to catch typos by verifying that the attribute user\n        tries to change already exists in this Struct.\n        \"\"\"\n        object.__setattr__(self, '_allownew', allow)\n\n    def merge(self, __loc_data__=None, __conflict_solve=None, **kw):\n        \"\"\"Merge two Structs with customizable conflict resolution.\n\n        This is similar to :meth:`update`, but much more flexible. First, a\n        dict is made from data+key=value pairs. When merging this dict with\n        the Struct S, the optional dictionary 'conflict' is used to decide\n        what to do.\n\n        If conflict is not given, the default behavior is to preserve any keys\n        with their current value (the opposite of the :meth:`update` method's\n        behavior).\n\n        Parameters\n        ----------\n        __loc_data : dict, Struct\n            The data to merge into self\n        __conflict_solve : dict\n            The conflict policy dict.  The keys are binary functions used to\n            resolve the conflict and the values are lists of strings naming\n            the keys the conflict resolution function applies to.  Instead of\n            a list of strings a space separated string can be used, like\n            'a b c'.\n        kw : dict\n            Additional key, value pairs to merge in\n\n        Notes\n        -----\n\n        The `__conflict_solve` dict is a dictionary of binary functions which will be used to\n        solve key conflicts.  Here is an example::\n\n            __conflict_solve = dict(\n                func1=['a','b','c'],\n                func2=['d','e']\n            )\n\n        In this case, the function :func:`func1` will be used to resolve\n        keys 'a', 'b' and 'c' and the function :func:`func2` will be used for\n        keys 'd' and 'e'.  This could also be written as::\n\n            __conflict_solve = dict(func1='a b c',func2='d e')\n\n        These functions will be called for each key they apply to with the\n        form::\n\n            func1(self['a'], other['a'])\n\n        The return value is used as the final merged value.\n\n        As a convenience, merge() provides five (the most commonly needed)\n        pre-defined policies: preserve, update, add, add_flip and add_s. The\n        easiest explanation is their implementation::\n\n            preserve = lambda old,new: old\n            update   = lambda old,new: new\n            add      = lambda old,new: old + new\n            add_flip = lambda old,new: new + old  # note change of order!\n            add_s    = lambda old,new: old + ' ' + new  # only for str!\n\n        You can use those four words (as strings) as keys instead\n        of defining them as functions, and the merge method will substitute\n        the appropriate functions for you.\n\n        For more complicated conflict resolution policies, you still need to\n        construct your own functions.\n\n        Examples\n        --------\n\n        This show the default policy:\n\n        >>> s = Struct(a=10,b=30)\n        >>> s2 = Struct(a=20,c=40)\n        >>> s.merge(s2)\n        >>> sorted(s.items())\n        [('a', 10), ('b', 30), ('c', 40)]\n\n        Now, show how to specify a conflict dict:\n\n        >>> s = Struct(a=10,b=30)\n        >>> s2 = Struct(a=20,b=40)\n        >>> conflict = {'update':'a','add':'b'}\n        >>> s.merge(s2,conflict)\n        >>> sorted(s.items())\n        [('a', 20), ('b', 70)]\n        \"\"\"\n\n        data_dict = dict(__loc_data__,**kw)\n\n        # policies for conflict resolution: two argument functions which return\n        # the value that will go in the new struct\n        preserve = lambda old,new: old\n        update   = lambda old,new: new\n        add      = lambda old,new: old + new\n        add_flip = lambda old,new: new + old  # note change of order!\n        add_s    = lambda old,new: old + ' ' + new\n\n        # default policy is to keep current keys when there's a conflict\n        conflict_solve = dict.fromkeys(self, preserve)\n\n        # the conflict_solve dictionary is given by the user 'inverted': we\n        # need a name-function mapping, it comes as a function -> names\n        # dict. Make a local copy (b/c we'll make changes), replace user\n        # strings for the three builtin policies and invert it.\n        if __conflict_solve:\n            inv_conflict_solve_user = __conflict_solve.copy()\n            for name, func in [('preserve',preserve), ('update',update),\n                               ('add',add), ('add_flip',add_flip),\n                               ('add_s',add_s)]:\n                if name in inv_conflict_solve_user.keys():\n                    inv_conflict_solve_user[func] = inv_conflict_solve_user[name]\n                    del inv_conflict_solve_user[name]\n            conflict_solve.update(self.__dict_invert(inv_conflict_solve_user))\n        for key in data_dict:\n            if key not in self:\n                self[key] = data_dict[key]\n            else:\n                self[key] = conflict_solve[key](self[key],data_dict[key])\n\n"
  },
  {
    "path": "lib/client/ipython_genutils/path.py",
    "content": "# encoding: utf-8\n\"\"\"\nUtilities for path handling.\n\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport os\nimport sys\nimport errno\nimport shutil\nimport random\n\nfrom . import py3compat\n\n\nfs_encoding = sys.getfilesystemencoding()\n\n\ndef filefind(filename, path_dirs=None):\n    \"\"\"Find a file by looking through a sequence of paths.\n\n    This iterates through a sequence of paths looking for a file and returns\n    the full, absolute path of the first occurence of the file.  If no set of\n    path dirs is given, the filename is tested as is, after running through\n    :func:`expandvars` and :func:`expanduser`.  Thus a simple call::\n\n        filefind('myfile.txt')\n\n    will find the file in the current working dir, but::\n\n        filefind('~/myfile.txt')\n\n    Will find the file in the users home directory.  This function does not\n    automatically try any paths, such as the cwd or the user's home directory.\n\n    Parameters\n    ----------\n    filename : str\n        The filename to look for.\n    path_dirs : str, None or sequence of str\n        The sequence of paths to look for the file in.  If None, the filename\n        need to be absolute or be in the cwd.  If a string, the string is\n        put into a sequence and the searched.  If a sequence, walk through\n        each element and join with ``filename``, calling :func:`expandvars`\n        and :func:`expanduser` before testing for existence.\n\n    Returns\n    -------\n    Raises :exc:`IOError` or returns absolute path to file.\n    \"\"\"\n\n    # If paths are quoted, abspath gets confused, strip them...\n    filename = filename.strip('\"').strip(\"'\")\n    # If the input is an absolute path, just check it exists\n    if os.path.isabs(filename) and os.path.isfile(filename):\n        return filename\n\n    if path_dirs is None:\n        path_dirs = (\"\",)\n    elif isinstance(path_dirs, py3compat.string_types):\n        path_dirs = (path_dirs,)\n\n    for path in path_dirs:\n        if path == '.': path = py3compat.getcwd()\n        testname = expand_path(os.path.join(path, filename))\n        if os.path.isfile(testname):\n            return os.path.abspath(testname)\n\n    raise IOError(\"File %r does not exist in any of the search paths: %r\" %\n                  (filename, path_dirs) )\n\n\ndef expand_path(s):\n    \"\"\"Expand $VARS and ~names in a string, like a shell\n\n    :Examples:\n\n       In [2]: os.environ['FOO']='test'\n\n       In [3]: expand_path('variable FOO is $FOO')\n       Out[3]: 'variable FOO is test'\n    \"\"\"\n    # This is a pretty subtle hack. When expand user is given a UNC path\n    # on Windows (\\\\server\\share$\\%username%), os.path.expandvars, removes\n    # the $ to get (\\\\server\\share\\%username%). I think it considered $\n    # alone an empty var. But, we need the $ to remains there (it indicates\n    # a hidden share).\n    if os.name=='nt':\n        s = s.replace('$\\\\', 'IPYTHON_TEMP')\n    s = os.path.expandvars(os.path.expanduser(s))\n    if os.name=='nt':\n        s = s.replace('IPYTHON_TEMP', '$\\\\')\n    return s\n\n\ntry:\n    ENOLINK = errno.ENOLINK\nexcept AttributeError:\n    ENOLINK = 1998\n\ndef link(src, dst):\n    \"\"\"Hard links ``src`` to ``dst``, returning 0 or errno.\n\n    Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't\n    supported by the operating system.\n    \"\"\"\n\n    if not hasattr(os, \"link\"):\n        return ENOLINK\n    link_errno = 0\n    try:\n        os.link(src, dst)\n    except OSError as e:\n        link_errno = e.errno\n    return link_errno\n\n\ndef link_or_copy(src, dst):\n    \"\"\"Attempts to hardlink ``src`` to ``dst``, copying if the link fails.\n\n    Attempts to maintain the semantics of ``shutil.copy``.\n\n    Because ``os.link`` does not overwrite files, a unique temporary file\n    will be used if the target already exists, then that file will be moved\n    into place.\n    \"\"\"\n\n    if os.path.isdir(dst):\n        dst = os.path.join(dst, os.path.basename(src))\n\n    link_errno = link(src, dst)\n    if link_errno == errno.EEXIST:\n        if os.stat(src).st_ino == os.stat(dst).st_ino:\n            # dst is already a hard link to the correct file, so we don't need\n            # to do anything else. If we try to link and rename the file\n            # anyway, we get duplicate files - see http://bugs.python.org/issue21876\n            return\n\n        new_dst = dst + \"-temp-%04X\" %(random.randint(1, 16**4), )\n        try:\n            link_or_copy(src, new_dst)\n        except:\n            try:\n                os.remove(new_dst)\n            except OSError:\n                pass\n            raise\n        os.rename(new_dst, dst)\n    elif link_errno != 0:\n        # Either link isn't supported, or the filesystem doesn't support\n        # linking, or 'src' and 'dst' are on different filesystems.\n        shutil.copy(src, dst)\n\n\ndef ensure_dir_exists(path, mode=0o755):\n    \"\"\"ensure that a directory exists\n    \n    If it doesn't exist, try to create it and protect against a race condition\n    if another process is doing the same.\n    \n    The default permissions are 755, which differ from os.makedirs default of 777.\n    \"\"\"\n    if not os.path.exists(path):\n        try:\n            os.makedirs(path, mode=mode)\n        except OSError as e:\n            if e.errno != errno.EEXIST:\n                raise\n    elif not os.path.isdir(path):\n        raise IOError(\"%r exists but is not a directory\" % path)\n"
  },
  {
    "path": "lib/client/ipython_genutils/py3compat.py",
    "content": "# coding: utf-8\n\"\"\"Compatibility tricks for Python 3. Mainly to do with unicode.\"\"\"\nimport functools\nimport os\nimport sys\nimport re\nimport shutil\nimport types\n\nfrom .encoding import DEFAULT_ENCODING\n\ndef no_code(x, encoding=None):\n    return x\n\ndef decode(s, encoding=None):\n    encoding = encoding or DEFAULT_ENCODING\n    return s.decode(encoding, \"replace\")\n\ndef encode(u, encoding=None):\n    encoding = encoding or DEFAULT_ENCODING\n    return u.encode(encoding, \"replace\")\n\n\ndef cast_unicode(s, encoding=None):\n    if isinstance(s, bytes):\n        return decode(s, encoding)\n    return s\n\ndef cast_bytes(s, encoding=None):\n    if not isinstance(s, bytes):\n        return encode(s, encoding)\n    return s\n\ndef buffer_to_bytes(buf):\n    \"\"\"Cast a buffer or memoryview object to bytes\"\"\"\n    if isinstance(buf, memoryview):\n        return buf.tobytes()\n    if not isinstance(buf, bytes):\n        return bytes(buf)\n    return buf\n\ndef _modify_str_or_docstring(str_change_func):\n    @functools.wraps(str_change_func)\n    def wrapper(func_or_str):\n        if isinstance(func_or_str, string_types):\n            func = None\n            doc = func_or_str\n        else:\n            func = func_or_str\n            doc = func.__doc__\n        \n        doc = str_change_func(doc)\n        \n        if func:\n            func.__doc__ = doc\n            return func\n        return doc\n    return wrapper\n\ndef safe_unicode(e):\n    \"\"\"unicode(e) with various fallbacks. Used for exceptions, which may not be\n    safe to call unicode() on.\n    \"\"\"\n    try:\n        return unicode_type(e)\n    except UnicodeError:\n        pass\n\n    try:\n        return str_to_unicode(str(e))\n    except UnicodeError:\n        pass\n\n    try:\n        return str_to_unicode(repr(e))\n    except UnicodeError:\n        pass\n\n    return u'Unrecoverably corrupt evalue'\n\n# shutil.which from Python 3.4\ndef _shutil_which(cmd, mode=os.F_OK | os.X_OK, path=None):\n    \"\"\"Given a command, mode, and a PATH string, return the path which\n    conforms to the given mode on the PATH, or None if there is no such\n    file.\n\n    `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result\n    of os.environ.get(\"PATH\"), or can be overridden with a custom search\n    path.\n    \n    This is a backport of shutil.which from Python 3.4\n    \"\"\"\n    # Check that a given file can be accessed with the correct mode.\n    # Additionally check that `file` is not a directory, as on Windows\n    # directories pass the os.access check.\n    def _access_check(fn, mode):\n        return (os.path.exists(fn) and os.access(fn, mode)\n                and not os.path.isdir(fn))\n\n    # If we're given a path with a directory part, look it up directly rather\n    # than referring to PATH directories. This includes checking relative to the\n    # current directory, e.g. ./script\n    if os.path.dirname(cmd):\n        if _access_check(cmd, mode):\n            return cmd\n        return None\n\n    if path is None:\n        path = os.environ.get(\"PATH\", os.defpath)\n    if not path:\n        return None\n    path = path.split(os.pathsep)\n\n    if sys.platform == \"win32\":\n        # The current directory takes precedence on Windows.\n        if not os.curdir in path:\n            path.insert(0, os.curdir)\n\n        # PATHEXT is necessary to check on Windows.\n        pathext = os.environ.get(\"PATHEXT\", \"\").split(os.pathsep)\n        # See if the given file matches any of the expected path extensions.\n        # This will allow us to short circuit when given \"python.exe\".\n        # If it does match, only test that one, otherwise we have to try\n        # others.\n        if any(cmd.lower().endswith(ext.lower()) for ext in pathext):\n            files = [cmd]\n        else:\n            files = [cmd + ext for ext in pathext]\n    else:\n        # On other platforms you don't have things like PATHEXT to tell you\n        # what file suffixes are executable, so just pass on cmd as-is.\n        files = [cmd]\n\n    seen = set()\n    for dir in path:\n        normdir = os.path.normcase(dir)\n        if not normdir in seen:\n            seen.add(normdir)\n            for thefile in files:\n                name = os.path.join(dir, thefile)\n                if _access_check(name, mode):\n                    return name\n    return None\n\nimport platform\nif sys.version_info[0] >= 3 or platform.python_implementation() == 'IronPython':\n    str_to_unicode = no_code\n    unicode_to_str = no_code\n    str_to_bytes = encode\n    bytes_to_str = decode\n    cast_bytes_py2 = no_code\n    cast_unicode_py2 = no_code\n    buffer_to_bytes_py2 = no_code\n    \n    string_types = (str,)\n    unicode_type = str\nelse:\n    str_to_unicode = decode\n    unicode_to_str = encode\n    str_to_bytes = no_code\n    bytes_to_str = no_code\n    cast_bytes_py2 = cast_bytes\n    cast_unicode_py2 = cast_unicode\n    buffer_to_bytes_py2 = buffer_to_bytes\n    \n    string_types = (str, unicode)\n    unicode_type = unicode\n\nif sys.version_info[0] >= 3:\n    PY3 = True\n    \n    # keep reference to builtin_mod because the kernel overrides that value\n    # to forward requests to a frontend.\n    def input(prompt=''):\n        return builtin_mod.input(prompt)\n    \n    builtin_mod_name = \"builtins\"\n    import builtins as builtin_mod\n        \n    which = shutil.which\n    \n    def isidentifier(s, dotted=False):\n        if dotted:\n            return all(isidentifier(a) for a in s.split(\".\"))\n        return s.isidentifier()\n\n    xrange = range\n    def iteritems(d): return iter(d.items())\n    def itervalues(d): return iter(d.values())\n    getcwd = os.getcwd\n    \n    MethodType = types.MethodType\n\n    def execfile(fname, glob, loc=None, compiler=None):\n        loc = loc if (loc is not None) else glob\n        with open(fname, 'rb') as f:\n            compiler = compiler or compile\n            exec(compiler(f.read(), fname, 'exec'), glob, loc)\n    \n    # Refactor print statements in doctests.\n    _print_statement_re = re.compile(r\"\\bprint (?P<expr>.*)$\", re.MULTILINE)\n    def _print_statement_sub(match):\n        expr = match.groups('expr')\n        return \"print(%s)\" % expr\n    \n    @_modify_str_or_docstring\n    def doctest_refactor_print(doc):\n        \"\"\"Refactor 'print x' statements in a doctest to print(x) style. 2to3\n        unfortunately doesn't pick up on our doctests.\n        \n        Can accept a string or a function, so it can be used as a decorator.\"\"\"\n        return _print_statement_re.sub(_print_statement_sub, doc)\n    \n    # Abstract u'abc' syntax:\n    @_modify_str_or_docstring\n    def u_format(s):\n        \"\"\"\"{u}'abc'\" --> \"'abc'\" (Python 3)\n        \n        Accepts a string or a function, so it can be used as a decorator.\"\"\"\n        return s.format(u='')\n    \n    def get_closure(f):\n        \"\"\"Get a function's closure attribute\"\"\"\n        return f.__closure__\n\nelse:\n    PY3 = False\n    \n    # keep reference to builtin_mod because the kernel overrides that value\n    # to forward requests to a frontend.\n    def input(prompt=''):\n        return builtin_mod.raw_input(prompt)\n    \n    builtin_mod_name = \"__builtin__\"\n    import __builtin__ as builtin_mod\n    \n    import re\n    _name_re = re.compile(r\"[a-zA-Z_][a-zA-Z0-9_]*$\")\n    def isidentifier(s, dotted=False):\n        if dotted:\n            return all(isidentifier(a) for a in s.split(\".\"))\n        return bool(_name_re.match(s))\n    \n    xrange = xrange\n    def iteritems(d): return d.iteritems()\n    def itervalues(d): return d.itervalues()\n    getcwd = os.getcwdu\n\n    def MethodType(func, instance):\n        return types.MethodType(func, instance, type(instance))\n    \n    def doctest_refactor_print(func_or_str):\n        return func_or_str\n\n    def get_closure(f):\n        \"\"\"Get a function's closure attribute\"\"\"\n        return f.func_closure\n    \n    which = _shutil_which\n\n    # Abstract u'abc' syntax:\n    @_modify_str_or_docstring\n    def u_format(s):\n        \"\"\"\"{u}'abc'\" --> \"u'abc'\" (Python 2)\n        \n        Accepts a string or a function, so it can be used as a decorator.\"\"\"\n        return s.format(u='u')\n\n    if sys.platform == 'win32':\n        def execfile(fname, glob=None, loc=None, compiler=None):\n            loc = loc if (loc is not None) else glob\n            scripttext = builtin_mod.open(fname).read()+ '\\n'\n            # compile converts unicode filename to str assuming\n            # ascii. Let's do the conversion before calling compile\n            if isinstance(fname, unicode):\n                filename = unicode_to_str(fname)\n            else:\n                filename = fname\n            compiler = compiler or compile\n            exec(compiler(scripttext, filename, 'exec'), glob, loc)\n\n    else:\n        def execfile(fname, glob=None, loc=None, compiler=None):\n            if isinstance(fname, unicode):\n                filename = fname.encode(sys.getfilesystemencoding())\n            else:\n                filename = fname\n            where = [ns for ns in [glob, loc] if ns is not None]\n            if compiler is None:\n                builtin_mod.execfile(filename, *where)\n            else:\n                scripttext = builtin_mod.open(fname).read().rstrip() + '\\n'\n                exec(compiler(scripttext, filename, 'exec'), glob, loc)\n\n\ndef annotate(**kwargs):\n    \"\"\"Python 3 compatible function annotation for Python 2.\"\"\"\n    if not kwargs:\n        raise ValueError('annotations must be provided as keyword arguments')\n    def dec(f):\n        if hasattr(f, '__annotations__'):\n            for k, v in kwargs.items():\n                f.__annotations__[k] = v\n        else:\n            f.__annotations__ = kwargs\n        return f\n    return dec\n\n\n# Parts below taken from six:\n# Copyright (c) 2010-2013 Benjamin Peterson\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in all\n# copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n\ndef with_metaclass(meta, *bases):\n    \"\"\"Create a base class with a metaclass.\"\"\"\n    return meta(\"_NewBase\", bases, {})\n"
  },
  {
    "path": "lib/client/ipython_genutils/tempdir.py",
    "content": "\"\"\"TemporaryDirectory class, copied from Python 3\n\nThis is copied from the stdlib and will be standard in Python 3.2 and onwards.\n\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function\n\nimport os as _os\nimport warnings as _warnings\nimport sys as _sys\n\n# This code should only be used in Python versions < 3.2, since after that we\n# can rely on the stdlib itself.\ntry:\n    from tempfile import TemporaryDirectory\n\nexcept ImportError:\n    from tempfile import mkdtemp, template\n\n    class TemporaryDirectory(object):\n        \"\"\"Create and return a temporary directory.  This has the same\n        behavior as mkdtemp but can be used as a context manager.  For\n        example:\n\n            with TemporaryDirectory() as tmpdir:\n                ...\n\n        Upon exiting the context, the directory and everthing contained\n        in it are removed.\n        \"\"\"\n\n        def __init__(self, suffix=\"\", prefix=template, dir=None):\n            self.name = mkdtemp(suffix, prefix, dir)\n            self._closed = False\n\n        def __enter__(self):\n            return self.name\n\n        def cleanup(self, _warn=False):\n            if self.name and not self._closed:\n                try:\n                    self._rmtree(self.name)\n                except (TypeError, AttributeError) as ex:\n                    # Issue #10188: Emit a warning on stderr\n                    # if the directory could not be cleaned\n                    # up due to missing globals\n                    if \"None\" not in str(ex):\n                        raise\n                    print(\"ERROR: {!r} while cleaning up {!r}\".format(ex, self,),\n                          file=_sys.stderr)\n                    return\n                self._closed = True\n                if _warn:\n                    self._warn(\"Implicitly cleaning up {!r}\".format(self),\n                               Warning)\n\n        def __exit__(self, exc, value, tb):\n            self.cleanup()\n\n        def __del__(self):\n            # Issue a ResourceWarning if implicit cleanup needed\n            self.cleanup(_warn=True)\n\n\n        # XXX (ncoghlan): The following code attempts to make\n        # this class tolerant of the module nulling out process\n        # that happens during CPython interpreter shutdown\n        # Alas, it doesn't actually manage it. See issue #10188\n        _listdir = staticmethod(_os.listdir)\n        _path_join = staticmethod(_os.path.join)\n        _isdir = staticmethod(_os.path.isdir)\n        _remove = staticmethod(_os.remove)\n        _rmdir = staticmethod(_os.rmdir)\n        _os_error = _os.error\n        _warn = _warnings.warn\n\n        def _rmtree(self, path):\n            # Essentially a stripped down version of shutil.rmtree.  We can't\n            # use globals because they may be None'ed out at shutdown.\n            for name in self._listdir(path):\n                fullname = self._path_join(path, name)\n                try:\n                    isdir = self._isdir(fullname)\n                except self._os_error:\n                    isdir = False\n                if isdir:\n                    self._rmtree(fullname)\n                else:\n                    try:\n                        self._remove(fullname)\n                    except self._os_error:\n                        pass\n            try:\n                self._rmdir(path)\n            except self._os_error:\n                pass\n\n# extra temp-dir-related context managers\n\nclass NamedFileInTemporaryDirectory(object):\n\n    def __init__(self, filename, mode='w+b', bufsize=-1, **kwds):\n        \"\"\"\n        Open a file named `filename` in a temporary directory.\n\n        This context manager is preferred over `NamedTemporaryFile` in\n        stdlib `tempfile` when one needs to reopen the file.\n\n        Arguments `mode` and `bufsize` are passed to `open`.\n        Rest of the arguments are passed to `TemporaryDirectory`.\n\n        \"\"\"\n        self._tmpdir = TemporaryDirectory(**kwds)\n        path = _os.path.join(self._tmpdir.name, filename)\n        self.file = open(path, mode, bufsize)\n\n    def cleanup(self):\n        self.file.close()\n        self._tmpdir.cleanup()\n\n    __del__ = cleanup\n\n    def __enter__(self):\n        return self.file\n\n    def __exit__(self, type, value, traceback):\n        self.cleanup()\n\n\nclass TemporaryWorkingDirectory(TemporaryDirectory):\n    \"\"\"\n    Creates a temporary directory and sets the cwd to that directory.\n    Automatically reverts to previous cwd upon cleanup.\n    Usage example:\n\n        with TemporaryWorkingDirectory() as tmpdir:\n            ...\n    \"\"\"\n    def __enter__(self):\n        self.old_wd = _os.getcwd()\n        _os.chdir(self.name)\n        return super(TemporaryWorkingDirectory, self).__enter__()\n\n    def __exit__(self, exc, value, tb):\n        _os.chdir(self.old_wd)\n        return super(TemporaryWorkingDirectory, self).__exit__(exc, value, tb)\n\n"
  },
  {
    "path": "lib/client/ipython_genutils/text.py",
    "content": "# encoding: utf-8\n\"\"\"\nUtilities for working with strings and text.\n\nInheritance diagram:\n\n.. inheritance-diagram:: IPython.utils.text\n   :parts: 3\n\"\"\"\n\nimport os\nimport re\nimport sys\nimport textwrap\nfrom string import Formatter\n\n# datetime.strftime date format for ipython\nif sys.platform == 'win32':\n    date_format = \"%B %d, %Y\"\nelse:\n    date_format = \"%B %-d, %Y\"\n\n\ndef indent(instr,nspaces=4, ntabs=0, flatten=False):\n    \"\"\"Indent a string a given number of spaces or tabstops.\n\n    indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.\n\n    Parameters\n    ----------\n\n    instr : basestring\n        The string to be indented.\n    nspaces : int (default: 4)\n        The number of spaces to be indented.\n    ntabs : int (default: 0)\n        The number of tabs to be indented.\n    flatten : bool (default: False)\n        Whether to scrub existing indentation.  If True, all lines will be\n        aligned to the same indentation.  If False, existing indentation will\n        be strictly increased.\n\n    Returns\n    -------\n\n    str|unicode : string indented by ntabs and nspaces.\n\n    \"\"\"\n    if instr is None:\n        return\n    ind = '\\t'*ntabs+' '*nspaces\n    if flatten:\n        pat = re.compile(r'^\\s*', re.MULTILINE)\n    else:\n        pat = re.compile(r'^', re.MULTILINE)\n    outstr = re.sub(pat, ind, instr)\n    if outstr.endswith(os.linesep+ind):\n        return outstr[:-len(ind)]\n    else:\n        return outstr\n\n\ndef dedent(text):\n    \"\"\"Equivalent of textwrap.dedent that ignores unindented first line.\n\n    This means it will still dedent strings like:\n    '''foo\n    is a bar\n    '''\n\n    For use in wrap_paragraphs.\n    \"\"\"\n\n    if text.startswith('\\n'):\n        # text starts with blank line, don't ignore the first line\n        return textwrap.dedent(text)\n\n    # split first line\n    splits = text.split('\\n',1)\n    if len(splits) == 1:\n        # only one line\n        return textwrap.dedent(text)\n\n    first, rest = splits\n    # dedent everything but the first line\n    rest = textwrap.dedent(rest)\n    return '\\n'.join([first, rest])\n\n\ndef wrap_paragraphs(text, ncols=80):\n    \"\"\"Wrap multiple paragraphs to fit a specified width.\n\n    This is equivalent to textwrap.wrap, but with support for multiple\n    paragraphs, as separated by empty lines.\n\n    Returns\n    -------\n\n    list of complete paragraphs, wrapped to fill `ncols` columns.\n    \"\"\"\n    paragraph_re = re.compile(r'\\n(\\s*\\n)+', re.MULTILINE)\n    text = dedent(text).strip()\n    paragraphs = paragraph_re.split(text)[::2] # every other entry is space\n    out_ps = []\n    indent_re = re.compile(r'\\n\\s+', re.MULTILINE)\n    for p in paragraphs:\n        # presume indentation that survives dedent is meaningful formatting,\n        # so don't fill unless text is flush.\n        if indent_re.search(p) is None:\n            # wrap paragraph\n            p = textwrap.fill(p, ncols)\n        out_ps.append(p)\n    return out_ps\n\n\ndef strip_ansi(source):\n    \"\"\"\n    Remove ansi escape codes from text.\n    \n    Parameters\n    ----------\n    source : str\n        Source to remove the ansi from\n    \"\"\"\n    return re.sub(r'\\033\\[(\\d|;)+?m', '', source)\n\n\n#-----------------------------------------------------------------------------\n# Utils to columnize a list of string\n#-----------------------------------------------------------------------------\n\ndef _chunks(l, n):\n    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n    for i in range(0, len(l), n):\n        yield l[i:i+n]\n\n\ndef _find_optimal(rlist , separator_size=2 , displaywidth=80):\n    \"\"\"Calculate optimal info to columnize a list of string\"\"\"\n    for nrow in range(1, len(rlist)+1) :\n        chk = list(map(max,_chunks(rlist, nrow)))\n        sumlength = sum(chk)\n        ncols = len(chk)\n        if sumlength+separator_size*(ncols-1) <= displaywidth :\n            break;\n    return {'columns_numbers' : ncols,\n            'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0,\n            'rows_numbers' : nrow,\n            'columns_width' : chk\n           }\n\n\ndef _get_or_default(mylist, i, default=None):\n    \"\"\"return list item number, or default if don't exist\"\"\"\n    if i >= len(mylist):\n        return default\n    else :\n        return mylist[i]\n\n\ndef compute_item_matrix(items, empty=None, *args, **kwargs) :\n    \"\"\"Returns a nested list, and info to columnize items\n\n    Parameters\n    ----------\n\n    items\n        list of strings to columize\n    empty : (default None)\n        default value to fill list if needed\n    separator_size : int (default=2)\n        How much caracters will be used as a separation between each columns.\n    displaywidth : int (default=80)\n        The width of the area onto wich the columns should enter\n\n    Returns\n    -------\n\n    strings_matrix\n\n        nested list of string, the outer most list contains as many list as\n        rows, the innermost lists have each as many element as colums. If the\n        total number of elements in `items` does not equal the product of\n        rows*columns, the last element of some lists are filled with `None`.\n\n    dict_info\n        some info to make columnize easier:\n\n        columns_numbers\n          number of columns\n        rows_numbers\n          number of rows\n        columns_width\n          list of with of each columns\n        optimal_separator_width\n          best separator width between columns\n\n    Examples\n    --------\n    ::\n\n        In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']\n           ...: compute_item_matrix(l,displaywidth=12)\n        Out[1]:\n            ([['aaa', 'f', 'k'],\n            ['b', 'g', 'l'],\n            ['cc', 'h', None],\n            ['d', 'i', None],\n            ['eeeee', 'j', None]],\n            {'columns_numbers': 3,\n            'columns_width': [5, 1, 1],\n            'optimal_separator_width': 2,\n            'rows_numbers': 5})\n    \"\"\"\n    info = _find_optimal(list(map(len, items)), *args, **kwargs)\n    nrow, ncol = info['rows_numbers'], info['columns_numbers']\n    return ([[ _get_or_default(items, c*nrow+i, default=empty) for c in range(ncol) ] for i in range(nrow) ], info)\n\n\ndef columnize(items, separator='  ', displaywidth=80):\n    \"\"\" Transform a list of strings into a single string with columns.\n\n    Parameters\n    ----------\n    items : sequence of strings\n        The strings to process.\n\n    separator : str, optional [default is two spaces]\n        The string that separates columns.\n\n    displaywidth : int, optional [default is 80]\n        Width of the display in number of characters.\n\n    Returns\n    -------\n    The formatted string.\n    \"\"\"\n    if not items :\n        return '\\n'\n    matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth)\n    fmatrix = [filter(None, x) for x in matrix]\n    sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])])\n    return '\\n'.join(map(sjoin, fmatrix))+'\\n'\n\n"
  },
  {
    "path": "lib/client/jupyter_client/__init__.py",
    "content": "\"\"\"Client-side implementations of the Jupyter protocol\"\"\"\n\nfrom ._version import version_info, __version__, protocol_version_info, protocol_version\nfrom .connect import *\nfrom .launcher import *\nfrom .client import KernelClient\nfrom .manager import KernelManager, run_kernel\nfrom .blocking import BlockingKernelClient\nfrom .multikernelmanager import MultiKernelManager\n"
  },
  {
    "path": "lib/client/jupyter_client/_version.py",
    "content": "version_info = (5, 2, 4)\n__version__ = '.'.join(map(str, version_info))\n\nprotocol_version_info = (5, 3)\nprotocol_version = \"%i.%i\" % protocol_version_info\n"
  },
  {
    "path": "lib/client/jupyter_client/adapter.py",
    "content": "\"\"\"Adapters for Jupyter msg spec versions.\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport re\nimport json\n\nfrom jupyter_client import protocol_version_info\n\ndef code_to_line(code, cursor_pos):\n    \"\"\"Turn a multiline code block and cursor position into a single line\n    and new cursor position.\n\n    For adapting ``complete_`` and ``object_info_request``.\n    \"\"\"\n    if not code:\n        return \"\", 0\n    for line in code.splitlines(True):\n        n = len(line)\n        if cursor_pos > n:\n            cursor_pos -= n\n        else:\n            break\n    return line, cursor_pos\n\n\n_match_bracket = re.compile(r'\\([^\\(\\)]+\\)', re.UNICODE)\n_end_bracket = re.compile(r'\\([^\\(]*$', re.UNICODE)\n_identifier = re.compile(r'[a-z_][0-9a-z._]*', re.I|re.UNICODE)\n\ndef extract_oname_v4(code, cursor_pos):\n    \"\"\"Reimplement token-finding logic from IPython 2.x javascript\n    \n    for adapting object_info_request from v5 to v4\n    \"\"\"\n    \n    line, _ = code_to_line(code, cursor_pos)\n    \n    oldline = line\n    line = _match_bracket.sub(u'', line)\n    while oldline != line:\n        oldline = line\n        line = _match_bracket.sub(u'', line)\n\n    # remove everything after last open bracket\n    line = _end_bracket.sub('', line)\n    matches = _identifier.findall(line)\n    if matches:\n        return matches[-1]\n    else:\n        return ''\n\n\nclass Adapter(object):\n    \"\"\"Base class for adapting messages\n\n    Override message_type(msg) methods to create adapters.\n    \"\"\"\n\n    msg_type_map = {}\n\n    def update_header(self, msg):\n        return msg\n\n    def update_metadata(self, msg):\n        return msg\n\n    def update_msg_type(self, msg):\n        header = msg['header']\n        msg_type = header['msg_type']\n        if msg_type in self.msg_type_map:\n            msg['msg_type'] = header['msg_type'] = self.msg_type_map[msg_type]\n        return msg\n\n    def handle_reply_status_error(self, msg):\n        \"\"\"This will be called *instead of* the regular handler\n\n        on any reply with status != ok\n        \"\"\"\n        return msg\n\n    def __call__(self, msg):\n        msg = self.update_header(msg)\n        msg = self.update_metadata(msg)\n        msg = self.update_msg_type(msg)\n        header = msg['header']\n\n        handler = getattr(self, header['msg_type'], None)\n        if handler is None:\n            return msg\n\n        # handle status=error replies separately (no change, at present)\n        if msg['content'].get('status', None) in {'error', 'aborted'}:\n            return self.handle_reply_status_error(msg)\n        return handler(msg)\n\ndef _version_str_to_list(version):\n    \"\"\"convert a version string to a list of ints\n\n    non-int segments are excluded\n    \"\"\"\n    v = []\n    for part in version.split('.'):\n        try:\n            v.append(int(part))\n        except ValueError:\n            pass\n    return v\n\nclass V5toV4(Adapter):\n    \"\"\"Adapt msg protocol v5 to v4\"\"\"\n\n    version = '4.1'\n\n    msg_type_map = {\n        'execute_result' : 'pyout',\n        'execute_input' : 'pyin',\n        'error' : 'pyerr',\n        'inspect_request' : 'object_info_request',\n        'inspect_reply' : 'object_info_reply',\n    }\n\n    def update_header(self, msg):\n        msg['header'].pop('version', None)\n        msg['parent_header'].pop('version', None)\n        return msg\n\n    # shell channel\n\n    def kernel_info_reply(self, msg):\n        v4c = {}\n        content = msg['content']\n        for key in ('language_version', 'protocol_version'):\n            if key in content:\n                v4c[key] = _version_str_to_list(content[key])\n        if content.get('implementation', '') == 'ipython' \\\n            and 'implementation_version' in content:\n            v4c['ipython_version'] = _version_str_to_list(content['implementation_version'])\n        language_info = content.get('language_info', {})\n        language = language_info.get('name', '')\n        v4c.setdefault('language', language)\n        if 'version' in language_info:\n            v4c.setdefault('language_version', _version_str_to_list(language_info['version']))\n        msg['content'] = v4c\n        return msg\n\n    def execute_request(self, msg):\n        content = msg['content']\n        content.setdefault('user_variables', [])\n        return msg\n\n    def execute_reply(self, msg):\n        content = msg['content']\n        content.setdefault('user_variables', {})\n        # TODO: handle payloads\n        return msg\n\n    def complete_request(self, msg):\n        content = msg['content']\n        code = content['code']\n        cursor_pos = content['cursor_pos']\n        line, cursor_pos = code_to_line(code, cursor_pos)\n\n        new_content = msg['content'] = {}\n        new_content['text'] = ''\n        new_content['line'] = line\n        new_content['block'] = None\n        new_content['cursor_pos'] = cursor_pos\n        return msg\n\n    def complete_reply(self, msg):\n        content = msg['content']\n        cursor_start = content.pop('cursor_start')\n        cursor_end = content.pop('cursor_end')\n        match_len = cursor_end - cursor_start\n        content['matched_text'] = content['matches'][0][:match_len]\n        content.pop('metadata', None)\n        return msg\n\n    def object_info_request(self, msg):\n        content = msg['content']\n        code = content['code']\n        cursor_pos = content['cursor_pos']\n        line, _ = code_to_line(code, cursor_pos)\n\n        new_content = msg['content'] = {}\n        new_content['oname'] = extract_oname_v4(code, cursor_pos)\n        new_content['detail_level'] = content['detail_level']\n        return msg\n\n    def object_info_reply(self, msg):\n        \"\"\"inspect_reply can't be easily backward compatible\"\"\"\n        msg['content'] = {'found' : False, 'oname' : 'unknown'}\n        return msg\n\n    # iopub channel\n\n    def stream(self, msg):\n        content = msg['content']\n        content['data'] = content.pop('text')\n        return msg\n\n    def display_data(self, msg):\n        content = msg['content']\n        content.setdefault(\"source\", \"display\")\n        data = content['data']\n        if 'application/json' in data:\n            try:\n                data['application/json'] = json.dumps(data['application/json'])\n            except Exception:\n                # warn?\n                pass\n        return msg\n\n    # stdin channel\n\n    def input_request(self, msg):\n        msg['content'].pop('password', None)\n        return msg\n\n\nclass V4toV5(Adapter):\n    \"\"\"Convert msg spec V4 to V5\"\"\"\n    version = '5.0'\n\n    # invert message renames above\n    msg_type_map = {v:k for k,v in V5toV4.msg_type_map.items()}\n\n    def update_header(self, msg):\n        msg['header']['version'] = self.version\n        if msg['parent_header']:\n            msg['parent_header']['version'] = self.version\n        return msg\n\n    # shell channel\n\n    def kernel_info_reply(self, msg):\n        content = msg['content']\n        for key in ('protocol_version', 'ipython_version'):\n            if key in content:\n                content[key] = '.'.join(map(str, content[key]))\n\n        content.setdefault('protocol_version', '4.1')\n\n        if content['language'].startswith('python') and 'ipython_version' in content:\n            content['implementation'] = 'ipython'\n            content['implementation_version'] = content.pop('ipython_version')\n\n        language = content.pop('language')\n        language_info = content.setdefault('language_info', {})\n        language_info.setdefault('name', language)\n        if 'language_version' in content:\n            language_version = '.'.join(map(str, content.pop('language_version')))\n            language_info.setdefault('version', language_version)\n\n        content['banner'] = ''\n        return msg\n\n    def execute_request(self, msg):\n        content = msg['content']\n        user_variables = content.pop('user_variables', [])\n        user_expressions = content.setdefault('user_expressions', {})\n        for v in user_variables:\n            user_expressions[v] = v\n        return msg\n\n    def execute_reply(self, msg):\n        content = msg['content']\n        user_expressions = content.setdefault('user_expressions', {})\n        user_variables = content.pop('user_variables', {})\n        if user_variables:\n            user_expressions.update(user_variables)\n\n        # Pager payloads became a mime bundle\n        for payload in content.get('payload', []):\n            if payload.get('source', None) == 'page' and ('text' in payload):\n                if 'data' not in payload:\n                    payload['data'] = {}\n                payload['data']['text/plain'] = payload.pop('text')\n\n        return msg\n\n    def complete_request(self, msg):\n        old_content = msg['content']\n\n        new_content = msg['content'] = {}\n        new_content['code'] = old_content['line']\n        new_content['cursor_pos'] = old_content['cursor_pos']\n        return msg\n\n    def complete_reply(self, msg):\n        # complete_reply needs more context than we have to get cursor_start and end.\n        # use special end=null to indicate current cursor position and negative offset\n        # for start relative to the cursor.\n        # start=None indicates that start == end (accounts for no -0).\n        content = msg['content']\n        new_content = msg['content'] = {'status' : 'ok'}\n        new_content['matches'] = content['matches']\n        if content['matched_text']:\n            new_content['cursor_start'] = -len(content['matched_text'])\n        else:\n            # no -0, use None to indicate that start == end\n            new_content['cursor_start'] = None\n        new_content['cursor_end'] = None\n        new_content['metadata'] = {}\n        return msg\n\n    def inspect_request(self, msg):\n        content = msg['content']\n        name = content['oname']\n\n        new_content = msg['content'] = {}\n        new_content['code'] = name\n        new_content['cursor_pos'] = len(name)\n        new_content['detail_level'] = content['detail_level']\n        return msg\n\n    def inspect_reply(self, msg):\n        \"\"\"inspect_reply can't be easily backward compatible\"\"\"\n        content = msg['content']\n        new_content = msg['content'] = {'status' : 'ok'}\n        found = new_content['found'] = content['found']\n        new_content['data'] = data = {}\n        new_content['metadata'] = {}\n        if found:\n            lines = []\n            for key in ('call_def', 'init_definition', 'definition'):\n                if content.get(key, False):\n                    lines.append(content[key])\n                    break\n            for key in ('call_docstring', 'init_docstring', 'docstring'):\n                if content.get(key, False):\n                    lines.append(content[key])\n                    break\n            if not lines:\n                lines.append(\"<empty docstring>\")\n            data['text/plain'] = '\\n'.join(lines)\n        return msg\n\n    # iopub channel\n\n    def stream(self, msg):\n        content = msg['content']\n        content['text'] = content.pop('data')\n        return msg\n\n    def display_data(self, msg):\n        content = msg['content']\n        content.pop(\"source\", None)\n        data = content['data']\n        if 'application/json' in data:\n            try:\n                data['application/json'] = json.loads(data['application/json'])\n            except Exception:\n                # warn?\n                pass\n        return msg\n\n    # stdin channel\n\n    def input_request(self, msg):\n        msg['content'].setdefault('password', False)\n        return msg\n\n\n\ndef adapt(msg, to_version=protocol_version_info[0]):\n    \"\"\"Adapt a single message to a target version\n\n    Parameters\n    ----------\n\n    msg : dict\n        A Jupyter message.\n    to_version : int, optional\n        The target major version.\n        If unspecified, adapt to the current version.\n\n    Returns\n    -------\n\n    msg : dict\n        A Jupyter message appropriate in the new version.\n    \"\"\"\n    from .session import utcnow\n    header = msg['header']\n    if 'date' not in header:\n        header['date'] = utcnow()\n    if 'version' in header:\n        from_version = int(header['version'].split('.')[0])\n    else:\n        # assume last version before adding the key to the header\n        from_version = 4\n    adapter = adapters.get((from_version, to_version), None)\n    if adapter is None:\n        return msg\n    return adapter(msg)\n\n\n# one adapter per major version from,to\nadapters = {\n    (5,4) : V5toV4(),\n    (4,5) : V4toV5(),\n}\n"
  },
  {
    "path": "lib/client/jupyter_client/blocking/__init__.py",
    "content": "from .client import BlockingKernelClient"
  },
  {
    "path": "lib/client/jupyter_client/blocking/channels.py",
    "content": "\"\"\"Blocking channels\n\nUseful for test suites and blocking terminal interfaces.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\ntry:\n    from queue import Queue, Empty  # Py 3\nexcept ImportError:\n    from Queue import Queue, Empty  # Py 2\n\n\nclass ZMQSocketChannel(object):\n    \"\"\"A ZMQ socket in a simple blocking API\"\"\"\n    session = None\n    socket = None\n    stream = None\n    _exiting = False\n    proxy_methods = []\n\n    def __init__(self, socket, session, loop=None):\n        \"\"\"Create a channel.\n\n        Parameters\n        ----------\n        socket : :class:`zmq.Socket`\n            The ZMQ socket to use.\n        session : :class:`session.Session`\n            The session to use.\n        loop\n            Unused here, for other implementations\n        \"\"\"\n        super(ZMQSocketChannel, self).__init__()\n\n        self.socket = socket\n        self.session = session\n\n    def _recv(self, **kwargs):\n        msg = self.socket.recv_multipart(**kwargs)\n        ident,smsg = self.session.feed_identities(msg)\n        return self.session.deserialize(smsg)\n\n    def get_msg(self, block=True, timeout=None):\n        \"\"\" Gets a message if there is one that is ready. \"\"\"\n        if block:\n            if timeout is not None:\n                timeout *= 1000  # seconds to ms\n            ready = self.socket.poll(timeout)\n        else:\n            ready = self.socket.poll(timeout=0)\n\n        if ready:\n            return self._recv()\n        else:\n            raise Empty\n\n    def get_msgs(self):\n        \"\"\" Get all messages that are currently ready. \"\"\"\n        msgs = []\n        while True:\n            try:\n                msgs.append(self.get_msg(block=False))\n            except Empty:\n                break\n        return msgs\n\n    def msg_ready(self):\n        \"\"\" Is there a message that has been received? \"\"\"\n        return bool(self.socket.poll(timeout=0))\n\n    def close(self):\n        if self.socket is not None:\n            try:\n                self.socket.close(linger=0)\n            except Exception:\n                pass\n            self.socket = None\n    stop =  close\n\n    def is_alive(self):\n        return (self.socket is not None)\n\n    def send(self, msg):\n        \"\"\"Pass a message to the ZMQ socket to send\n        \"\"\"\n        self.session.send(self.socket, msg)\n\n    def start(self):\n        pass\n"
  },
  {
    "path": "lib/client/jupyter_client/blocking/client.py",
    "content": "\"\"\"Implements a fully blocking kernel client.\n\nUseful for test suites and blocking terminal interfaces.\n\"\"\"\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function\n\nfrom functools import partial\nfrom getpass import getpass\ntry:\n    from queue import Empty  # Python 3\nexcept ImportError:\n    from Queue import Empty  # Python 2\nimport sys\nimport time\n\nimport zmq\n\nfrom traitlets import Type\nfrom jupyter_client.channels import HBChannel\nfrom jupyter_client.client import KernelClient\nfrom .channels import ZMQSocketChannel\n\ntry:\n    monotonic = time.monotonic\nexcept AttributeError:\n    # py2\n    monotonic = time.time # close enough\n\ntry:\n    TimeoutError\nexcept NameError:\n    # py2\n    TimeoutError = RuntimeError\n\n\ndef reqrep(meth):\n    def wrapped(self, *args, **kwargs):\n        reply = kwargs.pop('reply', False)\n        timeout = kwargs.pop('timeout', None)\n        msg_id = meth(self, *args, **kwargs)\n        if not reply:\n            return msg_id\n\n        return self._recv_reply(msg_id, timeout=timeout)\n    \n    if not meth.__doc__:\n        # python -OO removes docstrings,\n        # so don't bother building the wrapped docstring\n        return wrapped\n    \n    basedoc, _ = meth.__doc__.split('Returns\\n', 1)\n    parts = [basedoc.strip()]\n    if 'Parameters' not in basedoc:\n        parts.append(\"\"\"\n        Parameters\n        ----------\n        \"\"\")\n    parts.append(\"\"\"\n        reply: bool (default: False)\n            Whether to wait for and return reply\n        timeout: float or None (default: None)\n            Timeout to use when waiting for a reply\n\n        Returns\n        -------\n        msg_id: str\n            The msg_id of the request sent, if reply=False (default)\n        reply: dict\n            The reply message for this request, if reply=True\n    \"\"\")\n    wrapped.__doc__ = '\\n'.join(parts)\n    return wrapped\n\nclass BlockingKernelClient(KernelClient):\n    \"\"\"A KernelClient with blocking APIs\n    \n    ``get_[channel]_msg()`` methods wait for and return messages on channels,\n    raising :exc:`queue.Empty` if no message arrives within ``timeout`` seconds.\n    \"\"\"\n    \n    def wait_for_ready(self, timeout=None):\n        \"\"\"Waits for a response when a client is blocked\n        \n        - Sets future time for timeout\n        - Blocks on shell channel until a message is received\n        - Exit if the kernel has died\n        - If client times out before receiving a message from the kernel, send RuntimeError\n        - Flush the IOPub channel\n        \"\"\"\n        if timeout is None:\n            abs_timeout = float('inf')\n        else:\n            abs_timeout = time.time() + timeout\n\n        from ..manager import KernelManager\n        if not isinstance(self.parent, KernelManager):\n            # This Client was not created by a KernelManager,\n            # so wait for kernel to become responsive to heartbeats\n            # before checking for kernel_info reply\n            while not self.is_alive():\n                if time.time() > abs_timeout:\n                    raise RuntimeError(\"Kernel didn't respond to heartbeats in %d seconds and timed out\" % timeout)\n                time.sleep(0.2)\n\n        # Wait for kernel info reply on shell channel\n        while True:\n            try:\n                msg = self.shell_channel.get_msg(block=True, timeout=1)\n            except Empty:\n                pass\n            else:\n                if msg['msg_type'] == 'kernel_info_reply':\n                    self._handle_kernel_info_reply(msg)\n                    break\n\n            if not self.is_alive():\n                raise RuntimeError('Kernel died before replying to kernel_info')\n\n            # Check if current time is ready check time plus timeout\n            if time.time() > abs_timeout:\n                raise RuntimeError(\"Kernel didn't respond in %d seconds\" % timeout)\n\n        # Flush IOPub channel\n        while True:\n            try:\n                msg = self.iopub_channel.get_msg(block=True, timeout=0.2)\n            except Empty:\n                break\n\n    # The classes to use for the various channels\n    shell_channel_class = Type(ZMQSocketChannel)\n    iopub_channel_class = Type(ZMQSocketChannel)\n    stdin_channel_class = Type(ZMQSocketChannel)\n    hb_channel_class = Type(HBChannel)\n\n\n    def _recv_reply(self, msg_id, timeout=None):\n        \"\"\"Receive and return the reply for a given request\"\"\"\n        if timeout is not None:\n            deadline = monotonic() + timeout\n        while True:\n            if timeout is not None:\n                timeout = max(0, deadline - monotonic())\n            try:\n                reply = self.get_shell_msg(timeout=timeout)\n            except Empty:\n                raise TimeoutError(\"Timeout waiting for reply\")\n            if reply['parent_header'].get('msg_id') != msg_id:\n                # not my reply, someone may have forgotten to retrieve theirs\n                continue\n            return reply\n\n\n    execute = reqrep(KernelClient.execute)\n    history = reqrep(KernelClient.history)\n    complete = reqrep(KernelClient.complete)\n    inspect = reqrep(KernelClient.inspect)\n    kernel_info = reqrep(KernelClient.kernel_info)\n    comm_info = reqrep(KernelClient.comm_info)\n    shutdown = reqrep(KernelClient.shutdown)\n\n\n    def _stdin_hook_default(self, msg):\n        \"\"\"Handle an input request\"\"\"\n        content = msg['content']\n        if content.get('password', False):\n            prompt = getpass\n        elif sys.version_info < (3,):\n            prompt = raw_input\n        else:\n            prompt = input\n\n        try:\n            raw_data = prompt(content[\"prompt\"])\n        except EOFError:\n            # turn EOFError into EOF character\n            raw_data = '\\x04'\n        except KeyboardInterrupt:\n            sys.stdout.write('\\n')\n            return\n\n        # only send stdin reply if there *was not* another request\n        # or execution finished while we were reading.\n        if not (self.stdin_channel.msg_ready() or self.shell_channel.msg_ready()):\n            self.input(raw_data)\n\n    def _output_hook_default(self, msg):\n        \"\"\"Default hook for redisplaying plain-text output\"\"\"\n        msg_type = msg['header']['msg_type']\n        content = msg['content']\n        if msg_type == 'stream':\n            stream = getattr(sys, content['name'])\n            stream.write(content['text'])\n        elif msg_type in ('display_data', 'execute_result'):\n            sys.stdout.write(content['data'].get('text/plain', ''))\n        elif msg_type == 'error':\n            print('\\n'.join(content['traceback']), file=sys.stderr)\n\n    def _output_hook_kernel(self, session, socket, parent_header, msg):\n        \"\"\"Output hook when running inside an IPython kernel\n\n        adds rich output support.\n        \"\"\"\n        msg_type = msg['header']['msg_type']\n        if msg_type in ('display_data', 'execute_result', 'error'):\n            session.send(socket, msg_type, msg['content'], parent=parent_header)\n        else:\n            self._output_hook_default(msg)\n\n    def execute_interactive(self, code, silent=False, store_history=True,\n                 user_expressions=None, allow_stdin=None, stop_on_error=True,\n                 timeout=None, output_hook=None, stdin_hook=None,\n                ):\n        \"\"\"Execute code in the kernel interactively\n\n        Output will be redisplayed, and stdin prompts will be relayed as well.\n        If an IPython kernel is detected, rich output will be displayed.\n\n        You can pass a custom output_hook callable that will be called\n        with every IOPub message that is produced instead of the default redisplay.\n\n        .. versionadded:: 5.0\n\n        Parameters\n        ----------\n        code : str\n            A string of code in the kernel's language.\n\n        silent : bool, optional (default False)\n            If set, the kernel will execute the code as quietly possible, and\n            will force store_history to be False.\n\n        store_history : bool, optional (default True)\n            If set, the kernel will store command history.  This is forced\n            to be False if silent is True.\n\n        user_expressions : dict, optional\n            A dict mapping names to expressions to be evaluated in the user's\n            dict. The expression values are returned as strings formatted using\n            :func:`repr`.\n\n        allow_stdin : bool, optional (default self.allow_stdin)\n            Flag for whether the kernel can send stdin requests to frontends.\n\n            Some frontends (e.g. the Notebook) do not support stdin requests.\n            If raw_input is called from code executed from such a frontend, a\n            StdinNotImplementedError will be raised.\n\n        stop_on_error: bool, optional (default True)\n            Flag whether to abort the execution queue, if an exception is encountered.\n\n        timeout: float or None (default: None)\n            Timeout to use when waiting for a reply\n\n        output_hook: callable(msg)\n            Function to be called with output messages.\n            If not specified, output will be redisplayed.\n\n        stdin_hook: callable(msg)\n            Function to be called with stdin_request messages.\n            If not specified, input/getpass will be called.\n\n        Returns\n        -------\n        reply: dict\n            The reply message for this request\n        \"\"\"\n        if not self.iopub_channel.is_alive():\n            raise RuntimeError(\"IOPub channel must be running to receive output\")\n        if allow_stdin is None:\n            allow_stdin = self.allow_stdin\n        if allow_stdin and not self.stdin_channel.is_alive():\n            raise RuntimeError(\"stdin channel must be running to allow input\")\n        msg_id = self.execute(code,\n                              silent=silent,\n                              store_history=store_history,\n                              user_expressions=user_expressions,\n                              allow_stdin=allow_stdin,\n                              stop_on_error=stop_on_error,\n        )\n        if stdin_hook is None:\n            stdin_hook = self._stdin_hook_default\n        if output_hook is None:\n            # detect IPython kernel\n            if 'IPython' in sys.modules:\n                from IPython import get_ipython\n                ip = get_ipython()\n                in_kernel = getattr(ip, 'kernel', False)\n                if in_kernel:\n                    output_hook = partial(\n                        self._output_hook_kernel,\n                        ip.display_pub.session,\n                        ip.display_pub.pub_socket,\n                        ip.display_pub.parent_header,\n                    )\n        if output_hook is None:\n            # default: redisplay plain-text outputs\n            output_hook = self._output_hook_default\n\n        # set deadline based on timeout\n        if timeout is not None:\n            deadline = monotonic() + timeout\n        else:\n            timeout_ms = None\n\n        poller = zmq.Poller()\n        iopub_socket = self.iopub_channel.socket\n        poller.register(iopub_socket, zmq.POLLIN)\n        if allow_stdin:\n            stdin_socket = self.stdin_channel.socket\n            poller.register(stdin_socket, zmq.POLLIN)\n        else:\n            stdin_socket = None\n\n        # wait for output and redisplay it\n        while True:\n            if timeout is not None:\n                timeout = max(0, deadline - monotonic())\n                timeout_ms = 1e3 * timeout\n            events = dict(poller.poll(timeout_ms))\n            if not events:\n                raise TimeoutError(\"Timeout waiting for output\")\n            if stdin_socket in events:\n                req = self.stdin_channel.get_msg(timeout=0)\n                stdin_hook(req)\n                continue\n            if iopub_socket not in events:\n                continue\n\n            msg = self.iopub_channel.get_msg(timeout=0)\n\n            if msg['parent_header'].get('msg_id') != msg_id:\n                # not from my request\n                continue\n            output_hook(msg)\n\n            # stop on idle\n            if msg['header']['msg_type'] == 'status' and \\\n            msg['content']['execution_state'] == 'idle':\n                break\n\n        # output is done, get the reply\n        if timeout is not None:\n            timeout = max(0, deadline - monotonic())\n        return self._recv_reply(msg_id, timeout=timeout)\n"
  },
  {
    "path": "lib/client/jupyter_client/channels.py",
    "content": "\"\"\"Base classes to manage a Client's interaction with a running kernel\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import absolute_import\n\nimport atexit\nimport errno\nfrom threading import Thread\nimport time\n\nimport zmq\n# import ZMQError in top-level namespace, to avoid ugly attribute-error messages\n# during garbage collection of threads at exit:\nfrom zmq import ZMQError\n\nfrom jupyter_client import protocol_version_info\n\nfrom .channelsabc import HBChannelABC\n\n#-----------------------------------------------------------------------------\n# Constants and exceptions\n#-----------------------------------------------------------------------------\n\nmajor_protocol_version = protocol_version_info[0]\n\nclass InvalidPortNumber(Exception):\n    pass\n\nclass HBChannel(Thread):\n    \"\"\"The heartbeat channel which monitors the kernel heartbeat.\n\n    Note that the heartbeat channel is paused by default. As long as you start\n    this channel, the kernel manager will ensure that it is paused and un-paused\n    as appropriate.\n    \"\"\"\n    context = None\n    session = None\n    socket = None\n    address = None\n    _exiting = False\n\n    time_to_dead = 1.\n    poller = None\n    _running = None\n    _pause = None\n    _beating = None\n\n    def __init__(self, context=None, session=None, address=None):\n        \"\"\"Create the heartbeat monitor thread.\n\n        Parameters\n        ----------\n        context : :class:`zmq.Context`\n            The ZMQ context to use.\n        session : :class:`session.Session`\n            The session to use.\n        address : zmq url\n            Standard (ip, port) tuple that the kernel is listening on.\n        \"\"\"\n        super(HBChannel, self).__init__()\n        self.daemon = True\n\n        self.context = context\n        self.session = session\n        if isinstance(address, tuple):\n            if address[1] == 0:\n                message = 'The port number for a channel cannot be 0.'\n                raise InvalidPortNumber(message)\n            address = \"tcp://%s:%i\" % address\n        self.address = address\n\n        # running is False until `.start()` is called\n        self._running = False\n        # don't start paused\n        self._pause = False\n        self.poller = zmq.Poller()\n\n    @staticmethod\n    @atexit.register\n    def _notice_exit():\n        # Class definitions can be torn down during interpreter shutdown.\n        # We only need to set _exiting flag if this hasn't happened.\n        if HBChannel is not None:\n            HBChannel._exiting = True\n\n    def _create_socket(self):\n        if self.socket is not None:\n            # close previous socket, before opening a new one\n            self.poller.unregister(self.socket)\n            self.socket.close()\n        self.socket = self.context.socket(zmq.REQ)\n        self.socket.linger = 1000\n        self.socket.connect(self.address)\n\n        self.poller.register(self.socket, zmq.POLLIN)\n\n    def _poll(self, start_time):\n        \"\"\"poll for heartbeat replies until we reach self.time_to_dead.\n\n        Ignores interrupts, and returns the result of poll(), which\n        will be an empty list if no messages arrived before the timeout,\n        or the event tuple if there is a message to receive.\n        \"\"\"\n\n        until_dead = self.time_to_dead - (time.time() - start_time)\n        # ensure poll at least once\n        until_dead = max(until_dead, 1e-3)\n        events = []\n        while True:\n            try:\n                events = self.poller.poll(1000 * until_dead)\n            except ZMQError as e:\n                if e.errno == errno.EINTR:\n                    # ignore interrupts during heartbeat\n                    # this may never actually happen\n                    until_dead = self.time_to_dead - (time.time() - start_time)\n                    until_dead = max(until_dead, 1e-3)\n                    pass\n                else:\n                    raise\n            except Exception:\n                if self._exiting:\n                    break\n                else:\n                    raise\n            else:\n                break\n        return events\n\n    def run(self):\n        \"\"\"The thread's main activity.  Call start() instead.\"\"\"\n        self._create_socket()\n        self._running = True\n        self._beating = True\n\n        while self._running:\n            if self._pause:\n                # just sleep, and skip the rest of the loop\n                time.sleep(self.time_to_dead)\n                continue\n\n            since_last_heartbeat = 0.0\n            # io.rprint('Ping from HB channel') # dbg\n            # no need to catch EFSM here, because the previous event was\n            # either a recv or connect, which cannot be followed by EFSM\n            self.socket.send(b'ping')\n            request_time = time.time()\n            ready = self._poll(request_time)\n            if ready:\n                self._beating = True\n                # the poll above guarantees we have something to recv\n                self.socket.recv()\n                # sleep the remainder of the cycle\n                remainder = self.time_to_dead - (time.time() - request_time)\n                if remainder > 0:\n                    time.sleep(remainder)\n                continue\n            else:\n                # nothing was received within the time limit, signal heart failure\n                self._beating = False\n                since_last_heartbeat = time.time() - request_time\n                self.call_handlers(since_last_heartbeat)\n                # and close/reopen the socket, because the REQ/REP cycle has been broken\n                self._create_socket()\n                continue\n\n    def pause(self):\n        \"\"\"Pause the heartbeat.\"\"\"\n        self._pause = True\n\n    def unpause(self):\n        \"\"\"Unpause the heartbeat.\"\"\"\n        self._pause = False\n\n    def is_beating(self):\n        \"\"\"Is the heartbeat running and responsive (and not paused).\"\"\"\n        if self.is_alive() and not self._pause and self._beating:\n            return True\n        else:\n            return False\n\n    def stop(self):\n        \"\"\"Stop the channel's event loop and join its thread.\"\"\"\n        self._running = False\n        self.join()\n        self.close()\n\n    def close(self):\n        if self.socket is not None:\n            try:\n                self.socket.close(linger=0)\n            except Exception:\n                pass\n            self.socket = None\n\n    def call_handlers(self, since_last_heartbeat):\n        \"\"\"This method is called in the ioloop thread when a message arrives.\n\n        Subclasses should override this method to handle incoming messages.\n        It is important to remember that this method is called in the thread\n        so that some logic must be done to ensure that the application level\n        handlers are called in the application thread.\n        \"\"\"\n        pass\n\n\nHBChannelABC.register(HBChannel)\n"
  },
  {
    "path": "lib/client/jupyter_client/channelsabc.py",
    "content": "\"\"\"Abstract base classes for kernel client channels\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport abc\n\nfrom ipython_genutils.py3compat import with_metaclass\n\n\nclass ChannelABC(with_metaclass(abc.ABCMeta, object)):\n    \"\"\"A base class for all channel ABCs.\"\"\"\n\n    @abc.abstractmethod\n    def start(self):\n        pass\n\n    @abc.abstractmethod\n    def stop(self):\n        pass\n\n    @abc.abstractmethod\n    def is_alive(self):\n        pass\n\n\nclass HBChannelABC(ChannelABC):\n    \"\"\"HBChannel ABC.\n\n    The docstrings for this class can be found in the base implementation:\n\n    `jupyter_client.channels.HBChannel`\n    \"\"\"\n\n    @abc.abstractproperty\n    def time_to_dead(self):\n        pass\n\n    @abc.abstractmethod\n    def pause(self):\n        pass\n\n    @abc.abstractmethod\n    def unpause(self):\n        pass\n\n    @abc.abstractmethod\n    def is_beating(self):\n        pass\n"
  },
  {
    "path": "lib/client/jupyter_client/client.py",
    "content": "\"\"\"Base class to manage the interaction with a running kernel\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import absolute_import\nfrom jupyter_client.channels import major_protocol_version\nfrom ipython_genutils.py3compat import string_types, iteritems\n\nimport zmq\n\nfrom traitlets import (\n    Any, Instance, Type,\n)\n\nfrom .channelsabc import (ChannelABC, HBChannelABC)\nfrom .clientabc import KernelClientABC\nfrom .connect import ConnectionFileMixin\n\n\n# some utilities to validate message structure, these might get moved elsewhere\n# if they prove to have more generic utility\n\ndef validate_string_dict(dct):\n    \"\"\"Validate that the input is a dict with string keys and values.\n\n    Raises ValueError if not.\"\"\"\n    for k,v in iteritems(dct):\n        if not isinstance(k, string_types):\n            raise ValueError('key %r in dict must be a string' % k)\n        if not isinstance(v, string_types):\n            raise ValueError('value %r in dict must be a string' % v)\n\n\nclass KernelClient(ConnectionFileMixin):\n    \"\"\"Communicates with a single kernel on any host via zmq channels.\n\n    There are four channels associated with each kernel:\n\n    * shell: for request/reply calls to the kernel.\n    * iopub: for the kernel to publish results to frontends.\n    * hb: for monitoring the kernel's heartbeat.\n    * stdin: for frontends to reply to raw_input calls in the kernel.\n\n    The messages that can be sent on these channels are exposed as methods of the\n    client (KernelClient.execute, complete, history, etc.). These methods only\n    send the message, they don't wait for a reply. To get results, use e.g.\n    :meth:`get_shell_msg` to fetch messages from the shell channel.\n    \"\"\"\n\n    # The PyZMQ Context to use for communication with the kernel.\n    context = Instance(zmq.Context)\n    def _context_default(self):\n        return zmq.Context.instance()\n\n    # The classes to use for the various channels\n    shell_channel_class = Type(ChannelABC)\n    iopub_channel_class = Type(ChannelABC)\n    stdin_channel_class = Type(ChannelABC)\n    hb_channel_class = Type(HBChannelABC)\n\n    # Protected traits\n    _shell_channel = Any()\n    _iopub_channel = Any()\n    _stdin_channel = Any()\n    _hb_channel = Any()\n\n    # flag for whether execute requests should be allowed to call raw_input:\n    allow_stdin = True\n\n    #--------------------------------------------------------------------------\n    # Channel proxy methods\n    #--------------------------------------------------------------------------\n\n    def get_shell_msg(self, *args, **kwargs):\n        \"\"\"Get a message from the shell channel\"\"\"\n        return self.shell_channel.get_msg(*args, **kwargs)\n\n    def get_iopub_msg(self, *args, **kwargs):\n        \"\"\"Get a message from the iopub channel\"\"\"\n        return self.iopub_channel.get_msg(*args, **kwargs)\n\n    def get_stdin_msg(self, *args, **kwargs):\n        \"\"\"Get a message from the stdin channel\"\"\"\n        return self.stdin_channel.get_msg(*args, **kwargs)\n\n    #--------------------------------------------------------------------------\n    # Channel management methods\n    #--------------------------------------------------------------------------\n\n    def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):\n        \"\"\"Starts the channels for this kernel.\n\n        This will create the channels if they do not exist and then start\n        them (their activity runs in a thread). If port numbers of 0 are\n        being used (random ports) then you must first call\n        :meth:`start_kernel`. If the channels have been stopped and you\n        call this, :class:`RuntimeError` will be raised.\n        \"\"\"\n        if shell:\n            self.shell_channel.start()\n            self.kernel_info()\n        if iopub:\n            self.iopub_channel.start()\n        if stdin:\n            self.stdin_channel.start()\n            self.allow_stdin = True\n        else:\n            self.allow_stdin = False\n        if hb:\n            self.hb_channel.start()\n\n    def stop_channels(self):\n        \"\"\"Stops all the running channels for this kernel.\n\n        This stops their event loops and joins their threads.\n        \"\"\"\n        if self.shell_channel.is_alive():\n            self.shell_channel.stop()\n        if self.iopub_channel.is_alive():\n            self.iopub_channel.stop()\n        if self.stdin_channel.is_alive():\n            self.stdin_channel.stop()\n        if self.hb_channel.is_alive():\n            self.hb_channel.stop()\n\n    @property\n    def channels_running(self):\n        \"\"\"Are any of the channels created and running?\"\"\"\n        return (self.shell_channel.is_alive() or self.iopub_channel.is_alive() or\n                self.stdin_channel.is_alive() or self.hb_channel.is_alive())\n\n    ioloop = None  # Overridden in subclasses that use pyzmq event loop\n\n    @property\n    def shell_channel(self):\n        \"\"\"Get the shell channel object for this kernel.\"\"\"\n        if self._shell_channel is None:\n            url = self._make_url('shell')\n            self.log.debug(\"connecting shell channel to %s\", url)\n            socket = self.connect_shell(identity=self.session.bsession)\n            self._shell_channel = self.shell_channel_class(\n                socket, self.session, self.ioloop\n            )\n        return self._shell_channel\n\n    @property\n    def iopub_channel(self):\n        \"\"\"Get the iopub channel object for this kernel.\"\"\"\n        if self._iopub_channel is None:\n            url = self._make_url('iopub')\n            self.log.debug(\"connecting iopub channel to %s\", url)\n            socket = self.connect_iopub()\n            self._iopub_channel = self.iopub_channel_class(\n                socket, self.session, self.ioloop\n            )\n        return self._iopub_channel\n\n    @property\n    def stdin_channel(self):\n        \"\"\"Get the stdin channel object for this kernel.\"\"\"\n        if self._stdin_channel is None:\n            url = self._make_url('stdin')\n            self.log.debug(\"connecting stdin channel to %s\", url)\n            socket = self.connect_stdin(identity=self.session.bsession)\n            self._stdin_channel = self.stdin_channel_class(\n                socket, self.session, self.ioloop\n            )\n        return self._stdin_channel\n\n    @property\n    def hb_channel(self):\n        \"\"\"Get the hb channel object for this kernel.\"\"\"\n        if self._hb_channel is None:\n            url = self._make_url('hb')\n            self.log.debug(\"connecting heartbeat channel to %s\", url)\n            self._hb_channel = self.hb_channel_class(\n                self.context, self.session, url\n            )\n        return self._hb_channel\n\n    def is_alive(self):\n        \"\"\"Is the kernel process still running?\"\"\"\n        from .manager import KernelManager\n        if isinstance(self.parent, KernelManager):\n            # This KernelClient was created by a KernelManager,\n            # we can ask the parent KernelManager:\n            return self.parent.is_alive()\n        if self._hb_channel is not None:\n            # We don't have access to the KernelManager,\n            # so we use the heartbeat.\n            return self._hb_channel.is_beating()\n        else:\n            # no heartbeat and not local, we can't tell if it's running,\n            # so naively return True\n            return True\n\n\n    # Methods to send specific messages on channels\n    def execute(self, code, silent=False, store_history=True,\n                user_expressions=None, allow_stdin=None, stop_on_error=True):\n        \"\"\"Execute code in the kernel.\n\n        Parameters\n        ----------\n        code : str\n            A string of code in the kernel's language.\n\n        silent : bool, optional (default False)\n            If set, the kernel will execute the code as quietly possible, and\n            will force store_history to be False.\n\n        store_history : bool, optional (default True)\n            If set, the kernel will store command history.  This is forced\n            to be False if silent is True.\n\n        user_expressions : dict, optional\n            A dict mapping names to expressions to be evaluated in the user's\n            dict. The expression values are returned as strings formatted using\n            :func:`repr`.\n\n        allow_stdin : bool, optional (default self.allow_stdin)\n            Flag for whether the kernel can send stdin requests to frontends.\n\n            Some frontends (e.g. the Notebook) do not support stdin requests.\n            If raw_input is called from code executed from such a frontend, a\n            StdinNotImplementedError will be raised.\n\n        stop_on_error: bool, optional (default True)\n            Flag whether to abort the execution queue, if an exception is encountered.\n\n        Returns\n        -------\n        The msg_id of the message sent.\n        \"\"\"\n        if user_expressions is None:\n            user_expressions = {}\n        if allow_stdin is None:\n            allow_stdin = self.allow_stdin\n\n\n        # Don't waste network traffic if inputs are invalid\n        if not isinstance(code, string_types):\n            raise ValueError('code %r must be a string' % code)\n        validate_string_dict(user_expressions)\n\n        # Create class for content/msg creation. Related to, but possibly\n        # not in Session.\n        content = dict(code=code, silent=silent, store_history=store_history,\n                       user_expressions=user_expressions,\n                       allow_stdin=allow_stdin, stop_on_error=stop_on_error\n                       )\n        msg = self.session.msg('execute_request', content)\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def complete(self, code, cursor_pos=None):\n        \"\"\"Tab complete text in the kernel's namespace.\n\n        Parameters\n        ----------\n        code : str\n            The context in which completion is requested.\n            Can be anything between a variable name and an entire cell.\n        cursor_pos : int, optional\n            The position of the cursor in the block of code where the completion was requested.\n            Default: ``len(code)``\n\n        Returns\n        -------\n        The msg_id of the message sent.\n        \"\"\"\n        if cursor_pos is None:\n            cursor_pos = len(code)\n        content = dict(code=code, cursor_pos=cursor_pos)\n        msg = self.session.msg('complete_request', content)\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def inspect(self, code, cursor_pos=None, detail_level=0):\n        \"\"\"Get metadata information about an object in the kernel's namespace.\n\n        It is up to the kernel to determine the appropriate object to inspect.\n\n        Parameters\n        ----------\n        code : str\n            The context in which info is requested.\n            Can be anything between a variable name and an entire cell.\n        cursor_pos : int, optional\n            The position of the cursor in the block of code where the info was requested.\n            Default: ``len(code)``\n        detail_level : int, optional\n            The level of detail for the introspection (0-2)\n\n        Returns\n        -------\n        The msg_id of the message sent.\n        \"\"\"\n        if cursor_pos is None:\n            cursor_pos = len(code)\n        content = dict(code=code, cursor_pos=cursor_pos,\n            detail_level=detail_level,\n        )\n        msg = self.session.msg('inspect_request', content)\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def history(self, raw=True, output=False, hist_access_type='range', **kwargs):\n        \"\"\"Get entries from the kernel's history list.\n\n        Parameters\n        ----------\n        raw : bool\n            If True, return the raw input.\n        output : bool\n            If True, then return the output as well.\n        hist_access_type : str\n            'range' (fill in session, start and stop params), 'tail' (fill in n)\n             or 'search' (fill in pattern param).\n\n        session : int\n            For a range request, the session from which to get lines. Session\n            numbers are positive integers; negative ones count back from the\n            current session.\n        start : int\n            The first line number of a history range.\n        stop : int\n            The final (excluded) line number of a history range.\n\n        n : int\n            The number of lines of history to get for a tail request.\n\n        pattern : str\n            The glob-syntax pattern for a search request.\n\n        Returns\n        -------\n        The ID of the message sent.\n        \"\"\"\n        if hist_access_type == 'range':\n            kwargs.setdefault('session', 0)\n            kwargs.setdefault('start', 0)\n        content = dict(raw=raw, output=output, hist_access_type=hist_access_type,\n                                                                    **kwargs)\n        msg = self.session.msg('history_request', content)\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def kernel_info(self):\n        \"\"\"Request kernel info\n\n        Returns\n        -------\n        The msg_id of the message sent\n        \"\"\"\n        msg = self.session.msg('kernel_info_request')\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def comm_info(self, target_name=None):\n        \"\"\"Request comm info\n        \n        Returns\n        -------\n        The msg_id of the message sent\n        \"\"\"\n        if target_name is None:\n            content = {}\n        else:\n            content = dict(target_name=target_name)\n        msg = self.session.msg('comm_info_request', content)\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def _handle_kernel_info_reply(self, msg):\n        \"\"\"handle kernel info reply\n\n        sets protocol adaptation version. This might\n        be run from a separate thread.\n        \"\"\"\n        adapt_version = int(msg['content']['protocol_version'].split('.')[0])\n        if adapt_version != major_protocol_version:\n            self.session.adapt_version = adapt_version\n\n    def shutdown(self, restart=False):\n        \"\"\"Request an immediate kernel shutdown.\n\n        Upon receipt of the (empty) reply, client code can safely assume that\n        the kernel has shut down and it's safe to forcefully terminate it if\n        it's still alive.\n\n        The kernel will send the reply via a function registered with Python's\n        atexit module, ensuring it's truly done as the kernel is done with all\n        normal operation.\n\n        Returns\n        -------\n        The msg_id of the message sent\n        \"\"\"\n        # Send quit message to kernel. Once we implement kernel-side setattr,\n        # this should probably be done that way, but for now this will do.\n        msg = self.session.msg('shutdown_request', {'restart':restart})\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def is_complete(self, code):\n        \"\"\"Ask the kernel whether some code is complete and ready to execute.\"\"\"\n        msg = self.session.msg('is_complete_request', {'code': code})\n        self.shell_channel.send(msg)\n        return msg['header']['msg_id']\n\n    def input(self, string):\n        \"\"\"Send a string of raw input to the kernel.\n\n        This should only be called in response to the kernel sending an\n        ``input_request`` message on the stdin channel.\n        \"\"\"\n        content = dict(value=string)\n        msg = self.session.msg('input_reply', content)\n        self.stdin_channel.send(msg)\n\n\nKernelClientABC.register(KernelClient)\n"
  },
  {
    "path": "lib/client/jupyter_client/clientabc.py",
    "content": "\"\"\"Abstract base class for kernel clients\"\"\"\n\n#-----------------------------------------------------------------------------\n#  Copyright (c) The Jupyter Development Team\n#\n#  Distributed under the terms of the BSD License.  The full license is in\n#  the file COPYING, distributed as part of this software.\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# Imports\n#-----------------------------------------------------------------------------\n\nimport abc\n\nfrom ipython_genutils.py3compat import with_metaclass\n\n#-----------------------------------------------------------------------------\n# Main kernel client class\n#-----------------------------------------------------------------------------\n\nclass KernelClientABC(with_metaclass(abc.ABCMeta, object)):\n    \"\"\"KernelManager ABC.\n\n    The docstrings for this class can be found in the base implementation:\n\n    `jupyter_client.client.KernelClient`\n    \"\"\"\n\n    @abc.abstractproperty\n    def kernel(self):\n        pass\n\n    @abc.abstractproperty\n    def shell_channel_class(self):\n        pass\n\n    @abc.abstractproperty\n    def iopub_channel_class(self):\n        pass\n\n    @abc.abstractproperty\n    def hb_channel_class(self):\n        pass\n\n    @abc.abstractproperty\n    def stdin_channel_class(self):\n        pass\n\n    #--------------------------------------------------------------------------\n    # Channel management methods\n    #--------------------------------------------------------------------------\n\n    @abc.abstractmethod\n    def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):\n        pass\n\n    @abc.abstractmethod\n    def stop_channels(self):\n        pass\n\n    @abc.abstractproperty\n    def channels_running(self):\n        pass\n\n    @abc.abstractproperty\n    def shell_channel(self):\n        pass\n\n    @abc.abstractproperty\n    def iopub_channel(self):\n        pass\n\n    @abc.abstractproperty\n    def stdin_channel(self):\n        pass\n\n    @abc.abstractproperty\n    def hb_channel(self):\n        pass\n"
  },
  {
    "path": "lib/client/jupyter_client/connect.py",
    "content": "\"\"\"Utilities for connecting to jupyter kernels\n\nThe :class:`ConnectionFileMixin` class in this module encapsulates the logic\nrelated to writing and reading connections files.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\n\nfrom __future__ import absolute_import\n\nimport errno\nimport glob\nimport json\nimport os\nimport socket\nimport stat\nimport tempfile\nimport warnings\nfrom getpass import getpass\n\nimport zmq\n\nfrom traitlets.config import LoggingConfigurable\nfrom .localinterfaces import localhost\nfrom ipython_genutils.path import filefind\nfrom ipython_genutils.py3compat import (\n    bytes_to_str, cast_bytes, cast_bytes_py2, string_types,\n)\nfrom traitlets import (\n    Bool, Integer, Unicode, CaselessStrEnum, Instance, Type,\n)\nfrom jupyter_core.paths import jupyter_data_dir, jupyter_runtime_dir\n\n\ndef write_connection_file(fname=None, shell_port=0, iopub_port=0, stdin_port=0, hb_port=0,\n                         control_port=0, ip='', key=b'', transport='tcp',\n                         signature_scheme='hmac-sha256', kernel_name=''\n                         ):\n    \"\"\"Generates a JSON config file, including the selection of random ports.\n\n    Parameters\n    ----------\n\n    fname : unicode\n        The path to the file to write\n\n    shell_port : int, optional\n        The port to use for ROUTER (shell) channel.\n\n    iopub_port : int, optional\n        The port to use for the SUB channel.\n\n    stdin_port : int, optional\n        The port to use for the ROUTER (raw input) channel.\n\n    control_port : int, optional\n        The port to use for the ROUTER (control) channel.\n\n    hb_port : int, optional\n        The port to use for the heartbeat REP channel.\n\n    ip  : str, optional\n        The ip address the kernel will bind to.\n\n    key : str, optional\n        The Session key used for message authentication.\n\n    signature_scheme : str, optional\n        The scheme used for message authentication.\n        This has the form 'digest-hash', where 'digest'\n        is the scheme used for digests, and 'hash' is the name of the hash function\n        used by the digest scheme.\n        Currently, 'hmac' is the only supported digest scheme,\n        and 'sha256' is the default hash function.\n\n    kernel_name : str, optional\n        The name of the kernel currently connected to.\n    \"\"\"\n    if not ip:\n        ip = localhost()\n    # default to temporary connector file\n    if not fname:\n        fd, fname = tempfile.mkstemp('.json')\n        os.close(fd)\n\n    # Find open ports as necessary.\n\n    ports = []\n    ports_needed = int(shell_port <= 0) + \\\n                   int(iopub_port <= 0) + \\\n                   int(stdin_port <= 0) + \\\n                   int(control_port <= 0) + \\\n                   int(hb_port <= 0)\n    if transport == 'tcp':\n        for i in range(ports_needed):\n            sock = socket.socket()\n            # struct.pack('ii', (0,0)) is 8 null bytes\n            sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, b'\\0' * 8)\n            sock.bind((ip, 0))\n            ports.append(sock)\n        for i, sock in enumerate(ports):\n            port = sock.getsockname()[1]\n            sock.close()\n            ports[i] = port\n    else:\n        N = 1\n        for i in range(ports_needed):\n            while os.path.exists(\"%s-%s\" % (ip, str(N))):\n                N += 1\n            ports.append(N)\n            N += 1\n    if shell_port <= 0:\n        shell_port = ports.pop(0)\n    if iopub_port <= 0:\n        iopub_port = ports.pop(0)\n    if stdin_port <= 0:\n        stdin_port = ports.pop(0)\n    if control_port <= 0:\n        control_port = ports.pop(0)\n    if hb_port <= 0:\n        hb_port = ports.pop(0)\n\n    cfg = dict( shell_port=shell_port,\n                iopub_port=iopub_port,\n                stdin_port=stdin_port,\n                control_port=control_port,\n                hb_port=hb_port,\n              )\n    cfg['ip'] = ip\n    cfg['key'] = bytes_to_str(key)\n    cfg['transport'] = transport\n    cfg['signature_scheme'] = signature_scheme\n    cfg['kernel_name'] = kernel_name\n\n    with open(fname, 'w') as f:\n        f.write(json.dumps(cfg, indent=2))\n\n    if hasattr(stat, 'S_ISVTX'):\n        # set the sticky bit on the file and its parent directory\n        # to avoid periodic cleanup\n        paths = [fname]\n        runtime_dir = os.path.dirname(fname)\n        if runtime_dir:\n            paths.append(runtime_dir)\n        for path in paths:\n            permissions = os.stat(path).st_mode\n            new_permissions = permissions | stat.S_ISVTX\n            if new_permissions != permissions:\n                try:\n                    os.chmod(path, new_permissions)\n                except OSError as e:\n                    if e.errno == errno.EPERM and path == runtime_dir:\n                        # suppress permission errors setting sticky bit on runtime_dir,\n                        # which we may not own.\n                        pass\n                    else:\n                        # failed to set sticky bit, probably not a big deal\n                        warnings.warn(\n                            \"Failed to set sticky bit on %r: %s\"\n                            \"\\nProbably not a big deal, but runtime files may be cleaned up periodically.\" % (path, e),\n                            RuntimeWarning,\n                        )\n\n    return fname, cfg\n\n\ndef find_connection_file(filename='kernel-*.json', path=None, profile=None):\n    \"\"\"find a connection file, and return its absolute path.\n\n    The current working directory and optional search path\n    will be searched for the file if it is not given by absolute path.\n\n    If the argument does not match an existing file, it will be interpreted as a\n    fileglob, and the matching file in the profile's security dir with\n    the latest access time will be used.\n\n    Parameters\n    ----------\n    filename : str\n        The connection file or fileglob to search for.\n    path : str or list of strs[optional]\n        Paths in which to search for connection files.\n\n    Returns\n    -------\n    str : The absolute path of the connection file.\n    \"\"\"\n    if profile is not None:\n        warnings.warn(\"Jupyter has no profiles. profile=%s has been ignored.\" % profile)\n    if path is None:\n        path = ['.', jupyter_runtime_dir()]\n    if isinstance(path, string_types):\n        path = [path]\n    \n    try:\n        # first, try explicit name\n        return filefind(filename, path)\n    except IOError:\n        pass\n\n    # not found by full name\n\n    if '*' in filename:\n        # given as a glob already\n        pat = filename\n    else:\n        # accept any substring match\n        pat = '*%s*' % filename\n    \n    matches = []\n    for p in path:\n        matches.extend(glob.glob(os.path.join(p, pat)))\n    \n    matches = [ os.path.abspath(m) for m in matches ]\n    if not matches:\n        raise IOError(\"Could not find %r in %r\" % (filename, path))\n    elif len(matches) == 1:\n        return matches[0]\n    else:\n        # get most recent match, by access time:\n        return sorted(matches, key=lambda f: os.stat(f).st_atime)[-1]\n\n\ndef tunnel_to_kernel(connection_info, sshserver, sshkey=None):\n    \"\"\"tunnel connections to a kernel via ssh\n\n    This will open four SSH tunnels from localhost on this machine to the\n    ports associated with the kernel.  They can be either direct\n    localhost-localhost tunnels, or if an intermediate server is necessary,\n    the kernel must be listening on a public IP.\n\n    Parameters\n    ----------\n    connection_info : dict or str (path)\n        Either a connection dict, or the path to a JSON connection file\n    sshserver : str\n        The ssh sever to use to tunnel to the kernel. Can be a full\n        `user@server:port` string. ssh config aliases are respected.\n    sshkey : str [optional]\n        Path to file containing ssh key to use for authentication.\n        Only necessary if your ssh config does not already associate\n        a keyfile with the host.\n\n    Returns\n    -------\n\n    (shell, iopub, stdin, hb) : ints\n        The four ports on localhost that have been forwarded to the kernel.\n    \"\"\"\n    from zmq.ssh import tunnel\n    if isinstance(connection_info, string_types):\n        # it's a path, unpack it\n        with open(connection_info) as f:\n            connection_info = json.loads(f.read())\n\n    cf = connection_info\n\n    lports = tunnel.select_random_ports(4)\n    rports = cf['shell_port'], cf['iopub_port'], cf['stdin_port'], cf['hb_port']\n\n    remote_ip = cf['ip']\n\n    if tunnel.try_passwordless_ssh(sshserver, sshkey):\n        password=False\n    else:\n        password = getpass(\"SSH Password for %s: \" % cast_bytes_py2(sshserver))\n\n    for lp,rp in zip(lports, rports):\n        tunnel.ssh_tunnel(lp, rp, sshserver, remote_ip, sshkey, password)\n\n    return tuple(lports)\n\n\n#-----------------------------------------------------------------------------\n# Mixin for classes that work with connection files\n#-----------------------------------------------------------------------------\n\nchannel_socket_types = {\n    'hb' : zmq.REQ,\n    'shell' : zmq.DEALER,\n    'iopub' : zmq.SUB,\n    'stdin' : zmq.DEALER,\n    'control': zmq.DEALER,\n}\n\nport_names = [ \"%s_port\" % channel for channel in ('shell', 'stdin', 'iopub', 'hb', 'control')]\n\nclass ConnectionFileMixin(LoggingConfigurable):\n    \"\"\"Mixin for configurable classes that work with connection files\"\"\"\n    \n    data_dir = Unicode()\n    def _data_dir_default(self):\n        return jupyter_data_dir()\n    \n    # The addresses for the communication channels\n    connection_file = Unicode('', config=True,\n    help=\"\"\"JSON file in which to store connection info [default: kernel-<pid>.json]\n\n    This file will contain the IP, ports, and authentication key needed to connect\n    clients to this kernel. By default, this file will be created in the security dir\n    of the current profile, but can be specified by absolute path.\n    \"\"\")\n    _connection_file_written = Bool(False)\n\n    transport = CaselessStrEnum(['tcp', 'ipc'], default_value='tcp', config=True)\n    kernel_name = Unicode()\n\n    ip = Unicode(config=True,\n        help=\"\"\"Set the kernel\\'s IP address [default localhost].\n        If the IP address is something other than localhost, then\n        Consoles on other machines will be able to connect\n        to the Kernel, so be careful!\"\"\"\n    )\n\n    def _ip_default(self):\n        if self.transport == 'ipc':\n            if self.connection_file:\n                return os.path.splitext(self.connection_file)[0] + '-ipc'\n            else:\n                return 'kernel-ipc'\n        else:\n            return localhost()\n\n    def _ip_changed(self, name, old, new):\n        if new == '*':\n            self.ip = '0.0.0.0'\n\n    # protected traits\n\n    hb_port = Integer(0, config=True,\n            help=\"set the heartbeat port [default: random]\")\n    shell_port = Integer(0, config=True,\n            help=\"set the shell (ROUTER) port [default: random]\")\n    iopub_port = Integer(0, config=True,\n            help=\"set the iopub (PUB) port [default: random]\")\n    stdin_port = Integer(0, config=True,\n            help=\"set the stdin (ROUTER) port [default: random]\")\n    control_port = Integer(0, config=True,\n            help=\"set the control (ROUTER) port [default: random]\")\n\n    # names of the ports with random assignment\n    _random_port_names = None\n\n    @property\n    def ports(self):\n        return [ getattr(self, name) for name in port_names ]\n\n    # The Session to use for communication with the kernel.\n    session = Instance('jupyter_client.session.Session')\n    def _session_default(self):\n        from jupyter_client.session import Session\n        return Session(parent=self)\n\n    #--------------------------------------------------------------------------\n    # Connection and ipc file management\n    #--------------------------------------------------------------------------\n\n    def get_connection_info(self, session=False):\n        \"\"\"Return the connection info as a dict\n\n        Parameters\n        ----------\n        session : bool [default: False]\n            If True, return our session object will be included in the connection info.\n            If False (default), the configuration parameters of our session object will be included,\n            rather than the session object itself.\n\n        Returns\n        -------\n        connect_info : dict\n            dictionary of connection information.\n        \"\"\"\n        info = dict(\n            transport=self.transport,\n            ip=self.ip,\n            shell_port=self.shell_port,\n            iopub_port=self.iopub_port,\n            stdin_port=self.stdin_port,\n            hb_port=self.hb_port,\n            control_port=self.control_port,\n        )\n        if session:\n            # add *clone* of my session,\n            # so that state such as digest_history is not shared.\n            info['session'] = self.session.clone()\n        else:\n            # add session info\n            info.update(dict(\n                signature_scheme=self.session.signature_scheme,\n                key=self.session.key,\n            ))\n        return info\n\n    # factory for blocking clients\n    blocking_class = Type(klass=object, default_value='jupyter_client.BlockingKernelClient')\n    def blocking_client(self):\n        \"\"\"Make a blocking client connected to my kernel\"\"\"\n        info = self.get_connection_info()\n        info['parent'] = self\n        bc = self.blocking_class(**info)\n        bc.session.key = self.session.key\n        return bc\n\n    def cleanup_connection_file(self):\n        \"\"\"Cleanup connection file *if we wrote it*\n\n        Will not raise if the connection file was already removed somehow.\n        \"\"\"\n        if self._connection_file_written:\n            # cleanup connection files on full shutdown of kernel we started\n            self._connection_file_written = False\n            try:\n                os.remove(self.connection_file)\n            except (IOError, OSError, AttributeError):\n                pass\n\n    def cleanup_ipc_files(self):\n        \"\"\"Cleanup ipc files if we wrote them.\"\"\"\n        if self.transport != 'ipc':\n            return\n        for port in self.ports:\n            ipcfile = \"%s-%i\" % (self.ip, port)\n            try:\n                os.remove(ipcfile)\n            except (IOError, OSError):\n                pass\n\n    def _record_random_port_names(self):\n        \"\"\"Records which of the ports are randomly assigned.\n\n        Records on first invocation, if the transport is tcp.\n        Does nothing on later invocations.\"\"\"\n\n        if self.transport != 'tcp':\n            return\n        if self._random_port_names is not None:\n            return\n\n        self._random_port_names = []\n        for name in port_names:\n            if getattr(self, name) <= 0:\n                self._random_port_names.append(name)\n\n    def cleanup_random_ports(self):\n        \"\"\"Forgets randomly assigned port numbers and cleans up the connection file.\n\n        Does nothing if no port numbers have been randomly assigned.\n        In particular, does nothing unless the transport is tcp.\n        \"\"\"\n\n        if not self._random_port_names:\n            return\n\n        for name in self._random_port_names:\n            setattr(self, name, 0)\n\n        self.cleanup_connection_file()\n\n    def write_connection_file(self):\n        \"\"\"Write connection info to JSON dict in self.connection_file.\"\"\"\n        if self._connection_file_written and os.path.exists(self.connection_file):\n            return\n\n        self.connection_file, cfg = write_connection_file(self.connection_file,\n            transport=self.transport, ip=self.ip, key=self.session.key,\n            stdin_port=self.stdin_port, iopub_port=self.iopub_port,\n            shell_port=self.shell_port, hb_port=self.hb_port,\n            control_port=self.control_port,\n            signature_scheme=self.session.signature_scheme,\n            kernel_name=self.kernel_name\n        )\n        # write_connection_file also sets default ports:\n        self._record_random_port_names()\n        for name in port_names:\n            setattr(self, name, cfg[name])\n\n        self._connection_file_written = True\n\n    def load_connection_file(self, connection_file=None):\n        \"\"\"Load connection info from JSON dict in self.connection_file.\n        \n        Parameters\n        ----------\n        connection_file: unicode, optional\n            Path to connection file to load.\n            If unspecified, use self.connection_file\n        \"\"\"\n        if connection_file is None:\n            connection_file = self.connection_file\n        self.log.debug(u\"Loading connection file %s\", connection_file)\n        with open(connection_file) as f:\n            info = json.load(f)\n        self.load_connection_info(info)\n\n    def load_connection_info(self, info):\n        \"\"\"Load connection info from a dict containing connection info.\n        \n        Typically this data comes from a connection file\n        and is called by load_connection_file.\n        \n        Parameters\n        ----------\n        info: dict\n            Dictionary containing connection_info.\n            See the connection_file spec for details.\n        \"\"\"\n        self.transport = info.get('transport', self.transport)\n        self.ip = info.get('ip', self._ip_default())\n\n        self._record_random_port_names()\n        for name in port_names:\n            if getattr(self, name) == 0 and name in info:\n                # not overridden by config or cl_args\n                setattr(self, name, info[name])\n\n        if 'key' in info:\n            self.session.key = cast_bytes(info['key'])\n        if 'signature_scheme' in info:\n            self.session.signature_scheme = info['signature_scheme']\n\n    #--------------------------------------------------------------------------\n    # Creating connected sockets\n    #--------------------------------------------------------------------------\n\n    def _make_url(self, channel):\n        \"\"\"Make a ZeroMQ URL for a given channel.\"\"\"\n        transport = self.transport\n        ip = self.ip\n        port = getattr(self, '%s_port' % channel)\n\n        if transport == 'tcp':\n            return \"tcp://%s:%i\" % (ip, port)\n        else:\n            return \"%s://%s-%s\" % (transport, ip, port)\n\n    def _create_connected_socket(self, channel, identity=None):\n        \"\"\"Create a zmq Socket and connect it to the kernel.\"\"\"\n        url = self._make_url(channel)\n        socket_type = channel_socket_types[channel]\n        self.log.debug(\"Connecting to: %s\" % url)\n        sock = self.context.socket(socket_type)\n        # set linger to 1s to prevent hangs at exit\n        sock.linger = 1000\n        if identity:\n            sock.identity = identity\n        sock.connect(url)\n        return sock\n\n    def connect_iopub(self, identity=None):\n        \"\"\"return zmq Socket connected to the IOPub channel\"\"\"\n        sock = self._create_connected_socket('iopub', identity=identity)\n        sock.setsockopt(zmq.SUBSCRIBE, b'')\n        return sock\n\n    def connect_shell(self, identity=None):\n        \"\"\"return zmq Socket connected to the Shell channel\"\"\"\n        return self._create_connected_socket('shell', identity=identity)\n\n    def connect_stdin(self, identity=None):\n        \"\"\"return zmq Socket connected to the StdIn channel\"\"\"\n        return self._create_connected_socket('stdin', identity=identity)\n\n    def connect_hb(self, identity=None):\n        \"\"\"return zmq Socket connected to the Heartbeat channel\"\"\"\n        return self._create_connected_socket('hb', identity=identity)\n\n    def connect_control(self, identity=None):\n        \"\"\"return zmq Socket connected to the Control channel\"\"\"\n        return self._create_connected_socket('control', identity=identity)\n\n\n__all__ = [\n    'write_connection_file',\n    'find_connection_file',\n    'tunnel_to_kernel',\n]\n"
  },
  {
    "path": "lib/client/jupyter_client/consoleapp.py",
    "content": "\"\"\" A minimal application base mixin for all ZMQ based IPython frontends.\n\nThis is not a complete console app, as subprocess will not be able to receive\ninput, there is no real readline support, among other limitations. This is a\nrefactoring of what used to be the IPython/qt/console/qtconsoleapp.py\n\"\"\"\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport atexit\nimport os\nimport signal\nimport sys\nimport uuid\nimport warnings\n\n\nfrom traitlets.config.application import boolean_flag\nfrom ipython_genutils.path import filefind\nfrom traitlets import (\n    Dict, List, Unicode, CUnicode, CBool, Any\n)\n\nfrom jupyter_core.application import base_flags, base_aliases\n\nfrom .blocking import BlockingKernelClient\nfrom .restarter import KernelRestarter\nfrom . import KernelManager, tunnel_to_kernel, find_connection_file, connect\nfrom .kernelspec import NoSuchKernel\nfrom .session import Session\n\nConnectionFileMixin = connect.ConnectionFileMixin\n\nfrom .localinterfaces import localhost\n\n#-----------------------------------------------------------------------------\n# Aliases and Flags\n#-----------------------------------------------------------------------------\n\nflags = {}\nflags.update(base_flags)\n# the flags that are specific to the frontend\n# these must be scrubbed before being passed to the kernel,\n# or it will raise an error on unrecognized flags\napp_flags = {\n    'existing' : ({'JupyterConsoleApp' : {'existing' : 'kernel*.json'}},\n            \"Connect to an existing kernel. If no argument specified, guess most recent\"),\n}\napp_flags.update(boolean_flag(\n    'confirm-exit', 'JupyterConsoleApp.confirm_exit',\n    \"\"\"Set to display confirmation dialog on exit. You can always use 'exit' or\n       'quit', to force a direct exit without any confirmation. This can also\n       be set in the config file by setting\n       `c.JupyterConsoleApp.confirm_exit`.\n    \"\"\",\n    \"\"\"Don't prompt the user when exiting. This will terminate the kernel\n       if it is owned by the frontend, and leave it alive if it is external.\n       This can also be set in the config file by setting\n       `c.JupyterConsoleApp.confirm_exit`.\n    \"\"\"\n))\nflags.update(app_flags)\n\naliases = {}\naliases.update(base_aliases)\n\n# also scrub aliases from the frontend\napp_aliases = dict(\n    ip = 'JupyterConsoleApp.ip',\n    transport = 'JupyterConsoleApp.transport',\n    hb = 'JupyterConsoleApp.hb_port',\n    shell = 'JupyterConsoleApp.shell_port',\n    iopub = 'JupyterConsoleApp.iopub_port',\n    stdin = 'JupyterConsoleApp.stdin_port',\n    existing = 'JupyterConsoleApp.existing',\n    f = 'JupyterConsoleApp.connection_file',\n\n    kernel = 'JupyterConsoleApp.kernel_name',\n\n    ssh = 'JupyterConsoleApp.sshserver',\n)\naliases.update(app_aliases)\n\n#-----------------------------------------------------------------------------\n# Classes\n#-----------------------------------------------------------------------------\n\nclasses = [KernelManager, KernelRestarter, Session]\n\nclass JupyterConsoleApp(ConnectionFileMixin):\n    name = 'jupyter-console-mixin'\n\n    description = \"\"\"\n        The Jupyter Console Mixin.\n        \n        This class contains the common portions of console client (QtConsole,\n        ZMQ-based terminal console, etc).  It is not a full console, in that\n        launched terminal subprocesses will not be able to accept input.\n        \n        The Console using this mixing supports various extra features beyond\n        the single-process Terminal IPython shell, such as connecting to\n        existing kernel, via:\n        \n            jupyter console <appname> --existing\n        \n        as well as tunnel via SSH\n        \n    \"\"\"\n\n    classes = classes\n    flags = Dict(flags)\n    aliases = Dict(aliases)\n    kernel_manager_class = KernelManager\n    kernel_client_class = BlockingKernelClient\n\n    kernel_argv = List(Unicode())\n\n    # connection info:\n    \n    sshserver = Unicode('', config=True,\n        help=\"\"\"The SSH server to use to connect to the kernel.\"\"\")\n    sshkey = Unicode('', config=True,\n        help=\"\"\"Path to the ssh key to use for logging in to the ssh server.\"\"\")\n    \n    def _connection_file_default(self):\n        return 'kernel-%i.json' % os.getpid()\n\n    existing = CUnicode('', config=True,\n        help=\"\"\"Connect to an already running kernel\"\"\")\n\n    kernel_name = Unicode('python', config=True,\n        help=\"\"\"The name of the default kernel to start.\"\"\")\n\n    confirm_exit = CBool(True, config=True,\n        help=\"\"\"\n        Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',\n        to force a direct exit without any confirmation.\"\"\",\n    )\n    \n    def build_kernel_argv(self, argv=None):\n        \"\"\"build argv to be passed to kernel subprocess\n        \n        Override in subclasses if any args should be passed to the kernel\n        \"\"\"\n        self.kernel_argv = self.extra_args\n    \n    def init_connection_file(self):\n        \"\"\"find the connection file, and load the info if found.\n        \n        The current working directory and the current profile's security\n        directory will be searched for the file if it is not given by\n        absolute path.\n        \n        When attempting to connect to an existing kernel and the `--existing`\n        argument does not match an existing file, it will be interpreted as a\n        fileglob, and the matching file in the current profile's security dir\n        with the latest access time will be used.\n        \n        After this method is called, self.connection_file contains the *full path*\n        to the connection file, never just its name.\n        \"\"\"\n        if self.existing:\n            try:\n                cf = find_connection_file(self.existing, ['.', self.runtime_dir])\n            except Exception:\n                self.log.critical(\"Could not find existing kernel connection file %s\", self.existing)\n                self.exit(1)\n            self.log.debug(\"Connecting to existing kernel: %s\" % cf)\n            self.connection_file = cf\n        else:\n            # not existing, check if we are going to write the file\n            # and ensure that self.connection_file is a full path, not just the shortname\n            try:\n                cf = find_connection_file(self.connection_file, [self.runtime_dir])\n            except Exception:\n                # file might not exist\n                if self.connection_file == os.path.basename(self.connection_file):\n                    # just shortname, put it in security dir\n                    cf = os.path.join(self.runtime_dir, self.connection_file)\n                else:\n                    cf = self.connection_file\n                self.connection_file = cf\n        try:\n            self.connection_file = filefind(self.connection_file, ['.', self.runtime_dir])\n        except IOError:\n            self.log.debug(\"Connection File not found: %s\", self.connection_file)\n            return\n        \n        # should load_connection_file only be used for existing?\n        # as it is now, this allows reusing ports if an existing\n        # file is requested\n        try:\n            self.load_connection_file()\n        except Exception:\n            self.log.error(\"Failed to load connection file: %r\", self.connection_file, exc_info=True)\n            self.exit(1)\n    \n    def init_ssh(self):\n        \"\"\"set up ssh tunnels, if needed.\"\"\"\n        if not self.existing or (not self.sshserver and not self.sshkey):\n            return\n        self.load_connection_file()\n        \n        transport = self.transport\n        ip = self.ip\n        \n        if transport != 'tcp':\n            self.log.error(\"Can only use ssh tunnels with TCP sockets, not %s\", transport)\n            sys.exit(-1)\n        \n        if self.sshkey and not self.sshserver:\n            # specifying just the key implies that we are connecting directly\n            self.sshserver = ip\n            ip = localhost()\n        \n        # build connection dict for tunnels:\n        info = dict(ip=ip,\n                    shell_port=self.shell_port,\n                    iopub_port=self.iopub_port,\n                    stdin_port=self.stdin_port,\n                    hb_port=self.hb_port\n        )\n        \n        self.log.info(\"Forwarding connections to %s via %s\"%(ip, self.sshserver))\n        \n        # tunnels return a new set of ports, which will be on localhost:\n        self.ip = localhost()\n        try:\n            newports = tunnel_to_kernel(info, self.sshserver, self.sshkey)\n        except:\n            # even catch KeyboardInterrupt\n            self.log.error(\"Could not setup tunnels\", exc_info=True)\n            self.exit(1)\n        \n        self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = newports\n        \n        cf = self.connection_file\n        root, ext = os.path.splitext(cf)\n        self.connection_file = root + '-ssh' + ext\n        self.write_connection_file() # write the new connection file\n        self.log.info(\"To connect another client via this tunnel, use:\")\n        self.log.info(\"--existing %s\" % os.path.basename(self.connection_file))\n    \n    def _new_connection_file(self):\n        cf = ''\n        while not cf:\n            # we don't need a 128b id to distinguish kernels, use more readable\n            # 48b node segment (12 hex chars).  Users running more than 32k simultaneous\n            # kernels can subclass.\n            ident = str(uuid.uuid4()).split('-')[-1]\n            cf = os.path.join(self.runtime_dir, 'kernel-%s.json' % ident)\n            # only keep if it's actually new.  Protect against unlikely collision\n            # in 48b random search space\n            cf = cf if not os.path.exists(cf) else ''\n        return cf\n\n    def init_kernel_manager(self):\n        # Don't let Qt or ZMQ swallow KeyboardInterupts.\n        if self.existing:\n            self.kernel_manager = None\n            return\n        signal.signal(signal.SIGINT, signal.SIG_DFL)\n\n        # Create a KernelManager and start a kernel.\n        try:\n            self.kernel_manager = self.kernel_manager_class(\n                                    ip=self.ip,\n                                    session=self.session,\n                                    transport=self.transport,\n                                    shell_port=self.shell_port,\n                                    iopub_port=self.iopub_port,\n                                    stdin_port=self.stdin_port,\n                                    hb_port=self.hb_port,\n                                    connection_file=self.connection_file,\n                                    kernel_name=self.kernel_name,\n                                    parent=self,\n                                    data_dir=self.data_dir,\n            )\n        except NoSuchKernel:\n            self.log.critical(\"Could not find kernel %s\", self.kernel_name)\n            self.exit(1)\n\n        self.kernel_manager.client_factory = self.kernel_client_class\n        # FIXME: remove special treatment of IPython kernels\n        kwargs = {}\n        if self.kernel_manager.ipykernel:\n            kwargs['extra_arguments'] = self.kernel_argv\n        self.kernel_manager.start_kernel(**kwargs)\n        atexit.register(self.kernel_manager.cleanup_ipc_files)\n\n        if self.sshserver:\n            # ssh, write new connection file\n            self.kernel_manager.write_connection_file()\n\n        # in case KM defaults / ssh writing changes things:\n        km = self.kernel_manager\n        self.shell_port=km.shell_port\n        self.iopub_port=km.iopub_port\n        self.stdin_port=km.stdin_port\n        self.hb_port=km.hb_port\n        self.connection_file = km.connection_file\n\n        atexit.register(self.kernel_manager.cleanup_connection_file)\n\n    def init_kernel_client(self):\n        if self.kernel_manager is not None:\n            self.kernel_client = self.kernel_manager.client()\n        else:\n            self.kernel_client = self.kernel_client_class(\n                                session=self.session,\n                                ip=self.ip,\n                                transport=self.transport,\n                                shell_port=self.shell_port,\n                                iopub_port=self.iopub_port,\n                                stdin_port=self.stdin_port,\n                                hb_port=self.hb_port,\n                                connection_file=self.connection_file,\n                                parent=self,\n            )\n\n        self.kernel_client.start_channels()\n\n\n\n    def initialize(self, argv=None):\n        \"\"\"\n        Classes which mix this class in should call:\n               JupyterConsoleApp.initialize(self,argv)\n        \"\"\"\n        if self._dispatching:\n            return\n        self.init_connection_file()\n        self.init_ssh()\n        self.init_kernel_manager()\n        self.init_kernel_client()\n\nclass IPythonConsoleApp(JupyterConsoleApp):\n    def __init__(self, *args, **kwargs):\n        warnings.warn(\"IPythonConsoleApp is deprecated. Use JupyterConsoleApp\")\n        super(IPythonConsoleApp, self).__init__(*args, **kwargs)\n"
  },
  {
    "path": "lib/client/jupyter_client/ioloop/__init__.py",
    "content": "from .manager import IOLoopKernelManager\nfrom .restarter import IOLoopKernelRestarter\n"
  },
  {
    "path": "lib/client/jupyter_client/ioloop/manager.py",
    "content": "\"\"\"A kernel manager with a tornado IOLoop\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import absolute_import\n\nfrom zmq.eventloop import ioloop\nfrom zmq.eventloop.zmqstream import ZMQStream\n\nfrom traitlets import (\n    Instance,\n    Type,\n)\n\nfrom jupyter_client.manager import KernelManager\nfrom .restarter import IOLoopKernelRestarter\n\n\ndef as_zmqstream(f):\n    def wrapped(self, *args, **kwargs):\n        socket = f(self, *args, **kwargs)\n        return ZMQStream(socket, self.loop)\n    return wrapped\n\nclass IOLoopKernelManager(KernelManager):\n\n    loop = Instance('tornado.ioloop.IOLoop')\n    def _loop_default(self):\n        return ioloop.IOLoop.current()\n\n    restarter_class = Type(\n        default_value=IOLoopKernelRestarter,\n        klass=IOLoopKernelRestarter,\n        help=(\n            'Type of KernelRestarter to use. '\n            'Must be a subclass of IOLoopKernelRestarter.\\n'\n            'Override this to customize how kernel restarts are managed.'\n        ),\n        config=True,\n    )\n    _restarter = Instance('jupyter_client.ioloop.IOLoopKernelRestarter', allow_none=True)\n\n    def start_restarter(self):\n        if self.autorestart and self.has_kernel:\n            if self._restarter is None:\n                self._restarter = self.restarter_class(\n                    kernel_manager=self, loop=self.loop,\n                    parent=self, log=self.log\n                )\n            self._restarter.start()\n\n    def stop_restarter(self):\n        if self.autorestart:\n            if self._restarter is not None:\n                self._restarter.stop()\n\n    connect_shell = as_zmqstream(KernelManager.connect_shell)\n    connect_iopub = as_zmqstream(KernelManager.connect_iopub)\n    connect_stdin = as_zmqstream(KernelManager.connect_stdin)\n    connect_hb = as_zmqstream(KernelManager.connect_hb)\n"
  },
  {
    "path": "lib/client/jupyter_client/ioloop/restarter.py",
    "content": "\"\"\"A basic in process kernel monitor with autorestarting.\n\nThis watches a kernel's state using KernelManager.is_alive and auto\nrestarts the kernel if it dies.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import absolute_import\nimport warnings\n\nfrom zmq.eventloop import ioloop\n\nfrom jupyter_client.restarter import KernelRestarter\nfrom traitlets import (\n    Instance,\n)\n\nclass IOLoopKernelRestarter(KernelRestarter):\n    \"\"\"Monitor and autorestart a kernel.\"\"\"\n\n    loop = Instance('tornado.ioloop.IOLoop')\n    def _loop_default(self):\n        warnings.warn(\"IOLoopKernelRestarter.loop is deprecated in jupyter-client 5.2\",\n            DeprecationWarning, stacklevel=4,\n        )\n        return ioloop.IOLoop.current()\n\n    _pcallback = None\n\n    def start(self):\n        \"\"\"Start the polling of the kernel.\"\"\"\n        if self._pcallback is None:\n            self._pcallback = ioloop.PeriodicCallback(\n                self.poll, 1000*self.time_to_dead,\n            )\n            self._pcallback.start()\n\n    def stop(self):\n        \"\"\"Stop the kernel polling.\"\"\"\n        if self._pcallback is not None:\n            self._pcallback.stop()\n            self._pcallback = None\n"
  },
  {
    "path": "lib/client/jupyter_client/jsonutil.py",
    "content": "# coding: utf-8\n\"\"\"Utilities to manipulate JSON objects.\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom datetime import datetime\nimport re\nimport warnings\n\nfrom dateutil.parser import parse as _dateutil_parse\nfrom dateutil.tz import tzlocal\n\nfrom ipython_genutils import py3compat\nfrom ipython_genutils.py3compat import string_types, iteritems\nnext_attr_name = '__next__' if py3compat.PY3 else 'next'\n\n#-----------------------------------------------------------------------------\n# Globals and constants\n#-----------------------------------------------------------------------------\n\n# timestamp formats\nISO8601 = \"%Y-%m-%dT%H:%M:%S.%f\"\nISO8601_PAT = re.compile(r\"^(\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2})(\\.\\d{1,6})?(Z|([\\+\\-]\\d{2}:?\\d{2}))?$\")\n\n# holy crap, strptime is not threadsafe.\n# Calling it once at import seems to help.\ndatetime.strptime(\"1\", \"%d\")\n\n#-----------------------------------------------------------------------------\n# Classes and functions\n#-----------------------------------------------------------------------------\n\ndef _ensure_tzinfo(dt):\n    \"\"\"Ensure a datetime object has tzinfo\n    \n    If no tzinfo is present, add tzlocal\n    \"\"\"\n    if not dt.tzinfo:\n        # No more naïve datetime objects!\n        warnings.warn(u\"Interpreting naive datetime as local %s. Please add timezone info to timestamps.\" % dt,\n            DeprecationWarning,\n            stacklevel=4)\n        dt = dt.replace(tzinfo=tzlocal())\n    return dt\n\ndef parse_date(s):\n    \"\"\"parse an ISO8601 date string\n    \n    If it is None or not a valid ISO8601 timestamp,\n    it will be returned unmodified.\n    Otherwise, it will return a datetime object.\n    \"\"\"\n    if s is None:\n        return s\n    m = ISO8601_PAT.match(s)\n    if m:\n        dt = _dateutil_parse(s)\n        return _ensure_tzinfo(dt)\n    return s\n\ndef extract_dates(obj):\n    \"\"\"extract ISO8601 dates from unpacked JSON\"\"\"\n    if isinstance(obj, dict):\n        new_obj = {} # don't clobber\n        for k,v in iteritems(obj):\n            new_obj[k] = extract_dates(v)\n        obj = new_obj\n    elif isinstance(obj, (list, tuple)):\n        obj = [ extract_dates(o) for o in obj ]\n    elif isinstance(obj, string_types):\n        obj = parse_date(obj)\n    return obj\n\ndef squash_dates(obj):\n    \"\"\"squash datetime objects into ISO8601 strings\"\"\"\n    if isinstance(obj, dict):\n        obj = dict(obj) # don't clobber\n        for k,v in iteritems(obj):\n            obj[k] = squash_dates(v)\n    elif isinstance(obj, (list, tuple)):\n        obj = [ squash_dates(o) for o in obj ]\n    elif isinstance(obj, datetime):\n        obj = obj.isoformat()\n    return obj\n\ndef date_default(obj):\n    \"\"\"default function for packing datetime objects in JSON.\"\"\"\n    if isinstance(obj, datetime):\n        obj = _ensure_tzinfo(obj)\n        return obj.isoformat().replace('+00:00', 'Z')\n    else:\n        raise TypeError(\"%r is not JSON serializable\" % obj)\n\n"
  },
  {
    "path": "lib/client/jupyter_client/kernelapp.py",
    "content": "import os\nimport signal\nimport uuid\n\nfrom jupyter_core.application import JupyterApp, base_flags\nfrom tornado.ioloop import IOLoop\nfrom traitlets import Unicode\n\nfrom . import __version__\nfrom .kernelspec import KernelSpecManager, NATIVE_KERNEL_NAME\nfrom .manager import KernelManager\n\nclass KernelApp(JupyterApp):\n    \"\"\"Launch a kernel by name in a local subprocess.\n    \"\"\"\n    version = __version__\n    description = \"Run a kernel locally in a subprocess\"\n\n    classes = [KernelManager, KernelSpecManager]\n\n    aliases = {\n        'kernel': 'KernelApp.kernel_name',\n        'ip': 'KernelManager.ip',\n    }\n    flags = {'debug': base_flags['debug']}\n\n    kernel_name = Unicode(NATIVE_KERNEL_NAME,\n        help = 'The name of a kernel type to start'\n    ).tag(config=True)\n\n    def initialize(self, argv=None):\n        super(KernelApp, self).initialize(argv)\n        self.km = KernelManager(kernel_name=self.kernel_name,\n                                config=self.config)\n        cf_basename = 'kernel-%s.json' % uuid.uuid4()\n        self.km.connection_file = os.path.join(self.runtime_dir, cf_basename)\n        self.loop = IOLoop.current()\n        self.loop.add_callback(self._record_started)\n\n    def setup_signals(self):\n        \"\"\"Shutdown on SIGTERM or SIGINT (Ctrl-C)\"\"\"\n        if os.name == 'nt':\n            return\n\n        def shutdown_handler(signo, frame):\n            self.loop.add_callback_from_signal(self.shutdown, signo)\n        for sig in [signal.SIGTERM, signal.SIGINT]:\n            signal.signal(sig, shutdown_handler)\n\n    def shutdown(self, signo):\n        self.log.info('Shutting down on signal %d' % signo)\n        self.km.shutdown_kernel()\n        self.loop.stop()\n\n    def log_connection_info(self):\n        cf = self.km.connection_file\n        self.log.info('Connection file: %s', cf)\n        self.log.info(\"To connect a client: --existing %s\", os.path.basename(cf))\n\n    def _record_started(self):\n        \"\"\"For tests, create a file to indicate that we've started\n\n        Do not rely on this except in our own tests!\n        \"\"\"\n        fn = os.environ.get('JUPYTER_CLIENT_TEST_RECORD_STARTUP_PRIVATE')\n        if fn is not None:\n            with open(fn, 'wb'):\n                pass\n\n    def start(self):\n        self.log.info('Starting kernel %r', self.kernel_name)\n        try:\n            self.km.start_kernel()\n            self.log_connection_info()\n            self.setup_signals()\n            self.loop.start()\n        finally:\n            self.km.cleanup()\n\n\nmain = KernelApp.launch_instance\n"
  },
  {
    "path": "lib/client/jupyter_client/kernelspec.py",
    "content": "\"\"\"Tools for managing kernel specs\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport errno\nimport io\nimport json\nimport os\nimport re\nimport shutil\nimport warnings\n\npjoin = os.path.join\n\nfrom ipython_genutils.py3compat import PY3\nfrom traitlets import (\n    HasTraits, List, Unicode, Dict, Set, Bool, Type, CaselessStrEnum\n)\nfrom traitlets.config import LoggingConfigurable\n\nfrom jupyter_core.paths import jupyter_data_dir, jupyter_path, SYSTEM_JUPYTER_PATH\n\n\nNATIVE_KERNEL_NAME = 'python3' if PY3 else 'python2'\n\n\nclass KernelSpec(HasTraits):\n    argv = List()\n    display_name = Unicode()\n    language = Unicode()\n    env = Dict()\n    resource_dir = Unicode()\n    interrupt_mode = CaselessStrEnum(\n        ['message', 'signal'], default_value='signal'\n    )\n    metadata = Dict()\n\n    @classmethod\n    def from_resource_dir(cls, resource_dir):\n        \"\"\"Create a KernelSpec object by reading kernel.json\n\n        Pass the path to the *directory* containing kernel.json.\n        \"\"\"\n        kernel_file = pjoin(resource_dir, 'kernel.json')\n        with io.open(kernel_file, 'r', encoding='utf-8') as f:\n            kernel_dict = json.load(f)\n        return cls(resource_dir=resource_dir, **kernel_dict)\n\n    def to_dict(self):\n        d = dict(argv=self.argv,\n                 env=self.env,\n                 display_name=self.display_name,\n                 language=self.language,\n                 interrupt_mode=self.interrupt_mode,\n                 metadata=self.metadata,\n                )\n\n        return d\n\n    def to_json(self):\n        \"\"\"Serialise this kernelspec to a JSON object.\n\n        Returns a string.\n        \"\"\"\n        return json.dumps(self.to_dict())\n\n\n_kernel_name_pat = re.compile(r'^[a-z0-9._\\-]+$', re.IGNORECASE)\n\ndef _is_valid_kernel_name(name):\n    \"\"\"Check that a kernel name is valid.\"\"\"\n    # quote is not unicode-safe on Python 2\n    return _kernel_name_pat.match(name)\n\n\n_kernel_name_description = \"Kernel names can only contain ASCII letters and numbers and these separators:\" \\\n \" - . _ (hyphen, period, and underscore).\"\n\n\ndef _is_kernel_dir(path):\n    \"\"\"Is ``path`` a kernel directory?\"\"\"\n    return os.path.isdir(path) and os.path.isfile(pjoin(path, 'kernel.json'))\n\n\ndef _list_kernels_in(dir):\n    \"\"\"Return a mapping of kernel names to resource directories from dir.\n\n    If dir is None or does not exist, returns an empty dict.\n    \"\"\"\n    if dir is None or not os.path.isdir(dir):\n        return {}\n    kernels = {}\n    for f in os.listdir(dir):\n        path = pjoin(dir, f)\n        if not _is_kernel_dir(path):\n            continue\n        key = f.lower()\n        if not _is_valid_kernel_name(key):\n            warnings.warn(\"Invalid kernelspec directory name (%s): %s\"\n                % (_kernel_name_description, path), stacklevel=3,\n            )\n        kernels[key] = path\n    return kernels\n\n\nclass NoSuchKernel(KeyError):\n    def __init__(self, name):\n        self.name = name\n\n    def __str__(self):\n        return \"No such kernel named {}\".format(self.name)\n\n\nclass KernelSpecManager(LoggingConfigurable):\n\n    kernel_spec_class = Type(KernelSpec, config=True,\n        help=\"\"\"The kernel spec class.  This is configurable to allow\n        subclassing of the KernelSpecManager for customized behavior.\n        \"\"\"\n    )\n\n    ensure_native_kernel = Bool(True, config=True,\n        help=\"\"\"If there is no Python kernelspec registered and the IPython\n        kernel is available, ensure it is added to the spec list.\n        \"\"\"\n    )\n\n    data_dir = Unicode()\n    def _data_dir_default(self):\n        return jupyter_data_dir()\n\n    user_kernel_dir = Unicode()\n    def _user_kernel_dir_default(self):\n        return pjoin(self.data_dir, 'kernels')\n\n    whitelist = Set(config=True,\n        help=\"\"\"Whitelist of allowed kernel names.\n\n        By default, all installed kernels are allowed.\n        \"\"\"\n    )\n    kernel_dirs = List(\n        help=\"List of kernel directories to search. Later ones take priority over earlier.\"\n    )\n    def _kernel_dirs_default(self):\n        dirs = jupyter_path('kernels')\n        # At some point, we should stop adding .ipython/kernels to the path,\n        # but the cost to keeping it is very small.\n        try:\n            from IPython.paths import get_ipython_dir\n        except ImportError:\n            try:\n                from IPython.utils.path import get_ipython_dir\n            except ImportError:\n                # no IPython, no ipython dir\n                get_ipython_dir = None\n        if get_ipython_dir is not None:\n            dirs.append(os.path.join(get_ipython_dir(), 'kernels'))\n        return dirs\n\n    def find_kernel_specs(self):\n        \"\"\"Returns a dict mapping kernel names to resource directories.\"\"\"\n        d = {}\n        for kernel_dir in self.kernel_dirs:\n            kernels = _list_kernels_in(kernel_dir)\n            for kname, spec in kernels.items():\n                if kname not in d:\n                    self.log.debug(\"Found kernel %s in %s\", kname, kernel_dir)\n                    d[kname] = spec\n\n        if self.ensure_native_kernel and NATIVE_KERNEL_NAME not in d:\n            try:\n                from ipykernel.kernelspec import RESOURCES\n                self.log.debug(\"Native kernel (%s) available from %s\",\n                               NATIVE_KERNEL_NAME, RESOURCES)\n                d[NATIVE_KERNEL_NAME] = RESOURCES\n            except ImportError:\n                self.log.warning(\"Native kernel (%s) is not available\", NATIVE_KERNEL_NAME)\n\n        if self.whitelist:\n            # filter if there's a whitelist\n            d = {name:spec for name,spec in d.items() if name in self.whitelist}\n        return d\n        # TODO: Caching?\n\n    def _get_kernel_spec_by_name(self, kernel_name, resource_dir):\n        \"\"\" Returns a :class:`KernelSpec` instance for a given kernel_name\n        and resource_dir.\n        \"\"\"\n        if kernel_name == NATIVE_KERNEL_NAME:\n            try:\n                from ipykernel.kernelspec import RESOURCES, get_kernel_dict\n            except ImportError:\n                # It should be impossible to reach this, but let's play it safe\n                pass\n            else:\n                if resource_dir == RESOURCES:\n                    return self.kernel_spec_class(resource_dir=resource_dir, **get_kernel_dict())\n\n        return self.kernel_spec_class.from_resource_dir(resource_dir)\n\n    def _find_spec_directory(self, kernel_name):\n        \"\"\"Find the resource directory of a named kernel spec\"\"\"\n        for kernel_dir in self.kernel_dirs:\n            try:\n                files = os.listdir(kernel_dir)\n            except OSError as e:\n                if e.errno in (errno.ENOTDIR, errno.ENOENT):\n                    continue\n                raise\n            for f in files:\n                path = pjoin(kernel_dir, f)\n                if f.lower() == kernel_name and _is_kernel_dir(path):\n                    return path\n\n        if kernel_name == NATIVE_KERNEL_NAME:\n            try:\n                from ipykernel.kernelspec import RESOURCES\n            except ImportError:\n                pass\n            else:\n                return RESOURCES\n\n    def get_kernel_spec(self, kernel_name):\n        \"\"\"Returns a :class:`KernelSpec` instance for the given kernel_name.\n\n        Raises :exc:`NoSuchKernel` if the given kernel name is not found.\n        \"\"\"\n        if not _is_valid_kernel_name(kernel_name):\n            self.log.warning(\"Kernelspec name %r is invalid: %s\", kernel_name,\n                             _kernel_name_description)\n\n        resource_dir = self._find_spec_directory(kernel_name.lower())\n        if resource_dir is None:\n            raise NoSuchKernel(kernel_name)\n\n        return self._get_kernel_spec_by_name(kernel_name, resource_dir)\n\n    def get_all_specs(self):\n        \"\"\"Returns a dict mapping kernel names to kernelspecs.\n\n        Returns a dict of the form::\n\n            {\n              'kernel_name': {\n                'resource_dir': '/path/to/kernel_name',\n                'spec': {\"the spec itself\": ...}\n              },\n              ...\n            }\n        \"\"\"\n        d = self.find_kernel_specs()\n        res = {}\n        for kname, resource_dir in d.items():\n            try:\n                if self.__class__ is KernelSpecManager:\n                    spec = self._get_kernel_spec_by_name(kname, resource_dir)\n                else:\n                    # avoid calling private methods in subclasses,\n                    # which may have overridden find_kernel_specs\n                    # and get_kernel_spec, but not the newer get_all_specs\n                    spec = self.get_kernel_spec(kname)\n\n                res[kname] = {\n                    \"resource_dir\": resource_dir,\n                    \"spec\": spec.to_dict()\n                }\n            except Exception:\n                self.log.warning(\"Error loading kernelspec %r\", kname, exc_info=True)\n        return res\n\n    def remove_kernel_spec(self, name):\n        \"\"\"Remove a kernel spec directory by name.\n\n        Returns the path that was deleted.\n        \"\"\"\n        save_native = self.ensure_native_kernel\n        try:\n            self.ensure_native_kernel = False\n            specs = self.find_kernel_specs()\n        finally:\n            self.ensure_native_kernel = save_native\n        spec_dir = specs[name]\n        self.log.debug(\"Removing %s\", spec_dir)\n        if os.path.islink(spec_dir):\n            os.remove(spec_dir)\n        else:\n            shutil.rmtree(spec_dir)\n        return spec_dir\n\n    def _get_destination_dir(self, kernel_name, user=False, prefix=None):\n        if user:\n            return os.path.join(self.user_kernel_dir, kernel_name)\n        elif prefix:\n            return os.path.join(os.path.abspath(prefix), 'share', 'jupyter', 'kernels', kernel_name)\n        else:\n            return os.path.join(SYSTEM_JUPYTER_PATH[0], 'kernels', kernel_name)\n\n\n    def install_kernel_spec(self, source_dir, kernel_name=None, user=False,\n                            replace=None, prefix=None):\n        \"\"\"Install a kernel spec by copying its directory.\n\n        If ``kernel_name`` is not given, the basename of ``source_dir`` will\n        be used.\n\n        If ``user`` is False, it will attempt to install into the systemwide\n        kernel registry. If the process does not have appropriate permissions,\n        an :exc:`OSError` will be raised.\n\n        If ``prefix`` is given, the kernelspec will be installed to\n        PREFIX/share/jupyter/kernels/KERNEL_NAME. This can be sys.prefix\n        for installation inside virtual or conda envs.\n        \"\"\"\n        source_dir = source_dir.rstrip('/\\\\')\n        if not kernel_name:\n            kernel_name = os.path.basename(source_dir)\n        kernel_name = kernel_name.lower()\n        if not _is_valid_kernel_name(kernel_name):\n            raise ValueError(\"Invalid kernel name %r.  %s\" % (kernel_name, _kernel_name_description))\n\n        if user and prefix:\n            raise ValueError(\"Can't specify both user and prefix. Please choose one or the other.\")\n\n        if replace is not None:\n            warnings.warn(\n                \"replace is ignored. Installing a kernelspec always replaces an existing installation\",\n                DeprecationWarning,\n                stacklevel=2,\n            )\n\n        destination = self._get_destination_dir(kernel_name, user=user, prefix=prefix)\n        self.log.debug('Installing kernelspec in %s', destination)\n\n        kernel_dir = os.path.dirname(destination)\n        if kernel_dir not in self.kernel_dirs:\n            self.log.warning(\"Installing to %s, which is not in %s. The kernelspec may not be found.\",\n                kernel_dir, self.kernel_dirs,\n            )\n\n        if os.path.isdir(destination):\n            self.log.info('Removing existing kernelspec in %s', destination)\n            shutil.rmtree(destination)\n\n        shutil.copytree(source_dir, destination)\n        self.log.info('Installed kernelspec %s in %s', kernel_name, destination)\n        return destination\n\n    def install_native_kernel_spec(self, user=False):\n        \"\"\"DEPRECATED: Use ipykernel.kenelspec.install\"\"\"\n        warnings.warn(\"install_native_kernel_spec is deprecated.\"\n            \" Use ipykernel.kernelspec import install.\", stacklevel=2)\n        from ipykernel.kernelspec import install\n        install(self, user=user)\n\n\ndef find_kernel_specs():\n    \"\"\"Returns a dict mapping kernel names to resource directories.\"\"\"\n    return KernelSpecManager().find_kernel_specs()\n\ndef get_kernel_spec(kernel_name):\n    \"\"\"Returns a :class:`KernelSpec` instance for the given kernel_name.\n\n    Raises KeyError if the given kernel name is not found.\n    \"\"\"\n    return KernelSpecManager().get_kernel_spec(kernel_name)\n\ndef install_kernel_spec(source_dir, kernel_name=None, user=False, replace=False,\n                        prefix=None):\n    return KernelSpecManager().install_kernel_spec(source_dir, kernel_name,\n                                                    user, replace, prefix)\n\ninstall_kernel_spec.__doc__ = KernelSpecManager.install_kernel_spec.__doc__\n\ndef install_native_kernel_spec(user=False):\n    return KernelSpecManager().install_native_kernel_spec(user=user)\n\ninstall_native_kernel_spec.__doc__ = KernelSpecManager.install_native_kernel_spec.__doc__\n"
  },
  {
    "path": "lib/client/jupyter_client/kernelspecapp.py",
    "content": "\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function\n\nimport errno\nimport os.path\nimport sys\nimport json\n\nfrom traitlets.config.application import Application\nfrom jupyter_core.application import (\n    JupyterApp, base_flags, base_aliases\n)\nfrom traitlets import Instance, Dict, Unicode, Bool, List\n\nfrom . import __version__\nfrom .kernelspec import KernelSpecManager\n\ntry:\n    raw_input\nexcept NameError:\n    # py3\n    raw_input = input\n\nclass ListKernelSpecs(JupyterApp):\n    version = __version__\n    description = \"\"\"List installed kernel specifications.\"\"\"\n    kernel_spec_manager = Instance(KernelSpecManager)\n    json_output = Bool(False, help='output spec name and location as machine-readable json.',\n            config=True)\n    \n    flags = {'json': ({'ListKernelSpecs': {'json_output': True}},\n                \"output spec name and location as machine-readable json.\"),\n             'debug': base_flags['debug'],\n            }\n\n    def _kernel_spec_manager_default(self):\n        return KernelSpecManager(parent=self, data_dir=self.data_dir)\n\n    def start(self):\n        paths = self.kernel_spec_manager.find_kernel_specs()\n        specs = self.kernel_spec_manager.get_all_specs()\n        if not self.json_output:\n            if not specs:\n                print(\"No kernels available\")\n                return\n            # pad to width of longest kernel name\n            name_len = len(sorted(paths, key=lambda name: len(name))[-1])\n\n            def path_key(item):\n                \"\"\"sort key function for Jupyter path priority\"\"\"\n                path = item[1]\n                for idx, prefix in enumerate(self.jupyter_path):\n                    if path.startswith(prefix):\n                        return (idx, path)\n                # not in jupyter path, artificially added to the front\n                return (-1, path)\n\n            print(\"Available kernels:\")\n            for kernelname, path in sorted(paths.items(), key=path_key):\n                print(\"  %s    %s\" % (kernelname.ljust(name_len), path))\n        else:\n            print(json.dumps({\n                'kernelspecs': specs\n            }, indent=2))\n\n\n\nclass InstallKernelSpec(JupyterApp):\n    version = __version__\n    description = \"\"\"Install a kernel specification directory.\n    \n    Given a SOURCE DIRECTORY containing a kernel spec,\n    jupyter will copy that directory into one of the Jupyter kernel directories.\n    The default is to install kernelspecs for all users.\n    `--user` can be specified to install a kernel only for the current user.\n    \"\"\"\n    examples = \"\"\"\n    jupyter kernelspec install /path/to/my_kernel --user\n    \"\"\"\n    usage = \"jupyter kernelspec install SOURCE_DIR [--options]\"\n    kernel_spec_manager = Instance(KernelSpecManager)\n\n    def _kernel_spec_manager_default(self):\n        return KernelSpecManager(data_dir=self.data_dir)\n\n    sourcedir = Unicode()\n    kernel_name = Unicode(\"\", config=True,\n        help=\"Install the kernel spec with this name\"\n    )\n    def _kernel_name_default(self):\n        return os.path.basename(self.sourcedir)\n\n    user = Bool(False, config=True,\n        help=\"\"\"\n        Try to install the kernel spec to the per-user directory instead of\n        the system or environment directory.\n        \"\"\"\n    )\n    prefix = Unicode('', config=True,\n        help=\"\"\"Specify a prefix to install to, e.g. an env.\n        The kernelspec will be installed in PREFIX/share/jupyter/kernels/\n        \"\"\"\n    )\n    replace = Bool(False, config=True,\n        help=\"Replace any existing kernel spec with this name.\"\n    )\n\n    aliases = {\n        'name': 'InstallKernelSpec.kernel_name',\n        'prefix': 'InstallKernelSpec.prefix',\n    }\n    aliases.update(base_aliases)\n\n    flags = {'user': ({'InstallKernelSpec': {'user': True}},\n                \"Install to the per-user kernel registry\"),\n             'replace': ({'InstallKernelSpec': {'replace': True}},\n                \"Replace any existing kernel spec with this name.\"),\n             'sys-prefix': ({'InstallKernelSpec': {'prefix': sys.prefix}},\n                \"Install to Python's sys.prefix. Useful in conda/virtual environments.\"),\n             'debug': base_flags['debug'],\n            }\n\n    def parse_command_line(self, argv):\n        super(InstallKernelSpec, self).parse_command_line(argv)\n        # accept positional arg as profile name\n        if self.extra_args:\n            self.sourcedir = self.extra_args[0]\n        else:\n            print(\"No source directory specified.\")\n            self.exit(1)\n\n    def start(self):\n        if self.user and self.prefix:\n            self.exit(\"Can't specify both user and prefix. Please choose one or the other.\")\n        try:\n            self.kernel_spec_manager.install_kernel_spec(self.sourcedir,\n                                                 kernel_name=self.kernel_name,\n                                                 user=self.user,\n                                                 prefix=self.prefix,\n                                                 replace=self.replace,\n                                                )\n        except OSError as e:\n            if e.errno == errno.EACCES:\n                print(e, file=sys.stderr)\n                if not self.user:\n                    print(\"Perhaps you want to install with `sudo` or `--user`?\", file=sys.stderr)\n                self.exit(1)\n            elif e.errno == errno.EEXIST:\n                print(\"A kernel spec is already present at %s\" % e.filename, file=sys.stderr)\n                self.exit(1)\n            raise\n\nclass RemoveKernelSpec(JupyterApp):\n    version = __version__\n    description = \"\"\"Remove one or more Jupyter kernelspecs by name.\"\"\"\n    examples = \"\"\"jupyter kernelspec remove python2 [my_kernel ...]\"\"\"\n    \n    force = Bool(False, config=True,\n        help=\"\"\"Force removal, don't prompt for confirmation.\"\"\"\n    )\n    spec_names = List(Unicode())\n    \n    kernel_spec_manager = Instance(KernelSpecManager)\n    def _kernel_spec_manager_default(self):\n        return KernelSpecManager(data_dir=self.data_dir, parent=self)\n    \n    flags = {\n        'f': ({'RemoveKernelSpec': {'force': True}}, force.get_metadata('help')),\n    }\n    flags.update(JupyterApp.flags)\n    \n    def parse_command_line(self, argv):\n        super(RemoveKernelSpec, self).parse_command_line(argv)\n        # accept positional arg as profile name\n        if self.extra_args:\n            self.spec_names = sorted(set(self.extra_args)) # remove duplicates\n        else:\n            self.exit(\"No kernelspec specified.\")\n    \n    def start(self):\n        self.kernel_spec_manager.ensure_native_kernel = False\n        spec_paths = self.kernel_spec_manager.find_kernel_specs()\n        missing = set(self.spec_names).difference(set(spec_paths))\n        if missing:\n            self.exit(\"Couldn't find kernel spec(s): %s\" % ', '.join(missing))\n        \n        if not self.force:\n            print(\"Kernel specs to remove:\")\n            for name in self.spec_names:\n                print(\"  %s\\t%s\" % (name.ljust(20), spec_paths[name]))\n            answer = raw_input(\"Remove %i kernel specs [y/N]: \" % len(self.spec_names))\n            if not answer.lower().startswith('y'):\n                return\n        \n        for kernel_name in self.spec_names:\n            try:\n                path = self.kernel_spec_manager.remove_kernel_spec(kernel_name)\n            except OSError as e:\n                if e.errno == errno.EACCES:\n                    print(e, file=sys.stderr)\n                    print(\"Perhaps you want sudo?\", file=sys.stderr)\n                    self.exit(1)\n                else:\n                    raise\n            self.log.info(\"Removed %s\", path)\n\n\nclass InstallNativeKernelSpec(JupyterApp):\n    version = __version__\n    description = \"\"\"[DEPRECATED] Install the IPython kernel spec directory for this Python.\"\"\"\n    kernel_spec_manager = Instance(KernelSpecManager)\n\n    def _kernel_spec_manager_default(self):\n        return KernelSpecManager(data_dir=self.data_dir)\n\n    user = Bool(False, config=True,\n        help=\"\"\"\n        Try to install the kernel spec to the per-user directory instead of\n        the system or environment directory.\n        \"\"\"\n    )\n\n    flags = {'user': ({'InstallNativeKernelSpec': {'user': True}},\n                \"Install to the per-user kernel registry\"),\n             'debug': base_flags['debug'],\n            }\n\n    def start(self):\n        self.log.warning(\"`jupyter kernelspec install-self` is DEPRECATED as of 4.0.\"\n            \" You probably want `ipython kernel install` to install the IPython kernelspec.\")\n        try:\n            from ipykernel import kernelspec\n        except ImportError:\n            print(\"ipykernel not available, can't install its spec.\", file=sys.stderr)\n            self.exit(1)\n        try:\n            kernelspec.install(self.kernel_spec_manager, user=self.user)\n        except OSError as e:\n            if e.errno == errno.EACCES:\n                print(e, file=sys.stderr)\n                if not self.user:\n                    print(\"Perhaps you want to install with `sudo` or `--user`?\", file=sys.stderr)\n                self.exit(1)\n            self.exit(e)\n\nclass KernelSpecApp(Application):\n    version = __version__\n    name = \"jupyter kernelspec\"\n    description = \"\"\"Manage Jupyter kernel specifications.\"\"\"\n\n    subcommands = Dict({\n        'list': (ListKernelSpecs, ListKernelSpecs.description.splitlines()[0]),\n        'install': (InstallKernelSpec, InstallKernelSpec.description.splitlines()[0]),\n        'uninstall': (RemoveKernelSpec, \"Alias for remove\"),\n        'remove': (RemoveKernelSpec, RemoveKernelSpec.description.splitlines()[0]),\n        'install-self': (InstallNativeKernelSpec, InstallNativeKernelSpec.description.splitlines()[0]),\n    })\n\n    aliases = {}\n    flags = {}\n\n    def start(self):\n        if self.subapp is None:\n            print(\"No subcommand specified. Must specify one of: %s\"% list(self.subcommands))\n            print()\n            self.print_description()\n            self.print_subcommands()\n            self.exit(1)\n        else:\n            return self.subapp.start()\n\n\nif __name__ == '__main__':\n    KernelSpecApp.launch_instance()\n"
  },
  {
    "path": "lib/client/jupyter_client/launcher.py",
    "content": "\"\"\"Utilities for launching kernels\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport os\nimport sys\nfrom subprocess import Popen, PIPE\n\nfrom ipython_genutils.encoding import getdefaultencoding\nfrom ipython_genutils.py3compat import cast_bytes_py2, PY3\nfrom traitlets.log import get_logger\n\n\ndef launch_kernel(cmd, stdin=None, stdout=None, stderr=None, env=None,\n                  independent=False, cwd=None, **kw):\n    \"\"\" Launches a localhost kernel, binding to the specified ports.\n\n    Parameters\n    ----------\n    cmd : Popen list,\n        A string of Python code that imports and executes a kernel entry point.\n\n    stdin, stdout, stderr : optional (default None)\n        Standards streams, as defined in subprocess.Popen.\n\n    env: dict, optional\n        Environment variables passed to the kernel\n\n    independent : bool, optional (default False)\n        If set, the kernel process is guaranteed to survive if this process\n        dies. If not set, an effort is made to ensure that the kernel is killed\n        when this process dies. Note that in this case it is still good practice\n        to kill kernels manually before exiting.\n\n    cwd : path, optional\n        The working dir of the kernel process (default: cwd of this process).\n\n    **kw: optional\n        Additional arguments for Popen\n\n    Returns\n    -------\n\n    Popen instance for the kernel subprocess\n    \"\"\"\n\n    # Popen will fail (sometimes with a deadlock) if stdin, stdout, and stderr\n    # are invalid. Unfortunately, there is in general no way to detect whether\n    # they are valid.  The following two blocks redirect them to (temporary)\n    # pipes in certain important cases.\n\n    # If this process has been backgrounded, our stdin is invalid. Since there\n    # is no compelling reason for the kernel to inherit our stdin anyway, we'll\n    # place this one safe and always redirect.\n    redirect_in = True\n    _stdin = PIPE if stdin is None else stdin\n\n    # If this process in running on pythonw, we know that stdin, stdout, and\n    # stderr are all invalid.\n    redirect_out = sys.executable.endswith('pythonw.exe')\n    if redirect_out:\n        blackhole = open(os.devnull, 'w')\n        _stdout = blackhole if stdout is None else stdout\n        _stderr = blackhole if stderr is None else stderr\n    else:\n        _stdout, _stderr = stdout, stderr\n\n    env = env if (env is not None) else os.environ.copy()\n\n    encoding = getdefaultencoding(prefer_stream=False)\n    kwargs = kw.copy()\n    main_args = dict(\n        stdin=_stdin,\n        stdout=_stdout,\n        stderr=_stderr,\n        cwd=cwd,\n        env=env,\n    )\n    kwargs.update(main_args)\n\n    # Spawn a kernel.\n    if sys.platform == 'win32':\n        # Popen on Python 2 on Windows cannot handle unicode args or cwd\n        cmd = [ cast_bytes_py2(c, encoding) for c in cmd ]\n        if cwd:\n            cwd = cast_bytes_py2(cwd, sys.getfilesystemencoding() or 'ascii')\n            kwargs['cwd'] = cwd\n\n        from .win_interrupt import create_interrupt_event\n        # Create a Win32 event for interrupting the kernel\n        # and store it in an environment variable.\n        interrupt_event = create_interrupt_event()\n        env[\"JPY_INTERRUPT_EVENT\"] = str(interrupt_event)\n        # deprecated old env name:\n        env[\"IPY_INTERRUPT_EVENT\"] = env[\"JPY_INTERRUPT_EVENT\"]\n\n        try:\n            from _winapi import DuplicateHandle, GetCurrentProcess, \\\n                DUPLICATE_SAME_ACCESS, CREATE_NEW_PROCESS_GROUP\n        except:\n            from _subprocess import DuplicateHandle, GetCurrentProcess, \\\n                DUPLICATE_SAME_ACCESS, CREATE_NEW_PROCESS_GROUP\n\n        # create a handle on the parent to be inherited\n        if independent:\n            kwargs['creationflags'] = CREATE_NEW_PROCESS_GROUP\n        else:\n            pid = GetCurrentProcess()\n            handle = DuplicateHandle(pid, pid, pid, 0,\n                                     True, # Inheritable by new processes.\n                                     DUPLICATE_SAME_ACCESS)\n            env['JPY_PARENT_PID'] = str(int(handle))\n\n        # Prevent creating new console window on pythonw\n        if redirect_out:\n            kwargs['creationflags'] = kwargs.setdefault('creationflags', 0) | 0x08000000 # CREATE_NO_WINDOW\n\n        # Avoid closing the above parent and interrupt handles.\n        # close_fds is True by default on Python >=3.7\n        # or when no stream is captured on Python <3.7\n        # (we always capture stdin, so this is already False by default on <3.7)\n        kwargs['close_fds'] = False\n    else:\n        # Create a new session.\n        # This makes it easier to interrupt the kernel,\n        # because we want to interrupt the whole process group.\n        # We don't use setpgrp, which is known to cause problems for kernels starting\n        # certain interactive subprocesses, such as bash -i.\n        if PY3:\n            kwargs['start_new_session'] = True\n        else:\n            kwargs['preexec_fn'] = lambda: os.setsid()\n        if not independent:\n            env['JPY_PARENT_PID'] = str(os.getpid())\n\n    try:\n        proc = Popen(cmd, **kwargs)\n    except Exception as exc:\n        msg = (\n            \"Failed to run command:\\n{}\\n\"\n            \"    PATH={!r}\\n\"\n            \"    with kwargs:\\n{!r}\\n\"\n        )\n        # exclude environment variables,\n        # which may contain access tokens and the like.\n        without_env = {key:value for key, value in kwargs.items() if key != 'env'}\n        msg = msg.format(cmd, env.get('PATH', os.defpath), without_env)\n        get_logger().error(msg)\n        raise\n\n    if sys.platform == 'win32':\n        # Attach the interrupt event to the Popen objet so it can be used later.\n        proc.win32_interrupt_event = interrupt_event\n\n    # Clean up pipes created to work around Popen bug.\n    if redirect_in:\n        if stdin is None:\n            proc.stdin.close()\n\n    return proc\n\n__all__ = [\n    'launch_kernel',\n]\n"
  },
  {
    "path": "lib/client/jupyter_client/localinterfaces.py",
    "content": "\"\"\"Utilities for identifying local IP addresses.\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport os\nimport re\nimport socket\nimport subprocess\nfrom subprocess import Popen, PIPE\n\nfrom warnings import warn\n\n\nLOCAL_IPS = []\nPUBLIC_IPS = []\n\nLOCALHOST = ''\n\n\ndef _uniq_stable(elems):\n    \"\"\"uniq_stable(elems) -> list\n\n    Return from an iterable, a list of all the unique elements in the input,\n    maintaining the order in which they first appear.\n    \n    From ipython_genutils.data\n    \"\"\"\n    seen = set()\n    return [x for x in elems if x not in seen and not seen.add(x)]\n\ndef _get_output(cmd):\n    \"\"\"Get output of a command, raising IOError if it fails\"\"\"\n    startupinfo = None\n    if os.name == 'nt':\n        startupinfo = subprocess.STARTUPINFO()\n        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW\n    p = Popen(cmd, stdout=PIPE, stderr=PIPE, startupinfo=startupinfo)\n    stdout, stderr = p.communicate()\n    if p.returncode:\n        raise IOError(\"Failed to run %s: %s\" % (cmd, stderr.decode('utf8', 'replace')))\n    return stdout.decode('utf8', 'replace')\n\ndef _only_once(f):\n    \"\"\"decorator to only run a function once\"\"\"\n    f.called = False\n    def wrapped(**kwargs):\n        if f.called:\n            return\n        ret = f(**kwargs)\n        f.called = True\n        return ret\n    return wrapped\n\ndef _requires_ips(f):\n    \"\"\"decorator to ensure load_ips has been run before f\"\"\"\n    def ips_loaded(*args, **kwargs):\n        _load_ips()\n        return f(*args, **kwargs)\n    return ips_loaded\n\n# subprocess-parsing ip finders\nclass NoIPAddresses(Exception):\n    pass\n\ndef _populate_from_list(addrs):\n    \"\"\"populate local and public IPs from flat list of all IPs\"\"\"\n    if not addrs:\n        raise NoIPAddresses\n    \n    global LOCALHOST\n    public_ips = []\n    local_ips = []\n    \n    for ip in addrs:\n        local_ips.append(ip)\n        if not ip.startswith('127.'):\n            public_ips.append(ip)\n        elif not LOCALHOST:\n            LOCALHOST = ip\n    \n    if not LOCALHOST:\n        LOCALHOST = '127.0.0.1'\n        local_ips.insert(0, LOCALHOST)\n        \n    local_ips.extend(['0.0.0.0', ''])\n    \n    LOCAL_IPS[:] = _uniq_stable(local_ips)\n    PUBLIC_IPS[:] = _uniq_stable(public_ips)\n\n_ifconfig_ipv4_pat = re.compile(r'inet\\b.*?(\\d+\\.\\d+\\.\\d+\\.\\d+)', re.IGNORECASE)\n\ndef _load_ips_ifconfig():\n    \"\"\"load ip addresses from `ifconfig` output (posix)\"\"\"\n    \n    try:\n        out = _get_output('ifconfig')\n    except (IOError, OSError):\n        # no ifconfig, it's usually in /sbin and /sbin is not on everyone's PATH\n        out = _get_output('/sbin/ifconfig')\n    \n    lines = out.splitlines()\n    addrs = []\n    for line in lines:\n        m = _ifconfig_ipv4_pat.match(line.strip())\n        if m:\n            addrs.append(m.group(1))\n    _populate_from_list(addrs)\n\n\ndef _load_ips_ip():\n    \"\"\"load ip addresses from `ip addr` output (Linux)\"\"\"\n    out = _get_output(['ip', '-f', 'inet', 'addr'])\n    \n    lines = out.splitlines()\n    addrs = []\n    for line in lines:\n        blocks = line.lower().split()\n        if (len(blocks) >= 2) and (blocks[0] == 'inet'):\n            addrs.append(blocks[1].split('/')[0])\n    _populate_from_list(addrs)\n\n_ipconfig_ipv4_pat = re.compile(r'ipv4.*?(\\d+\\.\\d+\\.\\d+\\.\\d+)$', re.IGNORECASE)\n\ndef _load_ips_ipconfig():\n    \"\"\"load ip addresses from `ipconfig` output (Windows)\"\"\"\n    out = _get_output('ipconfig')\n    \n    lines = out.splitlines()\n    addrs = []\n    for line in lines:\n        m = _ipconfig_ipv4_pat.match(line.strip())\n        if m:\n            addrs.append(m.group(1))\n    _populate_from_list(addrs)\n\n\ndef _load_ips_netifaces():\n    \"\"\"load ip addresses with netifaces\"\"\"\n    import netifaces\n    global LOCALHOST\n    local_ips = []\n    public_ips = []\n    \n    # list of iface names, 'lo0', 'eth0', etc.\n    for iface in netifaces.interfaces():\n        # list of ipv4 addrinfo dicts\n        ipv4s = netifaces.ifaddresses(iface).get(netifaces.AF_INET, [])\n        for entry in ipv4s:\n            addr = entry.get('addr')\n            if not addr:\n                continue\n            if not (iface.startswith('lo') or addr.startswith('127.')):\n                public_ips.append(addr)\n            elif not LOCALHOST:\n                LOCALHOST = addr\n            local_ips.append(addr)\n    if not LOCALHOST:\n        # we never found a loopback interface (can this ever happen?), assume common default\n        LOCALHOST = '127.0.0.1'\n        local_ips.insert(0, LOCALHOST)\n    local_ips.extend(['0.0.0.0', ''])\n    LOCAL_IPS[:] = _uniq_stable(local_ips)\n    PUBLIC_IPS[:] = _uniq_stable(public_ips)\n\n\ndef _load_ips_gethostbyname():\n    \"\"\"load ip addresses with socket.gethostbyname_ex\n    \n    This can be slow.\n    \"\"\"\n    global LOCALHOST\n    try:\n        LOCAL_IPS[:] = socket.gethostbyname_ex('localhost')[2]\n    except socket.error:\n        # assume common default\n        LOCAL_IPS[:] = ['127.0.0.1']\n    \n    try:\n        hostname = socket.gethostname()\n        PUBLIC_IPS[:] = socket.gethostbyname_ex(hostname)[2]\n        # try hostname.local, in case hostname has been short-circuited to loopback\n        if not hostname.endswith('.local') and all(ip.startswith('127') for ip in PUBLIC_IPS):\n            PUBLIC_IPS[:] = socket.gethostbyname_ex(socket.gethostname() + '.local')[2]\n    except socket.error:\n        pass\n    finally:\n        PUBLIC_IPS[:] = _uniq_stable(PUBLIC_IPS)\n        LOCAL_IPS.extend(PUBLIC_IPS)\n    \n    # include all-interface aliases: 0.0.0.0 and ''\n    LOCAL_IPS.extend(['0.0.0.0', ''])\n\n    LOCAL_IPS[:] = _uniq_stable(LOCAL_IPS)\n\n    LOCALHOST = LOCAL_IPS[0]\n\ndef _load_ips_dumb():\n    \"\"\"Fallback in case of unexpected failure\"\"\"\n    global LOCALHOST\n    LOCALHOST = '127.0.0.1'\n    LOCAL_IPS[:] = [LOCALHOST, '0.0.0.0', '']\n    PUBLIC_IPS[:] = []\n\n@_only_once\ndef _load_ips(suppress_exceptions=True):\n    \"\"\"load the IPs that point to this machine\n    \n    This function will only ever be called once.\n    \n    It will use netifaces to do it quickly if available.\n    Then it will fallback on parsing the output of ifconfig / ip addr / ipconfig, as appropriate.\n    Finally, it will fallback on socket.gethostbyname_ex, which can be slow.\n    \"\"\"\n    \n    try:\n        # first priority, use netifaces\n        try:\n            return _load_ips_netifaces()\n        except ImportError:\n            pass\n        \n        # second priority, parse subprocess output (how reliable is this?)\n        \n        if os.name == 'nt':\n            try:\n                return _load_ips_ipconfig()\n            except (IOError, NoIPAddresses):\n                pass\n        else:\n            try:\n                return _load_ips_ip()\n            except (IOError, OSError, NoIPAddresses):\n                pass\n            try:\n                return _load_ips_ifconfig()\n            except (IOError, OSError, NoIPAddresses):\n                pass\n        \n        # lowest priority, use gethostbyname\n        \n        return _load_ips_gethostbyname()\n    except Exception as e:\n        if not suppress_exceptions:\n            raise\n        # unexpected error shouldn't crash, load dumb default values instead.\n        warn(\"Unexpected error discovering local network interfaces: %s\" % e)\n    _load_ips_dumb()\n\n\n@_requires_ips\ndef local_ips():\n    \"\"\"return the IP addresses that point to this machine\"\"\"\n    return LOCAL_IPS\n\n@_requires_ips\ndef public_ips():\n    \"\"\"return the IP addresses for this machine that are visible to other machines\"\"\"\n    return PUBLIC_IPS\n\n@_requires_ips\ndef localhost():\n    \"\"\"return ip for localhost (almost always 127.0.0.1)\"\"\"\n    return LOCALHOST\n\n@_requires_ips\ndef is_local_ip(ip):\n    \"\"\"does `ip` point to this machine?\"\"\"\n    return ip in LOCAL_IPS\n\n@_requires_ips\ndef is_public_ip(ip):\n    \"\"\"is `ip` a publicly visible address?\"\"\"\n    return ip in PUBLIC_IPS\n"
  },
  {
    "path": "lib/client/jupyter_client/manager.py",
    "content": "\"\"\"Base class to manage a running kernel\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import absolute_import\n\nfrom contextlib import contextmanager\nimport os\nimport re\nimport signal\nimport sys\nimport time\nimport warnings\n\nimport zmq\n\nfrom ipython_genutils.importstring import import_item\nfrom .localinterfaces import is_local_ip, local_ips\nfrom traitlets import (\n    Any, Float, Instance, Unicode, List, Bool, Type, DottedObjectName\n)\nfrom jupyter_client import (\n    launch_kernel,\n    kernelspec,\n)\nfrom .connect import ConnectionFileMixin\nfrom .managerabc import (\n    KernelManagerABC\n)\n\n\nclass KernelManager(ConnectionFileMixin):\n    \"\"\"Manages a single kernel in a subprocess on this host.\n\n    This version starts kernels with Popen.\n    \"\"\"\n\n    # The PyZMQ Context to use for communication with the kernel.\n    context = Instance(zmq.Context)\n    def _context_default(self):\n        return zmq.Context.instance()\n\n    # the class to create with our `client` method\n    client_class = DottedObjectName('jupyter_client.blocking.BlockingKernelClient')\n    client_factory = Type(klass='jupyter_client.KernelClient')\n    def _client_factory_default(self):\n        return import_item(self.client_class)\n\n    def _client_class_changed(self, name, old, new):\n        self.client_factory = import_item(str(new))\n\n    # The kernel process with which the KernelManager is communicating.\n    # generally a Popen instance\n    kernel = Any()\n\n    kernel_spec_manager = Instance(kernelspec.KernelSpecManager)\n\n    def _kernel_spec_manager_default(self):\n        return kernelspec.KernelSpecManager(data_dir=self.data_dir)\n\n    def _kernel_spec_manager_changed(self):\n        self._kernel_spec = None\n\n    shutdown_wait_time = Float(\n        5.0, config=True,\n        help=\"Time to wait for a kernel to terminate before killing it, \"\n             \"in seconds.\")\n\n    kernel_name = Unicode(kernelspec.NATIVE_KERNEL_NAME)\n\n    def _kernel_name_changed(self, name, old, new):\n        self._kernel_spec = None\n        if new == 'python':\n            self.kernel_name = kernelspec.NATIVE_KERNEL_NAME\n\n    _kernel_spec = None\n\n    @property\n    def kernel_spec(self):\n        if self._kernel_spec is None and self.kernel_name != '':\n            self._kernel_spec = self.kernel_spec_manager.get_kernel_spec(self.kernel_name)\n        return self._kernel_spec\n\n    kernel_cmd = List(Unicode(), config=True,\n        help=\"\"\"DEPRECATED: Use kernel_name instead.\n\n        The Popen Command to launch the kernel.\n        Override this if you have a custom kernel.\n        If kernel_cmd is specified in a configuration file,\n        Jupyter does not pass any arguments to the kernel,\n        because it cannot make any assumptions about the\n        arguments that the kernel understands. In particular,\n        this means that the kernel does not receive the\n        option --debug if it given on the Jupyter command line.\n        \"\"\"\n    )\n\n    def _kernel_cmd_changed(self, name, old, new):\n        warnings.warn(\"Setting kernel_cmd is deprecated, use kernel_spec to \"\n                      \"start different kernels.\")\n\n    @property\n    def ipykernel(self):\n        return self.kernel_name in {'python', 'python2', 'python3'}\n\n    # Protected traits\n    _launch_args = Any()\n    _control_socket = Any()\n\n    _restarter = Any()\n\n    autorestart = Bool(True, config=True,\n        help=\"\"\"Should we autorestart the kernel if it dies.\"\"\"\n    )\n\n    def __del__(self):\n        self._close_control_socket()\n        self.cleanup_connection_file()\n\n    #--------------------------------------------------------------------------\n    # Kernel restarter\n    #--------------------------------------------------------------------------\n\n    def start_restarter(self):\n        pass\n\n    def stop_restarter(self):\n        pass\n\n    def add_restart_callback(self, callback, event='restart'):\n        \"\"\"register a callback to be called when a kernel is restarted\"\"\"\n        if self._restarter is None:\n            return\n        self._restarter.add_callback(callback, event)\n\n    def remove_restart_callback(self, callback, event='restart'):\n        \"\"\"unregister a callback to be called when a kernel is restarted\"\"\"\n        if self._restarter is None:\n            return\n        self._restarter.remove_callback(callback, event)\n\n    #--------------------------------------------------------------------------\n    # create a Client connected to our Kernel\n    #--------------------------------------------------------------------------\n\n    def client(self, **kwargs):\n        \"\"\"Create a client configured to connect to our kernel\"\"\"\n        kw = {}\n        kw.update(self.get_connection_info(session=True))\n        kw.update(dict(\n            connection_file=self.connection_file,\n            parent=self,\n        ))\n\n        # add kwargs last, for manual overrides\n        kw.update(kwargs)\n        return self.client_factory(**kw)\n\n    #--------------------------------------------------------------------------\n    # Kernel management\n    #--------------------------------------------------------------------------\n\n    def format_kernel_cmd(self, extra_arguments=None):\n        \"\"\"replace templated args (e.g. {connection_file})\"\"\"\n        extra_arguments = extra_arguments or []\n        if self.kernel_cmd:\n            cmd = self.kernel_cmd + extra_arguments\n        else:\n            cmd = self.kernel_spec.argv + extra_arguments\n\n        if cmd and cmd[0] in {'python',\n                              'python%i' % sys.version_info[0],\n                              'python%i.%i' % sys.version_info[:2]}:\n            # executable is 'python' or 'python3', use sys.executable.\n            # These will typically be the same,\n            # but if the current process is in an env\n            # and has been launched by abspath without\n            # activating the env, python on PATH may not be sys.executable,\n            # but it should be.\n            cmd[0] = sys.executable\n\n        ns = dict(connection_file=self.connection_file,\n                  prefix=sys.prefix,\n                 )\n\n        if self.kernel_spec:\n            ns[\"resource_dir\"] = self.kernel_spec.resource_dir\n\n        ns.update(self._launch_args)\n\n        pat = re.compile(r'\\{([A-Za-z0-9_]+)\\}')\n        def from_ns(match):\n            \"\"\"Get the key out of ns if it's there, otherwise no change.\"\"\"\n            return ns.get(match.group(1), match.group())\n\n        return [ pat.sub(from_ns, arg) for arg in cmd ]\n\n    def _launch_kernel(self, kernel_cmd, **kw):\n        \"\"\"actually launch the kernel\n\n        override in a subclass to launch kernel subprocesses differently\n        \"\"\"\n        return launch_kernel(kernel_cmd, **kw)\n\n    # Control socket used for polite kernel shutdown\n\n    def _connect_control_socket(self):\n        if self._control_socket is None:\n            self._control_socket = self.connect_control()\n            self._control_socket.linger = 100\n\n    def _close_control_socket(self):\n        if self._control_socket is None:\n            return\n        self._control_socket.close()\n        self._control_socket = None\n\n    def start_kernel(self, **kw):\n        \"\"\"Starts a kernel on this host in a separate process.\n\n        If random ports (port=0) are being used, this method must be called\n        before the channels are created.\n\n        Parameters\n        ----------\n        `**kw` : optional\n             keyword arguments that are passed down to build the kernel_cmd\n             and launching the kernel (e.g. Popen kwargs).\n        \"\"\"\n        if self.transport == 'tcp' and not is_local_ip(self.ip):\n            raise RuntimeError(\"Can only launch a kernel on a local interface. \"\n                               \"This one is not: %s.\"\n                               \"Make sure that the '*_address' attributes are \"\n                               \"configured properly. \"\n                               \"Currently valid addresses are: %s\" % (self.ip, local_ips())\n                               )\n\n        # write connection file / get default ports\n        self.write_connection_file()\n\n        # save kwargs for use in restart\n        self._launch_args = kw.copy()\n        # build the Popen cmd\n        extra_arguments = kw.pop('extra_arguments', [])\n        kernel_cmd = self.format_kernel_cmd(extra_arguments=extra_arguments)\n        env = kw.pop('env', os.environ).copy()\n        # Don't allow PYTHONEXECUTABLE to be passed to kernel process.\n        # If set, it can bork all the things.\n        env.pop('PYTHONEXECUTABLE', None)\n        if not self.kernel_cmd:\n            # If kernel_cmd has been set manually, don't refer to a kernel spec\n            # Environment variables from kernel spec are added to os.environ\n            env.update(self.kernel_spec.env or {})\n\n        # launch the kernel subprocess\n        self.log.debug(\"Starting kernel: %s\", kernel_cmd)\n        self.kernel = self._launch_kernel(kernel_cmd, env=env,\n                                    **kw)\n        self.start_restarter()\n        self._connect_control_socket()\n\n    def request_shutdown(self, restart=False):\n        \"\"\"Send a shutdown request via control channel\n        \"\"\"\n        content = dict(restart=restart)\n        msg = self.session.msg(\"shutdown_request\", content=content)\n        # ensure control socket is connected\n        self._connect_control_socket()\n        self.session.send(self._control_socket, msg)\n\n    def finish_shutdown(self, waittime=None, pollinterval=0.1):\n        \"\"\"Wait for kernel shutdown, then kill process if it doesn't shutdown.\n\n        This does not send shutdown requests - use :meth:`request_shutdown`\n        first.\n        \"\"\"\n        if waittime is None:\n            waittime = max(self.shutdown_wait_time, 0)\n        for i in range(int(waittime/pollinterval)):\n            if self.is_alive():\n                time.sleep(pollinterval)\n            else:\n                break\n        else:\n            # OK, we've waited long enough.\n            if self.has_kernel:\n                self.log.debug(\"Kernel is taking too long to finish, killing\")\n                self._kill_kernel()\n\n    def cleanup(self, connection_file=True):\n        \"\"\"Clean up resources when the kernel is shut down\"\"\"\n        if connection_file:\n            self.cleanup_connection_file()\n\n        self.cleanup_ipc_files()\n        self._close_control_socket()\n\n    def shutdown_kernel(self, now=False, restart=False):\n        \"\"\"Attempts to stop the kernel process cleanly.\n\n        This attempts to shutdown the kernels cleanly by:\n\n        1. Sending it a shutdown message over the shell channel.\n        2. If that fails, the kernel is shutdown forcibly by sending it\n           a signal.\n\n        Parameters\n        ----------\n        now : bool\n            Should the kernel be forcible killed *now*. This skips the\n            first, nice shutdown attempt.\n        restart: bool\n            Will this kernel be restarted after it is shutdown. When this\n            is True, connection files will not be cleaned up.\n        \"\"\"\n        # Stop monitoring for restarting while we shutdown.\n        self.stop_restarter()\n\n        if now:\n            self._kill_kernel()\n        else:\n            self.request_shutdown(restart=restart)\n            # Don't send any additional kernel kill messages immediately, to give\n            # the kernel a chance to properly execute shutdown actions. Wait for at\n            # most 1s, checking every 0.1s.\n            self.finish_shutdown()\n\n        self.cleanup(connection_file=not restart)\n\n    def restart_kernel(self, now=False, newports=False, **kw):\n        \"\"\"Restarts a kernel with the arguments that were used to launch it.\n\n        Parameters\n        ----------\n        now : bool, optional\n            If True, the kernel is forcefully restarted *immediately*, without\n            having a chance to do any cleanup action.  Otherwise the kernel is\n            given 1s to clean up before a forceful restart is issued.\n\n            In all cases the kernel is restarted, the only difference is whether\n            it is given a chance to perform a clean shutdown or not.\n\n        newports : bool, optional\n            If the old kernel was launched with random ports, this flag decides\n            whether the same ports and connection file will be used again.\n            If False, the same ports and connection file are used. This is\n            the default. If True, new random port numbers are chosen and a\n            new connection file is written. It is still possible that the newly\n            chosen random port numbers happen to be the same as the old ones.\n\n        `**kw` : optional\n            Any options specified here will overwrite those used to launch the\n            kernel.\n        \"\"\"\n        if self._launch_args is None:\n            raise RuntimeError(\"Cannot restart the kernel. \"\n                               \"No previous call to 'start_kernel'.\")\n        else:\n            # Stop currently running kernel.\n            self.shutdown_kernel(now=now, restart=True)\n\n            if newports:\n                self.cleanup_random_ports()\n\n            # Start new kernel.\n            self._launch_args.update(kw)\n            self.start_kernel(**self._launch_args)\n\n    @property\n    def has_kernel(self):\n        \"\"\"Has a kernel been started that we are managing.\"\"\"\n        return self.kernel is not None\n\n    def _kill_kernel(self):\n        \"\"\"Kill the running kernel.\n\n        This is a private method, callers should use shutdown_kernel(now=True).\n        \"\"\"\n        if self.has_kernel:\n\n            # Signal the kernel to terminate (sends SIGKILL on Unix and calls\n            # TerminateProcess() on Win32).\n            try:\n                if hasattr(signal, 'SIGKILL'):\n                    self.signal_kernel(signal.SIGKILL)\n                else:\n                    self.kernel.kill()\n            except OSError as e:\n                # In Windows, we will get an Access Denied error if the process\n                # has already terminated. Ignore it.\n                if sys.platform == 'win32':\n                    if e.winerror != 5:\n                        raise\n                # On Unix, we may get an ESRCH error if the process has already\n                # terminated. Ignore it.\n                else:\n                    from errno import ESRCH\n                    if e.errno != ESRCH:\n                        raise\n\n            # Block until the kernel terminates.\n            self.kernel.wait()\n            self.kernel = None\n        else:\n            raise RuntimeError(\"Cannot kill kernel. No kernel is running!\")\n\n    def interrupt_kernel(self):\n        \"\"\"Interrupts the kernel by sending it a signal.\n\n        Unlike ``signal_kernel``, this operation is well supported on all\n        platforms.\n        \"\"\"\n        if self.has_kernel:\n            interrupt_mode = self.kernel_spec.interrupt_mode\n            if interrupt_mode == 'signal':\n                if sys.platform == 'win32':\n                    from .win_interrupt import send_interrupt\n                    send_interrupt(self.kernel.win32_interrupt_event)\n                else:\n                    self.signal_kernel(signal.SIGINT)\n\n            elif interrupt_mode == 'message':\n                msg = self.session.msg(\"interrupt_request\", content={})\n                self._connect_control_socket()\n                self.session.send(self._control_socket, msg)\n        else:\n            raise RuntimeError(\"Cannot interrupt kernel. No kernel is running!\")\n\n    def signal_kernel(self, signum):\n        \"\"\"Sends a signal to the process group of the kernel (this\n        usually includes the kernel and any subprocesses spawned by\n        the kernel).\n\n        Note that since only SIGTERM is supported on Windows, this function is\n        only useful on Unix systems.\n        \"\"\"\n        if self.has_kernel:\n            if hasattr(os, \"getpgid\") and hasattr(os, \"killpg\"):\n                try:\n                    pgid = os.getpgid(self.kernel.pid)\n                    os.killpg(pgid, signum)\n                    return\n                except OSError:\n                    pass\n            self.kernel.send_signal(signum)\n        else:\n            raise RuntimeError(\"Cannot signal kernel. No kernel is running!\")\n\n    def is_alive(self):\n        \"\"\"Is the kernel process still running?\"\"\"\n        if self.has_kernel:\n            if self.kernel.poll() is None:\n                return True\n            else:\n                return False\n        else:\n            # we don't have a kernel\n            return False\n\n\nKernelManagerABC.register(KernelManager)\n\n\ndef start_new_kernel(startup_timeout=60, kernel_name='python', **kwargs):\n    \"\"\"Start a new kernel, and return its Manager and Client\"\"\"\n    km = KernelManager(kernel_name=kernel_name)\n    km.start_kernel(**kwargs)\n    kc = km.client()\n    kc.start_channels()\n    try:\n        kc.wait_for_ready(timeout=startup_timeout)\n    except RuntimeError:\n        kc.stop_channels()\n        km.shutdown_kernel()\n        raise\n\n    return km, kc\n\n@contextmanager\ndef run_kernel(**kwargs):\n    \"\"\"Context manager to create a kernel in a subprocess.\n\n    The kernel is shut down when the context exits.\n\n    Returns\n    -------\n    kernel_client: connected KernelClient instance\n    \"\"\"\n    km, kc = start_new_kernel(**kwargs)\n    try:\n        yield kc\n    finally:\n        kc.stop_channels()\n        km.shutdown_kernel(now=True)\n"
  },
  {
    "path": "lib/client/jupyter_client/managerabc.py",
    "content": "\"\"\"Abstract base class for kernel managers.\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport abc\n\nfrom ipython_genutils.py3compat import with_metaclass\n\n\nclass KernelManagerABC(with_metaclass(abc.ABCMeta, object)):\n    \"\"\"KernelManager ABC.\n\n    The docstrings for this class can be found in the base implementation:\n\n    `jupyter_client.kernelmanager.KernelManager`\n    \"\"\"\n\n    @abc.abstractproperty\n    def kernel(self):\n        pass\n\n    #--------------------------------------------------------------------------\n    # Kernel management\n    #--------------------------------------------------------------------------\n\n    @abc.abstractmethod\n    def start_kernel(self, **kw):\n        pass\n\n    @abc.abstractmethod\n    def shutdown_kernel(self, now=False, restart=False):\n        pass\n\n    @abc.abstractmethod\n    def restart_kernel(self, now=False, **kw):\n        pass\n\n    @abc.abstractproperty\n    def has_kernel(self):\n        pass\n\n    @abc.abstractmethod\n    def interrupt_kernel(self):\n        pass\n\n    @abc.abstractmethod\n    def signal_kernel(self, signum):\n        pass\n\n    @abc.abstractmethod\n    def is_alive(self):\n        pass\n"
  },
  {
    "path": "lib/client/jupyter_client/multikernelmanager.py",
    "content": "\"\"\"A kernel manager for multiple kernels\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import absolute_import\n\nimport os\nimport uuid\n\nimport zmq\n\nfrom traitlets.config.configurable import LoggingConfigurable\nfrom ipython_genutils.importstring import import_item\nfrom traitlets import (\n    Instance, Dict, List, Unicode, Any, DottedObjectName\n)\nfrom ipython_genutils.py3compat import unicode_type\n\nfrom .kernelspec import NATIVE_KERNEL_NAME, KernelSpecManager\n\nclass DuplicateKernelError(Exception):\n    pass\n\n\ndef kernel_method(f):\n    \"\"\"decorator for proxying MKM.method(kernel_id) to individual KMs by ID\"\"\"\n    def wrapped(self, kernel_id, *args, **kwargs):\n        # get the kernel\n        km = self.get_kernel(kernel_id)\n        method = getattr(km, f.__name__)\n        # call the kernel's method\n        r = method(*args, **kwargs)\n        # last thing, call anything defined in the actual class method\n        # such as logging messages\n        f(self, kernel_id, *args, **kwargs)\n        # return the method result\n        return r\n    return wrapped\n\n\nclass MultiKernelManager(LoggingConfigurable):\n    \"\"\"A class for managing multiple kernels.\"\"\"\n\n    default_kernel_name = Unicode(NATIVE_KERNEL_NAME, config=True,\n        help=\"The name of the default kernel to start\"\n    )\n\n    kernel_spec_manager = Instance(KernelSpecManager, allow_none=True)\n    \n    kernel_manager_class = DottedObjectName(\n        \"jupyter_client.ioloop.IOLoopKernelManager\", config=True,\n        help=\"\"\"The kernel manager class.  This is configurable to allow\n        subclassing of the KernelManager for customized behavior.\n        \"\"\"\n    )\n    def _kernel_manager_class_changed(self, name, old, new):\n        self.kernel_manager_factory = import_item(new)\n\n    kernel_manager_factory = Any(help=\"this is kernel_manager_class after import\")\n    def _kernel_manager_factory_default(self):\n        return import_item(self.kernel_manager_class)\n\n    context = Instance('zmq.Context')\n    def _context_default(self):\n        return zmq.Context.instance()\n\n    connection_dir = Unicode('')\n\n    _kernels = Dict()\n\n    def list_kernel_ids(self):\n        \"\"\"Return a list of the kernel ids of the active kernels.\"\"\"\n        # Create a copy so we can iterate over kernels in operations\n        # that delete keys.\n        return list(self._kernels.keys())\n\n    def __len__(self):\n        \"\"\"Return the number of running kernels.\"\"\"\n        return len(self.list_kernel_ids())\n\n    def __contains__(self, kernel_id):\n        return kernel_id in self._kernels\n\n    def start_kernel(self, kernel_name=None, **kwargs):\n        \"\"\"Start a new kernel.\n\n        The caller can pick a kernel_id by passing one in as a keyword arg,\n        otherwise one will be picked using a uuid.\n\n        The kernel ID for the newly started kernel is returned.\n        \"\"\"\n        kernel_id = kwargs.pop('kernel_id', unicode_type(uuid.uuid4()))\n        if kernel_id in self:\n            raise DuplicateKernelError('Kernel already exists: %s' % kernel_id)\n\n        if kernel_name is None:\n            kernel_name = self.default_kernel_name\n        # kernel_manager_factory is the constructor for the KernelManager\n        # subclass we are using. It can be configured as any Configurable,\n        # including things like its transport and ip.\n        constructor_kwargs = {}\n        if self.kernel_spec_manager:\n            constructor_kwargs['kernel_spec_manager'] = self.kernel_spec_manager\n        km = self.kernel_manager_factory(connection_file=os.path.join(\n                    self.connection_dir, \"kernel-%s.json\" % kernel_id),\n                    parent=self, log=self.log, kernel_name=kernel_name,\n                    **constructor_kwargs\n        )\n        km.start_kernel(**kwargs)\n        self._kernels[kernel_id] = km\n        return kernel_id\n\n    @kernel_method\n    def shutdown_kernel(self, kernel_id, now=False, restart=False):\n        \"\"\"Shutdown a kernel by its kernel uuid.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel to shutdown.\n        now : bool\n            Should the kernel be shutdown forcibly using a signal.\n        restart : bool\n            Will the kernel be restarted?\n        \"\"\"\n        self.log.info(\"Kernel shutdown: %s\" % kernel_id)\n        self.remove_kernel(kernel_id)\n\n    @kernel_method\n    def request_shutdown(self, kernel_id, restart=False):\n        \"\"\"Ask a kernel to shut down by its kernel uuid\"\"\"\n\n    @kernel_method\n    def finish_shutdown(self, kernel_id, waittime=None, pollinterval=0.1):\n        \"\"\"Wait for a kernel to finish shutting down, and kill it if it doesn't\n        \"\"\"\n        self.log.info(\"Kernel shutdown: %s\" % kernel_id)\n\n    @kernel_method\n    def cleanup(self, kernel_id, connection_file=True):\n        \"\"\"Clean up a kernel's resources\"\"\"\n\n    def remove_kernel(self, kernel_id):\n        \"\"\"remove a kernel from our mapping.\n\n        Mainly so that a kernel can be removed if it is already dead,\n        without having to call shutdown_kernel.\n\n        The kernel object is returned.\n        \"\"\"\n        return self._kernels.pop(kernel_id)\n\n    def shutdown_all(self, now=False):\n        \"\"\"Shutdown all kernels.\"\"\"\n        kids = self.list_kernel_ids()\n        for kid in kids:\n            self.request_shutdown(kid)\n        for kid in kids:\n            self.finish_shutdown(kid)\n            self.cleanup(kid)\n            self.remove_kernel(kid)\n\n    @kernel_method\n    def interrupt_kernel(self, kernel_id):\n        \"\"\"Interrupt (SIGINT) the kernel by its uuid.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel to interrupt.\n        \"\"\"\n        self.log.info(\"Kernel interrupted: %s\" % kernel_id)\n\n    @kernel_method\n    def signal_kernel(self, kernel_id, signum):\n        \"\"\"Sends a signal to the kernel by its uuid.\n\n        Note that since only SIGTERM is supported on Windows, this function\n        is only useful on Unix systems.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel to signal.\n        \"\"\"\n        self.log.info(\"Signaled Kernel %s with %s\" % (kernel_id, signum))\n\n    @kernel_method\n    def restart_kernel(self, kernel_id, now=False):\n        \"\"\"Restart a kernel by its uuid, keeping the same ports.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel to interrupt.\n        \"\"\"\n        self.log.info(\"Kernel restarted: %s\" % kernel_id)\n\n    @kernel_method\n    def is_alive(self, kernel_id):\n        \"\"\"Is the kernel alive.\n\n        This calls KernelManager.is_alive() which calls Popen.poll on the\n        actual kernel subprocess.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel.\n        \"\"\"\n\n    def _check_kernel_id(self, kernel_id):\n        \"\"\"check that a kernel id is valid\"\"\"\n        if kernel_id not in self:\n            raise KeyError(\"Kernel with id not found: %s\" % kernel_id)\n\n    def get_kernel(self, kernel_id):\n        \"\"\"Get the single KernelManager object for a kernel by its uuid.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel.\n        \"\"\"\n        self._check_kernel_id(kernel_id)\n        return self._kernels[kernel_id]\n\n    @kernel_method\n    def add_restart_callback(self, kernel_id, callback, event='restart'):\n        \"\"\"add a callback for the KernelRestarter\"\"\"\n\n    @kernel_method\n    def remove_restart_callback(self, kernel_id, callback, event='restart'):\n        \"\"\"remove a callback for the KernelRestarter\"\"\"\n\n    @kernel_method\n    def get_connection_info(self, kernel_id):\n        \"\"\"Return a dictionary of connection data for a kernel.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel.\n\n        Returns\n        =======\n        connection_dict : dict\n            A dict of the information needed to connect to a kernel.\n            This includes the ip address and the integer port\n            numbers of the different channels (stdin_port, iopub_port,\n            shell_port, hb_port).\n        \"\"\"\n\n    @kernel_method\n    def connect_iopub(self, kernel_id, identity=None):\n        \"\"\"Return a zmq Socket connected to the iopub channel.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel\n        identity : bytes (optional)\n            The zmq identity of the socket\n\n        Returns\n        =======\n        stream : zmq Socket or ZMQStream\n        \"\"\"\n\n    @kernel_method\n    def connect_shell(self, kernel_id, identity=None):\n        \"\"\"Return a zmq Socket connected to the shell channel.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel\n        identity : bytes (optional)\n            The zmq identity of the socket\n\n        Returns\n        =======\n        stream : zmq Socket or ZMQStream\n        \"\"\"\n\n    @kernel_method\n    def connect_stdin(self, kernel_id, identity=None):\n        \"\"\"Return a zmq Socket connected to the stdin channel.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel\n        identity : bytes (optional)\n            The zmq identity of the socket\n\n        Returns\n        =======\n        stream : zmq Socket or ZMQStream\n        \"\"\"\n\n    @kernel_method\n    def connect_hb(self, kernel_id, identity=None):\n        \"\"\"Return a zmq Socket connected to the hb channel.\n\n        Parameters\n        ==========\n        kernel_id : uuid\n            The id of the kernel\n        identity : bytes (optional)\n            The zmq identity of the socket\n\n        Returns\n        =======\n        stream : zmq Socket or ZMQStream\n        \"\"\"\n"
  },
  {
    "path": "lib/client/jupyter_client/restarter.py",
    "content": "\"\"\"A basic kernel monitor with autorestarting.\n\nThis watches a kernel's state using KernelManager.is_alive and auto\nrestarts the kernel if it dies.\n\nIt is an incomplete base class, and must be subclassed.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom traitlets.config.configurable import LoggingConfigurable\nfrom traitlets import (\n    Instance, Float, Dict, Bool, Integer,\n)\n\n\nclass KernelRestarter(LoggingConfigurable):\n    \"\"\"Monitor and autorestart a kernel.\"\"\"\n\n    kernel_manager = Instance('jupyter_client.KernelManager')\n\n    debug = Bool(False, config=True,\n        help=\"\"\"Whether to include every poll event in debugging output.\n\n        Has to be set explicitly, because there will be *a lot* of output.\n        \"\"\"\n    )\n\n    time_to_dead = Float(3.0, config=True,\n        help=\"\"\"Kernel heartbeat interval in seconds.\"\"\"\n    )\n\n    restart_limit = Integer(5, config=True,\n        help=\"\"\"The number of consecutive autorestarts before the kernel is presumed dead.\"\"\"\n    )\n\n    random_ports_until_alive = Bool(True, config=True,\n        help=\"\"\"Whether to choose new random ports when restarting before the kernel is alive.\"\"\"\n    )\n    _restarting = Bool(False)\n    _restart_count = Integer(0)\n    _initial_startup = Bool(True)\n\n    callbacks = Dict()\n    def _callbacks_default(self):\n        return dict(restart=[], dead=[])\n\n    def start(self):\n        \"\"\"Start the polling of the kernel.\"\"\"\n        raise NotImplementedError(\"Must be implemented in a subclass\")\n\n    def stop(self):\n        \"\"\"Stop the kernel polling.\"\"\"\n        raise NotImplementedError(\"Must be implemented in a subclass\")\n\n    def add_callback(self, f, event='restart'):\n        \"\"\"register a callback to fire on a particular event\n\n        Possible values for event:\n\n          'restart' (default): kernel has died, and will be restarted.\n          'dead': restart has failed, kernel will be left dead.\n\n        \"\"\"\n        self.callbacks[event].append(f)\n\n    def remove_callback(self, f, event='restart'):\n        \"\"\"unregister a callback to fire on a particular event\n\n        Possible values for event:\n\n          'restart' (default): kernel has died, and will be restarted.\n          'dead': restart has failed, kernel will be left dead.\n\n        \"\"\"\n        try:\n            self.callbacks[event].remove(f)\n        except ValueError:\n            pass\n\n    def _fire_callbacks(self, event):\n        \"\"\"fire our callbacks for a particular event\"\"\"\n        for callback in self.callbacks[event]:\n            try:\n                callback()\n            except Exception as e:\n                self.log.error(\"KernelRestarter: %s callback %r failed\", event, callback, exc_info=True)\n\n    def poll(self):\n        if self.debug:\n            self.log.debug('Polling kernel...')\n        if not self.kernel_manager.is_alive():\n            if self._restarting:\n                self._restart_count += 1\n            else:\n                self._restart_count = 1\n\n            if self._restart_count >= self.restart_limit:\n                self.log.warning(\"KernelRestarter: restart failed\")\n                self._fire_callbacks('dead')\n                self._restarting = False\n                self._restart_count = 0\n                self.stop()\n            else:\n                newports = self.random_ports_until_alive and self._initial_startup\n                self.log.info('KernelRestarter: restarting kernel (%i/%i), %s random ports',\n                    self._restart_count,\n                    self.restart_limit,\n                    'new' if newports else 'keep'\n                )\n                self._fire_callbacks('restart')\n                self.kernel_manager.restart_kernel(now=True, newports=newports)\n                self._restarting = True\n        else:\n            if self._initial_startup:\n                self._initial_startup = False\n            if self._restarting:\n                self.log.debug(\"KernelRestarter: restart apparently succeeded\")\n            self._restarting = False\n"
  },
  {
    "path": "lib/client/jupyter_client/runapp.py",
    "content": "\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function\n\nimport logging\nimport signal\nimport time\nimport sys\n\nfrom traitlets.config import catch_config_error\nfrom traitlets import (\n    Instance, Dict, Unicode, Bool, List, CUnicode, Any, Float\n)\nfrom jupyter_core.application import (\n    JupyterApp, base_flags, base_aliases\n)\n\nfrom . import __version__\nfrom .consoleapp import JupyterConsoleApp, app_aliases, app_flags\n\ntry:\n    import queue\nexcept ImportError:\n    import Queue as queue\n\nOUTPUT_TIMEOUT = 10\n\n# copy flags from mixin:\nflags = dict(base_flags)\n# start with mixin frontend flags:\nfrontend_flags = dict(app_flags)\n# update full dict with frontend flags:\nflags.update(frontend_flags)\n\n# copy flags from mixin\naliases = dict(base_aliases)\n# start with mixin frontend flags\nfrontend_aliases = dict(app_aliases)\n# load updated frontend flags into full dict\naliases.update(frontend_aliases)\n\n# get flags&aliases into sets, and remove a couple that\n# shouldn't be scrubbed from backend flags:\nfrontend_aliases = set(frontend_aliases.keys())\nfrontend_flags = set(frontend_flags.keys())\n\nclass RunApp(JupyterApp, JupyterConsoleApp):\n    version = __version__\n    name = \"jupyter run\"\n    description = \"\"\"Run Jupyter kernel code.\"\"\"\n    flags = Dict(flags)\n    aliases = Dict(aliases)\n    frontend_aliases = Any(frontend_aliases)\n    frontend_flags = Any(frontend_flags)\n    kernel_timeout = Float(60, config=True,\n        help=\"\"\"Timeout for giving up on a kernel (in seconds).\n\n        On first connect and restart, the console tests whether the\n        kernel is running and responsive by sending kernel_info_requests.\n        This sets the timeout in seconds for how long the kernel can take\n        before being presumed dead.\n        \"\"\"\n    )\n\n    def parse_command_line(self, argv=None):\n        super(RunApp, self).parse_command_line(argv)\n        self.build_kernel_argv(self.extra_args)\n        self.filenames_to_run = self.extra_args[:]\n\n    @catch_config_error\n    def initialize(self, argv=None):\n        self.log.debug(\"jupyter run: initialize...\")\n        super(RunApp, self).initialize(argv)\n        JupyterConsoleApp.initialize(self)\n        signal.signal(signal.SIGINT, self.handle_sigint)\n        self.init_kernel_info()\n\n    def handle_sigint(self, *args):\n        if self.kernel_manager:\n            self.kernel_manager.interrupt_kernel()\n        else:\n            print(\"\", file=sys.stderr)\n            error(\"Cannot interrupt kernels we didn't start.\\n\")\n\n    def init_kernel_info(self):\n        \"\"\"Wait for a kernel to be ready, and store kernel info\"\"\"\n        timeout = self.kernel_timeout\n        tic = time.time()\n        self.kernel_client.hb_channel.unpause()\n        msg_id = self.kernel_client.kernel_info()\n        while True:\n            try:\n                reply = self.kernel_client.get_shell_msg(timeout=1)\n            except queue.Empty:\n                if (time.time() - tic) > timeout:\n                    raise RuntimeError(\"Kernel didn't respond to kernel_info_request\")\n            else:\n                if reply['parent_header'].get('msg_id') == msg_id:\n                    self.kernel_info = reply['content']\n                    return\n\n    def start(self):\n        self.log.debug(\"jupyter run: starting...\")\n        super(RunApp, self).start()\n        if self.filenames_to_run:\n            for filename in self.filenames_to_run:\n                self.log.debug(\"jupyter run: executing `%s`\" % filename)\n                with open(filename) as fp:\n                    code = fp.read()\n                    reply = self.kernel_client.execute_interactive(code, timeout=OUTPUT_TIMEOUT)\n                    return_code = 0 if reply['content']['status'] == 'ok' else 1\n                    if return_code:\n                        raise Exception(\"jupyter-run error running '%s'\" % filename)\n        else:\n            code = sys.stdin.read()\n            reply = self.kernel_client.execute_interactive(code, timeout=OUTPUT_TIMEOUT)\n            return_code = 0 if reply['content']['status'] == 'ok' else 1\n            if return_code:\n                raise Exception(\"jupyter-run error running 'stdin'\")\n\nmain = launch_new_instance = RunApp.launch_instance\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "lib/client/jupyter_client/session.py",
    "content": "\"\"\"Session object for building, serializing, sending, and receiving messages.\n\nThe Session object supports serialization, HMAC signatures,\nand metadata on messages.\n\nAlso defined here are utilities for working with Sessions:\n* A SessionFactory to be used as a base class for configurables that work with\nSessions.\n* A Message object for convenience that allows attribute-access to the msg dict.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom binascii import b2a_hex\nimport hashlib\nimport hmac\nimport logging\nimport os\nimport pprint\nimport random\nimport warnings\nfrom datetime import datetime\n\ntry:\n    import cPickle\n    pickle = cPickle\nexcept:\n    cPickle = None\n    import pickle\n\ntry:\n    # py3\n    PICKLE_PROTOCOL = pickle.DEFAULT_PROTOCOL\nexcept AttributeError:\n    PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL\n\ntry:\n    # We are using compare_digest to limit the surface of timing attacks\n    from hmac import compare_digest\nexcept ImportError:\n    # Python < 2.7.7: When digests don't match no feedback is provided,\n    # limiting the surface of attack\n    def compare_digest(a,b): return a == b\n\ntry:\n    from datetime import timezone\n    utc = timezone.utc\nexcept ImportError:\n    # Python 2\n    from dateutil.tz import tzutc\n    utc = tzutc()\n\nimport zmq\nfrom zmq.utils import jsonapi\nfrom zmq.eventloop.ioloop import IOLoop\nfrom zmq.eventloop.zmqstream import ZMQStream\n\nfrom traitlets.config.configurable import Configurable, LoggingConfigurable\nfrom ipython_genutils.importstring import import_item\nfrom jupyter_client.jsonutil import extract_dates, squash_dates, date_default\nfrom ipython_genutils.py3compat import (str_to_bytes, str_to_unicode, unicode_type,\n                                     iteritems)\nfrom traitlets import (CBytes, Unicode, Bool, Any, Instance, Set,\n                                        DottedObjectName, CUnicode, Dict, Integer,\n                                        TraitError,\n)\nfrom jupyter_client import protocol_version\nfrom jupyter_client.adapter import adapt\nfrom traitlets.log import get_logger\n\n\n#-----------------------------------------------------------------------------\n# utility functions\n#-----------------------------------------------------------------------------\n\ndef squash_unicode(obj):\n    \"\"\"coerce unicode back to bytestrings.\"\"\"\n    if isinstance(obj,dict):\n        for key in obj.keys():\n            obj[key] = squash_unicode(obj[key])\n            if isinstance(key, unicode_type):\n                obj[squash_unicode(key)] = obj.pop(key)\n    elif isinstance(obj, list):\n        for i,v in enumerate(obj):\n            obj[i] = squash_unicode(v)\n    elif isinstance(obj, unicode_type):\n        obj = obj.encode('utf8')\n    return obj\n\n#-----------------------------------------------------------------------------\n# globals and defaults\n#-----------------------------------------------------------------------------\n\n# default values for the thresholds:\nMAX_ITEMS = 64\nMAX_BYTES = 1024\n\n# ISO8601-ify datetime objects\n# allow unicode\n# disallow nan, because it's not actually valid JSON\njson_packer = lambda obj: jsonapi.dumps(obj, default=date_default,\n    ensure_ascii=False, allow_nan=False,\n)\njson_unpacker = lambda s: jsonapi.loads(s)\n\npickle_packer = lambda o: pickle.dumps(squash_dates(o), PICKLE_PROTOCOL)\npickle_unpacker = pickle.loads\n\ndefault_packer = json_packer\ndefault_unpacker = json_unpacker\n\nDELIM = b\"<IDS|MSG>\"\n# singleton dummy tracker, which will always report as done\nDONE = zmq.MessageTracker()\n\n#-----------------------------------------------------------------------------\n# Mixin tools for apps that use Sessions\n#-----------------------------------------------------------------------------\n\ndef new_id():\n    \"\"\"Generate a new random id.\n\n    Avoids problematic runtime import in stdlib uuid on Python 2.\n\n    Returns\n    -------\n\n    id string (16 random bytes as hex-encoded text, chunks separated by '-')\n    \"\"\"\n    buf = os.urandom(16)\n    return u'-'.join(b2a_hex(x).decode('ascii') for x in (\n        buf[:4], buf[4:]\n    ))\n\ndef new_id_bytes():\n    \"\"\"Return new_id as ascii bytes\"\"\"\n    return new_id().encode('ascii')\n\nsession_aliases = dict(\n    ident = 'Session.session',\n    user = 'Session.username',\n    keyfile = 'Session.keyfile',\n)\n\nsession_flags  = {\n    'secure' : ({'Session' : { 'key' : new_id_bytes(),\n                            'keyfile' : '' }},\n        \"\"\"Use HMAC digests for authentication of messages.\n        Setting this flag will generate a new UUID to use as the HMAC key.\n        \"\"\"),\n    'no-secure' : ({'Session' : { 'key' : b'', 'keyfile' : '' }},\n        \"\"\"Don't authenticate messages.\"\"\"),\n}\n\ndef default_secure(cfg):\n    \"\"\"Set the default behavior for a config environment to be secure.\n\n    If Session.key/keyfile have not been set, set Session.key to\n    a new random UUID.\n    \"\"\"\n    warnings.warn(\"default_secure is deprecated\", DeprecationWarning)\n    if 'Session' in cfg:\n        if 'key' in cfg.Session or 'keyfile' in cfg.Session:\n            return\n    # key/keyfile not specified, generate new UUID:\n    cfg.Session.key = new_id_bytes()\n\ndef utcnow():\n    \"\"\"Return timezone-aware UTC timestamp\"\"\"\n    return datetime.utcnow().replace(tzinfo=utc)\n\n#-----------------------------------------------------------------------------\n# Classes\n#-----------------------------------------------------------------------------\n\nclass SessionFactory(LoggingConfigurable):\n    \"\"\"The Base class for configurables that have a Session, Context, logger,\n    and IOLoop.\n    \"\"\"\n\n    logname = Unicode('')\n    def _logname_changed(self, name, old, new):\n        self.log = logging.getLogger(new)\n\n    # not configurable:\n    context = Instance('zmq.Context')\n    def _context_default(self):\n        return zmq.Context.instance()\n\n    session = Instance('jupyter_client.session.Session',\n                       allow_none=True)\n\n    loop = Instance('tornado.ioloop.IOLoop')\n    def _loop_default(self):\n        return IOLoop.current()\n\n    def __init__(self, **kwargs):\n        super(SessionFactory, self).__init__(**kwargs)\n\n        if self.session is None:\n            # construct the session\n            self.session = Session(**kwargs)\n\n\nclass Message(object):\n    \"\"\"A simple message object that maps dict keys to attributes.\n\n    A Message can be created from a dict and a dict from a Message instance\n    simply by calling dict(msg_obj).\"\"\"\n\n    def __init__(self, msg_dict):\n        dct = self.__dict__\n        for k, v in iteritems(dict(msg_dict)):\n            if isinstance(v, dict):\n                v = Message(v)\n            dct[k] = v\n\n    # Having this iterator lets dict(msg_obj) work out of the box.\n    def __iter__(self):\n        return iter(iteritems(self.__dict__))\n\n    def __repr__(self):\n        return repr(self.__dict__)\n\n    def __str__(self):\n        return pprint.pformat(self.__dict__)\n\n    def __contains__(self, k):\n        return k in self.__dict__\n\n    def __getitem__(self, k):\n        return self.__dict__[k]\n\n\ndef msg_header(msg_id, msg_type, username, session):\n    \"\"\"Create a new message header\"\"\"\n    date = utcnow()\n    version = protocol_version\n    return locals()\n\ndef extract_header(msg_or_header):\n    \"\"\"Given a message or header, return the header.\"\"\"\n    if not msg_or_header:\n        return {}\n    try:\n        # See if msg_or_header is the entire message.\n        h = msg_or_header['header']\n    except KeyError:\n        try:\n            # See if msg_or_header is just the header\n            h = msg_or_header['msg_id']\n        except KeyError:\n            raise\n        else:\n            h = msg_or_header\n    if not isinstance(h, dict):\n        h = dict(h)\n    return h\n\nclass Session(Configurable):\n    \"\"\"Object for handling serialization and sending of messages.\n\n    The Session object handles building messages and sending them\n    with ZMQ sockets or ZMQStream objects.  Objects can communicate with each\n    other over the network via Session objects, and only need to work with the\n    dict-based IPython message spec. The Session will handle\n    serialization/deserialization, security, and metadata.\n\n    Sessions support configurable serialization via packer/unpacker traits,\n    and signing with HMAC digests via the key/keyfile traits.\n\n    Parameters\n    ----------\n\n    debug : bool\n        whether to trigger extra debugging statements\n    packer/unpacker : str : 'json', 'pickle' or import_string\n        importstrings for methods to serialize message parts.  If just\n        'json' or 'pickle', predefined JSON and pickle packers will be used.\n        Otherwise, the entire importstring must be used.\n\n        The functions must accept at least valid JSON input, and output *bytes*.\n\n        For example, to use msgpack:\n        packer = 'msgpack.packb', unpacker='msgpack.unpackb'\n    pack/unpack : callables\n        You can also set the pack/unpack callables for serialization directly.\n    session : bytes\n        the ID of this Session object.  The default is to generate a new UUID.\n    username : unicode\n        username added to message headers.  The default is to ask the OS.\n    key : bytes\n        The key used to initialize an HMAC signature.  If unset, messages\n        will not be signed or checked.\n    keyfile : filepath\n        The file containing a key.  If this is set, `key` will be initialized\n        to the contents of the file.\n\n    \"\"\"\n\n    debug = Bool(False, config=True, help=\"\"\"Debug output in the Session\"\"\")\n    \n    check_pid = Bool(True, config=True,\n        help=\"\"\"Whether to check PID to protect against calls after fork.\n        \n        This check can be disabled if fork-safety is handled elsewhere.\n        \"\"\")\n\n    packer = DottedObjectName('json',config=True,\n            help=\"\"\"The name of the packer for serializing messages.\n            Should be one of 'json', 'pickle', or an import name\n            for a custom callable serializer.\"\"\")\n    def _packer_changed(self, name, old, new):\n        if new.lower() == 'json':\n            self.pack = json_packer\n            self.unpack = json_unpacker\n            self.unpacker = new\n        elif new.lower() == 'pickle':\n            self.pack = pickle_packer\n            self.unpack = pickle_unpacker\n            self.unpacker = new\n        else:\n            self.pack = import_item(str(new))\n\n    unpacker = DottedObjectName('json', config=True,\n        help=\"\"\"The name of the unpacker for unserializing messages.\n        Only used with custom functions for `packer`.\"\"\")\n    def _unpacker_changed(self, name, old, new):\n        if new.lower() == 'json':\n            self.pack = json_packer\n            self.unpack = json_unpacker\n            self.packer = new\n        elif new.lower() == 'pickle':\n            self.pack = pickle_packer\n            self.unpack = pickle_unpacker\n            self.packer = new\n        else:\n            self.unpack = import_item(str(new))\n\n    session = CUnicode(u'', config=True,\n        help=\"\"\"The UUID identifying this session.\"\"\")\n    def _session_default(self):\n        u = new_id()\n        self.bsession = u.encode('ascii')\n        return u\n\n    def _session_changed(self, name, old, new):\n        self.bsession = self.session.encode('ascii')\n\n    # bsession is the session as bytes\n    bsession = CBytes(b'')\n\n    username = Unicode(str_to_unicode(os.environ.get('USER', 'username')),\n        help=\"\"\"Username for the Session. Default is your system username.\"\"\",\n        config=True)\n\n    metadata = Dict({}, config=True,\n        help=\"\"\"Metadata dictionary, which serves as the default top-level metadata dict for each message.\"\"\")\n\n    # if 0, no adapting to do.\n    adapt_version = Integer(0)\n\n    # message signature related traits:\n\n    key = CBytes(config=True,\n        help=\"\"\"execution key, for signing messages.\"\"\")\n    def _key_default(self):\n        return new_id_bytes()\n\n    def _key_changed(self):\n        self._new_auth()\n\n    signature_scheme = Unicode('hmac-sha256', config=True,\n        help=\"\"\"The digest scheme used to construct the message signatures.\n        Must have the form 'hmac-HASH'.\"\"\")\n    def _signature_scheme_changed(self, name, old, new):\n        if not new.startswith('hmac-'):\n            raise TraitError(\"signature_scheme must start with 'hmac-', got %r\" % new)\n        hash_name = new.split('-', 1)[1]\n        try:\n            self.digest_mod = getattr(hashlib, hash_name)\n        except AttributeError:\n            raise TraitError(\"hashlib has no such attribute: %s\" % hash_name)\n        self._new_auth()\n\n    digest_mod = Any()\n    def _digest_mod_default(self):\n        return hashlib.sha256\n    \n    auth = Instance(hmac.HMAC, allow_none=True)\n    \n    def _new_auth(self):\n        if self.key:\n            self.auth = hmac.HMAC(self.key, digestmod=self.digest_mod)\n        else:\n            self.auth = None\n\n    digest_history = Set()\n    digest_history_size = Integer(2**16, config=True,\n        help=\"\"\"The maximum number of digests to remember.\n\n        The digest history will be culled when it exceeds this value.\n        \"\"\"\n    )\n\n    keyfile = Unicode('', config=True,\n        help=\"\"\"path to file containing execution key.\"\"\")\n    def _keyfile_changed(self, name, old, new):\n        with open(new, 'rb') as f:\n            self.key = f.read().strip()\n\n    # for protecting against sends from forks\n    pid = Integer()\n\n    # serialization traits:\n\n    pack = Any(default_packer) # the actual packer function\n    def _pack_changed(self, name, old, new):\n        if not callable(new):\n            raise TypeError(\"packer must be callable, not %s\"%type(new))\n\n    unpack = Any(default_unpacker) # the actual packer function\n    def _unpack_changed(self, name, old, new):\n        # unpacker is not checked - it is assumed to be\n        if not callable(new):\n            raise TypeError(\"unpacker must be callable, not %s\"%type(new))\n\n    # thresholds:\n    copy_threshold = Integer(2**16, config=True,\n        help=\"Threshold (in bytes) beyond which a buffer should be sent without copying.\")\n    buffer_threshold = Integer(MAX_BYTES, config=True,\n        help=\"Threshold (in bytes) beyond which an object's buffer should be extracted to avoid pickling.\")\n    item_threshold = Integer(MAX_ITEMS, config=True,\n        help=\"\"\"The maximum number of items for a container to be introspected for custom serialization.\n        Containers larger than this are pickled outright.\n        \"\"\"\n    )\n\n\n    def __init__(self, **kwargs):\n        \"\"\"create a Session object\n\n        Parameters\n        ----------\n\n        debug : bool\n            whether to trigger extra debugging statements\n        packer/unpacker : str : 'json', 'pickle' or import_string\n            importstrings for methods to serialize message parts.  If just\n            'json' or 'pickle', predefined JSON and pickle packers will be used.\n            Otherwise, the entire importstring must be used.\n\n            The functions must accept at least valid JSON input, and output\n            *bytes*.\n\n            For example, to use msgpack:\n            packer = 'msgpack.packb', unpacker='msgpack.unpackb'\n        pack/unpack : callables\n            You can also set the pack/unpack callables for serialization\n            directly.\n        session : unicode (must be ascii)\n            the ID of this Session object.  The default is to generate a new\n            UUID.\n        bsession : bytes\n            The session as bytes\n        username : unicode\n            username added to message headers.  The default is to ask the OS.\n        key : bytes\n            The key used to initialize an HMAC signature.  If unset, messages\n            will not be signed or checked.\n        signature_scheme : str\n            The message digest scheme. Currently must be of the form 'hmac-HASH',\n            where 'HASH' is a hashing function available in Python's hashlib.\n            The default is 'hmac-sha256'.\n            This is ignored if 'key' is empty.\n        keyfile : filepath\n            The file containing a key.  If this is set, `key` will be\n            initialized to the contents of the file.\n        \"\"\"\n        super(Session, self).__init__(**kwargs)\n        self._check_packers()\n        self.none = self.pack({})\n        # ensure self._session_default() if necessary, so bsession is defined:\n        self.session\n        self.pid = os.getpid()\n        self._new_auth()\n        if not self.key:\n            get_logger().warning(\"Message signing is disabled.  This is insecure and not recommended!\")\n\n    def clone(self):\n        \"\"\"Create a copy of this Session\n\n        Useful when connecting multiple times to a given kernel.\n        This prevents a shared digest_history warning about duplicate digests\n        due to multiple connections to IOPub in the same process.\n\n        .. versionadded:: 5.1\n        \"\"\"\n        # make a copy\n        new_session = type(self)()\n        for name in self.traits():\n            setattr(new_session, name, getattr(self, name))\n        # fork digest_history\n        new_session.digest_history = set()\n        new_session.digest_history.update(self.digest_history)\n        return new_session\n\n    @property\n    def msg_id(self):\n        \"\"\"always return new uuid\"\"\"\n        return new_id()\n\n    def _check_packers(self):\n        \"\"\"check packers for datetime support.\"\"\"\n        pack = self.pack\n        unpack = self.unpack\n\n        # check simple serialization\n        msg = dict(a=[1,'hi'])\n        try:\n            packed = pack(msg)\n        except Exception as e:\n            msg = \"packer '{packer}' could not serialize a simple message: {e}{jsonmsg}\"\n            if self.packer == 'json':\n                jsonmsg = \"\\nzmq.utils.jsonapi.jsonmod = %s\" % jsonapi.jsonmod\n            else:\n                jsonmsg = \"\"\n            raise ValueError(\n                msg.format(packer=self.packer, e=e, jsonmsg=jsonmsg)\n            )\n\n        # ensure packed message is bytes\n        if not isinstance(packed, bytes):\n            raise ValueError(\"message packed to %r, but bytes are required\"%type(packed))\n\n        # check that unpack is pack's inverse\n        try:\n            unpacked = unpack(packed)\n            assert unpacked == msg\n        except Exception as e:\n            msg = \"unpacker '{unpacker}' could not handle output from packer '{packer}': {e}{jsonmsg}\"\n            if self.packer == 'json':\n                jsonmsg = \"\\nzmq.utils.jsonapi.jsonmod = %s\" % jsonapi.jsonmod\n            else:\n                jsonmsg = \"\"\n            raise ValueError(\n                msg.format(packer=self.packer, unpacker=self.unpacker, e=e, jsonmsg=jsonmsg)\n            )\n\n        # check datetime support\n        msg = dict(t=utcnow())\n        try:\n            unpacked = unpack(pack(msg))\n            if isinstance(unpacked['t'], datetime):\n                raise ValueError(\"Shouldn't deserialize to datetime\")\n        except Exception:\n            self.pack = lambda o: pack(squash_dates(o))\n            self.unpack = lambda s: unpack(s)\n\n    def msg_header(self, msg_type):\n        return msg_header(self.msg_id, msg_type, self.username, self.session)\n\n    def msg(self, msg_type, content=None, parent=None, header=None, metadata=None):\n        \"\"\"Return the nested message dict.\n\n        This format is different from what is sent over the wire. The\n        serialize/deserialize methods converts this nested message dict to the wire\n        format, which is a list of message parts.\n        \"\"\"\n        msg = {}\n        header = self.msg_header(msg_type) if header is None else header\n        msg['header'] = header\n        msg['msg_id'] = header['msg_id']\n        msg['msg_type'] = header['msg_type']\n        msg['parent_header'] = {} if parent is None else extract_header(parent)\n        msg['content'] = {} if content is None else content\n        msg['metadata'] = self.metadata.copy()\n        if metadata is not None:\n            msg['metadata'].update(metadata)\n        return msg\n\n    def sign(self, msg_list):\n        \"\"\"Sign a message with HMAC digest. If no auth, return b''.\n\n        Parameters\n        ----------\n        msg_list : list\n            The [p_header,p_parent,p_content] part of the message list.\n        \"\"\"\n        if self.auth is None:\n            return b''\n        h = self.auth.copy()\n        for m in msg_list:\n            h.update(m)\n        return str_to_bytes(h.hexdigest())\n\n    def serialize(self, msg, ident=None):\n        \"\"\"Serialize the message components to bytes.\n\n        This is roughly the inverse of deserialize. The serialize/deserialize\n        methods work with full message lists, whereas pack/unpack work with\n        the individual message parts in the message list.\n\n        Parameters\n        ----------\n        msg : dict or Message\n            The next message dict as returned by the self.msg method.\n\n        Returns\n        -------\n        msg_list : list\n            The list of bytes objects to be sent with the format::\n\n                [ident1, ident2, ..., DELIM, HMAC, p_header, p_parent,\n                 p_metadata, p_content, buffer1, buffer2, ...]\n\n            In this list, the ``p_*`` entities are the packed or serialized\n            versions, so if JSON is used, these are utf8 encoded JSON strings.\n        \"\"\"\n        content = msg.get('content', {})\n        if content is None:\n            content = self.none\n        elif isinstance(content, dict):\n            content = self.pack(content)\n        elif isinstance(content, bytes):\n            # content is already packed, as in a relayed message\n            pass\n        elif isinstance(content, unicode_type):\n            # should be bytes, but JSON often spits out unicode\n            content = content.encode('utf8')\n        else:\n            raise TypeError(\"Content incorrect type: %s\"%type(content))\n\n        real_message = [self.pack(msg['header']),\n                        self.pack(msg['parent_header']),\n                        self.pack(msg['metadata']),\n                        content,\n        ]\n\n        to_send = []\n\n        if isinstance(ident, list):\n            # accept list of idents\n            to_send.extend(ident)\n        elif ident is not None:\n            to_send.append(ident)\n        to_send.append(DELIM)\n\n        signature = self.sign(real_message)\n        to_send.append(signature)\n\n        to_send.extend(real_message)\n\n        return to_send\n\n    def send(self, stream, msg_or_type, content=None, parent=None, ident=None,\n             buffers=None, track=False, header=None, metadata=None):\n        \"\"\"Build and send a message via stream or socket.\n\n        The message format used by this function internally is as follows:\n\n        [ident1,ident2,...,DELIM,HMAC,p_header,p_parent,p_content,\n         buffer1,buffer2,...]\n\n        The serialize/deserialize methods convert the nested message dict into this\n        format.\n\n        Parameters\n        ----------\n\n        stream : zmq.Socket or ZMQStream\n            The socket-like object used to send the data.\n        msg_or_type : str or Message/dict\n            Normally, msg_or_type will be a msg_type unless a message is being\n            sent more than once. If a header is supplied, this can be set to\n            None and the msg_type will be pulled from the header.\n\n        content : dict or None\n            The content of the message (ignored if msg_or_type is a message).\n        header : dict or None\n            The header dict for the message (ignored if msg_to_type is a message).\n        parent : Message or dict or None\n            The parent or parent header describing the parent of this message\n            (ignored if msg_or_type is a message).\n        ident : bytes or list of bytes\n            The zmq.IDENTITY routing path.\n        metadata : dict or None\n            The metadata describing the message\n        buffers : list or None\n            The already-serialized buffers to be appended to the message.\n        track : bool\n            Whether to track.  Only for use with Sockets, because ZMQStream\n            objects cannot track messages.\n\n\n        Returns\n        -------\n        msg : dict\n            The constructed message.\n        \"\"\"\n        if not isinstance(stream, zmq.Socket):\n            # ZMQStreams and dummy sockets do not support tracking.\n            track = False\n\n        if isinstance(msg_or_type, (Message, dict)):\n            # We got a Message or message dict, not a msg_type so don't\n            # build a new Message.\n            msg = msg_or_type\n            buffers = buffers or msg.get('buffers', [])\n        else:\n            msg = self.msg(msg_or_type, content=content, parent=parent,\n                           header=header, metadata=metadata)\n        if self.check_pid and not os.getpid() == self.pid:\n            get_logger().warning(\"WARNING: attempted to send message from fork\\n%s\",\n                msg\n            )\n            return\n        buffers = [] if buffers is None else buffers\n        for idx, buf in enumerate(buffers):\n            if isinstance(buf, memoryview):\n                view = buf\n            else:\n                try:\n                    # check to see if buf supports the buffer protocol.\n                    view = memoryview(buf)\n                except TypeError:\n                    raise TypeError(\"Buffer objects must support the buffer protocol.\")\n            # memoryview.contiguous is new in 3.3,\n            # just skip the check on Python 2\n            if hasattr(view, 'contiguous') and not view.contiguous:\n                # zmq requires memoryviews to be contiguous\n                raise ValueError(\"Buffer %i (%r) is not contiguous\" % (idx, buf))\n\n        if self.adapt_version:\n            msg = adapt(msg, self.adapt_version)\n        to_send = self.serialize(msg, ident)\n        to_send.extend(buffers)\n        longest = max([ len(s) for s in to_send ])\n        copy = (longest < self.copy_threshold)\n\n        if buffers and track and not copy:\n            # only really track when we are doing zero-copy buffers\n            tracker = stream.send_multipart(to_send, copy=False, track=True)\n        else:\n            # use dummy tracker, which will be done immediately\n            tracker = DONE\n            stream.send_multipart(to_send, copy=copy)\n\n        if self.debug:\n            pprint.pprint(msg)\n            pprint.pprint(to_send)\n            pprint.pprint(buffers)\n\n        msg['tracker'] = tracker\n\n        return msg\n\n    def send_raw(self, stream, msg_list, flags=0, copy=True, ident=None):\n        \"\"\"Send a raw message via ident path.\n\n        This method is used to send a already serialized message.\n\n        Parameters\n        ----------\n        stream : ZMQStream or Socket\n            The ZMQ stream or socket to use for sending the message.\n        msg_list : list\n            The serialized list of messages to send. This only includes the\n            [p_header,p_parent,p_metadata,p_content,buffer1,buffer2,...] portion of\n            the message.\n        ident : ident or list\n            A single ident or a list of idents to use in sending.\n        \"\"\"\n        to_send = []\n        if isinstance(ident, bytes):\n            ident = [ident]\n        if ident is not None:\n            to_send.extend(ident)\n\n        to_send.append(DELIM)\n        to_send.append(self.sign(msg_list))\n        to_send.extend(msg_list)\n        stream.send_multipart(to_send, flags, copy=copy)\n\n    def recv(self, socket, mode=zmq.NOBLOCK, content=True, copy=True):\n        \"\"\"Receive and unpack a message.\n\n        Parameters\n        ----------\n        socket : ZMQStream or Socket\n            The socket or stream to use in receiving.\n\n        Returns\n        -------\n        [idents], msg\n            [idents] is a list of idents and msg is a nested message dict of\n            same format as self.msg returns.\n        \"\"\"\n        if isinstance(socket, ZMQStream):\n            socket = socket.socket\n        try:\n            msg_list = socket.recv_multipart(mode, copy=copy)\n        except zmq.ZMQError as e:\n            if e.errno == zmq.EAGAIN:\n                # We can convert EAGAIN to None as we know in this case\n                # recv_multipart won't return None.\n                return None,None\n            else:\n                raise\n        # split multipart message into identity list and message dict\n        # invalid large messages can cause very expensive string comparisons\n        idents, msg_list = self.feed_identities(msg_list, copy)\n        try:\n            return idents, self.deserialize(msg_list, content=content, copy=copy)\n        except Exception as e:\n            # TODO: handle it\n            raise e\n\n    def feed_identities(self, msg_list, copy=True):\n        \"\"\"Split the identities from the rest of the message.\n\n        Feed until DELIM is reached, then return the prefix as idents and\n        remainder as msg_list. This is easily broken by setting an IDENT to DELIM,\n        but that would be silly.\n\n        Parameters\n        ----------\n        msg_list : a list of Message or bytes objects\n            The message to be split.\n        copy : bool\n            flag determining whether the arguments are bytes or Messages\n\n        Returns\n        -------\n        (idents, msg_list) : two lists\n            idents will always be a list of bytes, each of which is a ZMQ\n            identity. msg_list will be a list of bytes or zmq.Messages of the\n            form [HMAC,p_header,p_parent,p_content,buffer1,buffer2,...] and\n            should be unpackable/unserializable via self.deserialize at this\n            point.\n        \"\"\"\n        if copy:\n            idx = msg_list.index(DELIM)\n            return msg_list[:idx], msg_list[idx+1:]\n        else:\n            failed = True\n            for idx,m in enumerate(msg_list):\n                if m.bytes == DELIM:\n                    failed = False\n                    break\n            if failed:\n                raise ValueError(\"DELIM not in msg_list\")\n            idents, msg_list = msg_list[:idx], msg_list[idx+1:]\n            return [m.bytes for m in idents], msg_list\n\n    def _add_digest(self, signature):\n        \"\"\"add a digest to history to protect against replay attacks\"\"\"\n        if self.digest_history_size == 0:\n            # no history, never add digests\n            return\n\n        self.digest_history.add(signature)\n        if len(self.digest_history) > self.digest_history_size:\n            # threshold reached, cull 10%\n            self._cull_digest_history()\n\n    def _cull_digest_history(self):\n        \"\"\"cull the digest history\n\n        Removes a randomly selected 10% of the digest history\n        \"\"\"\n        current = len(self.digest_history)\n        n_to_cull = max(int(current // 10), current - self.digest_history_size)\n        if n_to_cull >= current:\n            self.digest_history = set()\n            return\n        to_cull = random.sample(self.digest_history, n_to_cull)\n        self.digest_history.difference_update(to_cull)\n\n    def deserialize(self, msg_list, content=True, copy=True):\n        \"\"\"Unserialize a msg_list to a nested message dict.\n\n        This is roughly the inverse of serialize. The serialize/deserialize\n        methods work with full message lists, whereas pack/unpack work with\n        the individual message parts in the message list.\n\n        Parameters\n        ----------\n        msg_list : list of bytes or Message objects\n            The list of message parts of the form [HMAC,p_header,p_parent,\n            p_metadata,p_content,buffer1,buffer2,...].\n        content : bool (True)\n            Whether to unpack the content dict (True), or leave it packed\n            (False).\n        copy : bool (True)\n            Whether msg_list contains bytes (True) or the non-copying Message\n            objects in each place (False).\n\n        Returns\n        -------\n        msg : dict\n            The nested message dict with top-level keys [header, parent_header,\n            content, buffers].  The buffers are returned as memoryviews.\n        \"\"\"\n        minlen = 5\n        message = {}\n        if not copy:\n            # pyzmq didn't copy the first parts of the message, so we'll do it\n            for i in range(minlen):\n                msg_list[i] = msg_list[i].bytes\n        if self.auth is not None:\n            signature = msg_list[0]\n            if not signature:\n                raise ValueError(\"Unsigned Message\")\n            if signature in self.digest_history:\n                raise ValueError(\"Duplicate Signature: %r\" % signature)\n            if content:\n                # Only store signature if we are unpacking content, don't store if just peeking.\n                self._add_digest(signature)\n            check = self.sign(msg_list[1:5])\n            if not compare_digest(signature, check):\n                raise ValueError(\"Invalid Signature: %r\" % signature)\n        if not len(msg_list) >= minlen:\n            raise TypeError(\"malformed message, must have at least %i elements\"%minlen)\n        header = self.unpack(msg_list[1])\n        message['header'] = extract_dates(header)\n        message['msg_id'] = header['msg_id']\n        message['msg_type'] = header['msg_type']\n        message['parent_header'] = extract_dates(self.unpack(msg_list[2]))\n        message['metadata'] = self.unpack(msg_list[3])\n        if content:\n            message['content'] = self.unpack(msg_list[4])\n        else:\n            message['content'] = msg_list[4]\n        buffers = [memoryview(b) for b in msg_list[5:]]\n        if buffers and buffers[0].shape is None:\n            # force copy to workaround pyzmq #646\n            buffers = [memoryview(b.bytes) for b in msg_list[5:]]\n        message['buffers'] = buffers\n        if self.debug:\n            pprint.pprint(message)\n        # adapt to the current version\n        return adapt(message)\n\n    def unserialize(self, *args, **kwargs):\n        warnings.warn(\n            \"Session.unserialize is deprecated. Use Session.deserialize.\",\n            DeprecationWarning,\n        )\n        return self.deserialize(*args, **kwargs)\n\n\ndef test_msg2obj():\n    am = dict(x=1)\n    ao = Message(am)\n    assert ao.x == am['x']\n\n    am['y'] = dict(z=1)\n    ao = Message(am)\n    assert ao.y.z == am['y']['z']\n\n    k1, k2 = 'y', 'z'\n    assert ao[k1][k2] == am[k1][k2]\n\n    am2 = dict(ao)\n    assert am['x'] == am2['x']\n    assert am['y']['z'] == am2['y']['z']\n"
  },
  {
    "path": "lib/client/jupyter_client/threaded.py",
    "content": "\"\"\" Defines a KernelClient that provides thread-safe sockets with async callbacks on message replies.\n\"\"\"\nfrom __future__ import absolute_import\nimport atexit\nimport errno\nimport sys\nfrom threading import Thread, Event\nimport time\n\n# import ZMQError in top-level namespace, to avoid ugly attribute-error messages\n# during garbage collection of threads at exit:\nfrom zmq import ZMQError\nfrom zmq.eventloop import ioloop, zmqstream\n\n# Local imports\nfrom traitlets import Type, Instance\nfrom jupyter_client.channels import HBChannel\nfrom jupyter_client import KernelClient\n\nclass ThreadedZMQSocketChannel(object):\n    \"\"\"A ZMQ socket invoking a callback in the ioloop\"\"\"\n    session = None\n    socket = None\n    ioloop = None\n    stream = None\n    _inspect = None\n\n    def __init__(self, socket, session, loop):\n        \"\"\"Create a channel.\n\n        Parameters\n        ----------\n        socket : :class:`zmq.Socket`\n            The ZMQ socket to use.\n        session : :class:`session.Session`\n            The session to use.\n        loop\n            A pyzmq ioloop to connect the socket to using a ZMQStream\n        \"\"\"\n        super(ThreadedZMQSocketChannel, self).__init__()\n\n        self.socket = socket\n        self.session = session\n        self.ioloop = loop\n        evt = Event()\n\n        def setup_stream():\n            self.stream = zmqstream.ZMQStream(self.socket, self.ioloop)\n            self.stream.on_recv(self._handle_recv)\n            evt.set()\n\n        self.ioloop.add_callback(setup_stream)\n        evt.wait()\n\n    _is_alive = False\n    def is_alive(self):\n        return self._is_alive\n\n    def start(self):\n        self._is_alive = True\n\n    def stop(self):\n        self._is_alive = False\n\n    def close(self):\n        if self.socket is not None:\n            try:\n                self.socket.close(linger=0)\n            except Exception:\n                pass\n            self.socket = None\n\n    def send(self, msg):\n        \"\"\"Queue a message to be sent from the IOLoop's thread.\n\n        Parameters\n        ----------\n        msg : message to send\n\n        This is threadsafe, as it uses IOLoop.add_callback to give the loop's\n        thread control of the action.\n        \"\"\"\n        def thread_send():\n            self.session.send(self.stream, msg)\n        self.ioloop.add_callback(thread_send)\n\n    def _handle_recv(self, msg):\n        \"\"\"Callback for stream.on_recv.\n\n        Unpacks message, and calls handlers with it.\n        \"\"\"\n        ident,smsg = self.session.feed_identities(msg)\n        msg = self.session.deserialize(smsg)\n        # let client inspect messages\n        if self._inspect:\n            self._inspect(msg)\n        self.call_handlers(msg)\n\n    def call_handlers(self, msg):\n        \"\"\"This method is called in the ioloop thread when a message arrives.\n\n        Subclasses should override this method to handle incoming messages.\n        It is important to remember that this method is called in the thread\n        so that some logic must be done to ensure that the application level\n        handlers are called in the application thread.\n        \"\"\"\n        pass\n\n    def process_events(self):\n        \"\"\"Subclasses should override this with a method\n        processing any pending GUI events.\n        \"\"\"\n        pass\n\n\n    def flush(self, timeout=1.0):\n        \"\"\"Immediately processes all pending messages on this channel.\n\n        This is only used for the IOPub channel.\n\n        Callers should use this method to ensure that :meth:`call_handlers`\n        has been called for all messages that have been received on the\n        0MQ SUB socket of this channel.\n\n        This method is thread safe.\n\n        Parameters\n        ----------\n        timeout : float, optional\n            The maximum amount of time to spend flushing, in seconds. The\n            default is one second.\n        \"\"\"\n        # We do the IOLoop callback process twice to ensure that the IOLoop\n        # gets to perform at least one full poll.\n        stop_time = time.time() + timeout\n        for i in range(2):\n            self._flushed = False\n            self.ioloop.add_callback(self._flush)\n            while not self._flushed and time.time() < stop_time:\n                time.sleep(0.01)\n\n    def _flush(self):\n        \"\"\"Callback for :method:`self.flush`.\"\"\"\n        self.stream.flush()\n        self._flushed = True\n\n\nclass IOLoopThread(Thread):\n    \"\"\"Run a pyzmq ioloop in a thread to send and receive messages\n    \"\"\"\n    _exiting = False\n    ioloop = None\n\n    def __init__(self):\n        super(IOLoopThread, self).__init__()\n        self.daemon = True\n\n    @staticmethod\n    @atexit.register\n    def _notice_exit():\n        # Class definitions can be torn down during interpreter shutdown.\n        # We only need to set _exiting flag if this hasn't happened.\n        if IOLoopThread is not None:\n            IOLoopThread._exiting = True\n\n    def start(self):\n        \"\"\"Start the IOLoop thread\n\n        Don't return until self.ioloop is defined,\n        which is created in the thread\n        \"\"\"\n        self._start_event = Event()\n        Thread.start(self)\n        self._start_event.wait()\n\n    def run(self):\n        \"\"\"Run my loop, ignoring EINTR events in the poller\"\"\"\n        if 'asyncio' in sys.modules:\n            # tornado may be using asyncio,\n            # ensure an eventloop exists for this thread\n            import asyncio\n            asyncio.set_event_loop(asyncio.new_event_loop())\n        self.ioloop = ioloop.IOLoop()\n        # signal that self.ioloop is defined\n        self._start_event.set()\n        while True:\n            try:\n                self.ioloop.start()\n            except ZMQError as e:\n                if e.errno == errno.EINTR:\n                    continue\n                else:\n                    raise\n            except Exception:\n                if self._exiting:\n                    break\n                else:\n                    raise\n            else:\n                break\n\n    def stop(self):\n        \"\"\"Stop the channel's event loop and join its thread.\n\n        This calls :meth:`~threading.Thread.join` and returns when the thread\n        terminates. :class:`RuntimeError` will be raised if\n        :meth:`~threading.Thread.start` is called again.\n        \"\"\"\n        if self.ioloop is not None:\n            self.ioloop.add_callback(self.ioloop.stop)\n        self.join()\n        self.close()\n        self.ioloop = None\n\n    def close(self):\n        if self.ioloop is not None:\n            try:\n                self.ioloop.close(all_fds=True)\n            except Exception:\n                pass\n\n\nclass ThreadedKernelClient(KernelClient):\n    \"\"\" A KernelClient that provides thread-safe sockets with async callbacks on message replies.\n    \"\"\"\n\n    @property\n    def ioloop(self):\n        return self.ioloop_thread.ioloop\n\n    ioloop_thread = Instance(IOLoopThread, allow_none=True)\n\n    def start_channels(self, shell=True, iopub=True, stdin=True, hb=True):\n        self.ioloop_thread = IOLoopThread()\n        self.ioloop_thread.start()\n\n        if shell:\n            self.shell_channel._inspect = self._check_kernel_info_reply\n\n        super(ThreadedKernelClient, self).start_channels(shell, iopub, stdin, hb)\n\n    def _check_kernel_info_reply(self, msg):\n        \"\"\"This is run in the ioloop thread when the kernel info reply is received\n        \"\"\"\n        if msg['msg_type'] == 'kernel_info_reply':\n            self._handle_kernel_info_reply(msg)\n            self.shell_channel._inspect = None\n\n    def stop_channels(self):\n        super(ThreadedKernelClient, self).stop_channels()\n        if self.ioloop_thread.is_alive():\n            self.ioloop_thread.stop()\n\n    iopub_channel_class = Type(ThreadedZMQSocketChannel)\n    shell_channel_class = Type(ThreadedZMQSocketChannel)\n    stdin_channel_class = Type(ThreadedZMQSocketChannel)\n    hb_channel_class = Type(HBChannel)\n"
  },
  {
    "path": "lib/client/jupyter_client/win_interrupt.py",
    "content": "\"\"\"Use a Windows event to interrupt a child process like SIGINT.\n\nThe child needs to explicitly listen for this - see\nipykernel.parentpoller.ParentPollerWindows for a Python implementation.\n\"\"\"\n\nimport ctypes\n\ndef create_interrupt_event():\n    \"\"\"Create an interrupt event handle.\n\n    The parent process should call this to create the\n    interrupt event that is passed to the child process. It should store\n    this handle and use it with ``send_interrupt`` to interrupt the child\n    process.\n    \"\"\"\n    # Create a security attributes struct that permits inheritance of the\n    # handle by new processes.\n    # FIXME: We can clean up this mess by requiring pywin32 for IPython.\n    class SECURITY_ATTRIBUTES(ctypes.Structure):\n        _fields_ = [ (\"nLength\", ctypes.c_int),\n                     (\"lpSecurityDescriptor\", ctypes.c_void_p),\n                     (\"bInheritHandle\", ctypes.c_int) ]\n    sa = SECURITY_ATTRIBUTES()\n    sa_p = ctypes.pointer(sa)\n    sa.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES)\n    sa.lpSecurityDescriptor = 0\n    sa.bInheritHandle = 1\n\n    return ctypes.windll.kernel32.CreateEventA(\n        sa_p,  # lpEventAttributes\n        False, # bManualReset\n        False, # bInitialState\n        '')    # lpName\n\ndef send_interrupt(interrupt_handle):\n    \"\"\" Sends an interrupt event using the specified handle.\n    \"\"\"\n    ctypes.windll.kernel32.SetEvent(interrupt_handle)\n"
  },
  {
    "path": "lib/client/jupyter_core/__init__.py",
    "content": "from .version import version_info, __version__\n"
  },
  {
    "path": "lib/client/jupyter_core/__main__.py",
    "content": "\"\"\"Launch the root jupyter command\"\"\"\nfrom .command import main\nmain()\n"
  },
  {
    "path": "lib/client/jupyter_core/application.py",
    "content": "# encoding: utf-8\n\"\"\"\nA base Application class for Jupyter applications.\n\nAll Jupyter applications should inherit from this.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function\n\nfrom copy import deepcopy\nimport logging\nimport os\nimport sys\n\ntry:\n    # py3\n    from shutil import which\nexcept ImportError:\n    from .utils.shutil_which import which\n\ntry:\n    raw_input\nexcept NameError:\n    # py3\n    raw_input = input\n\nfrom traitlets.config.application import Application, catch_config_error\nfrom traitlets.config.loader import ConfigFileNotFound\nfrom traitlets import Unicode, Bool, List, observe\n\nfrom .utils import ensure_dir_exists\nfrom ipython_genutils import py3compat\n\nfrom .paths import (\n    jupyter_config_dir, jupyter_data_dir, jupyter_runtime_dir,\n    jupyter_path, jupyter_config_path,\n)\n\n# aliases and flags\n\nbase_aliases = {\n    'log-level' : 'Application.log_level',\n    'config' : 'JupyterApp.config_file',\n}\n\nbase_flags = {\n    'debug': ({'Application' : {'log_level' : logging.DEBUG}},\n            \"set log level to logging.DEBUG (maximize logging output)\"),\n    'generate-config': ({'JupyterApp': {'generate_config': True}},\n        \"generate default config file\"),\n    'y': ({'JupyterApp': {'answer_yes': True}},\n        \"Answer yes to any questions instead of prompting.\"),\n}\n\nclass NoStart(Exception):\n    \"\"\"Exception to raise when an application shouldn't start\"\"\"\n\nclass JupyterApp(Application):\n    \"\"\"Base class for Jupyter applications\"\"\"\n    name = 'jupyter' # override in subclasses\n    description = \"A Jupyter Application\"\n    \n    aliases = base_aliases\n    flags = base_flags\n\n    def _log_level_default(self):\n        return logging.INFO\n    \n    jupyter_path = List(Unicode())\n    def _jupyter_path_default(self):\n        return jupyter_path()\n    \n    config_dir = Unicode()\n    \n    def _config_dir_default(self):\n        return jupyter_config_dir()\n    \n    @property\n    def config_file_paths(self):\n        path = jupyter_config_path()\n        if self.config_dir not in path:\n            path.insert(0, self.config_dir)\n        path.insert(0, py3compat.getcwd())\n        return path\n    \n    data_dir = Unicode()\n    \n    def _data_dir_default(self):\n        d = jupyter_data_dir()\n        ensure_dir_exists(d, mode=0o700)\n        return d\n    runtime_dir = Unicode()\n    \n    def _runtime_dir_default(self):\n        rd = jupyter_runtime_dir()\n        ensure_dir_exists(rd, mode=0o700)\n        return rd\n\n    @observe('runtime_dir')\n    def _runtime_dir_changed(self, change):\n        ensure_dir_exists(change['new'], mode=0o700)\n\n    generate_config = Bool(False, config=True,\n        help=\"\"\"Generate default config file.\"\"\"\n    )\n    \n    config_file_name = Unicode(config=True,\n        help=\"Specify a config file to load.\"\n    )\n    def _config_file_name_default(self):\n        if not self.name:\n            return ''\n        return self.name.replace('-','_') + u'_config'\n    \n    config_file = Unicode(config=True,\n        help=\"\"\"Full path of a config file.\"\"\",\n    )\n    \n    answer_yes = Bool(False, config=True,\n        help=\"\"\"Answer yes to any prompts.\"\"\"\n    )\n    \n    def write_default_config(self):\n        \"\"\"Write our default config to a .py config file\"\"\"\n        if self.config_file:\n            config_file = self.config_file\n        else:\n            config_file = os.path.join(self.config_dir, self.config_file_name + '.py')\n        \n        if os.path.exists(config_file) and not self.answer_yes:\n            answer = ''\n            def ask():\n                prompt = \"Overwrite %s with default config? [y/N]\" % config_file\n                try:\n                    return raw_input(prompt).lower() or 'n'\n                except KeyboardInterrupt:\n                    print('') # empty line\n                    return 'n'\n            answer = ask()\n            while not answer.startswith(('y', 'n')):\n                print(\"Please answer 'yes' or 'no'\")\n                answer = ask()\n            if answer.startswith('n'):\n                return\n        \n        config_text = self.generate_config_file()\n        if isinstance(config_text, bytes):\n            config_text = config_text.decode('utf8')\n        print(\"Writing default config to: %s\" % config_file)\n        ensure_dir_exists(os.path.abspath(os.path.dirname(config_file)), 0o700)\n        with open(config_file, mode='w') as f:\n            f.write(config_text)\n    \n    def migrate_config(self):\n        \"\"\"Migrate config/data from IPython 3\"\"\"\n        if os.path.exists(os.path.join(self.config_dir, 'migrated')):\n            # already migrated\n            return\n\n        from .migrate import get_ipython_dir, migrate\n\n        # No IPython dir, nothing to migrate\n        if not os.path.exists(get_ipython_dir()):\n            return\n\n        migrate()\n\n    def load_config_file(self, suppress_errors=True):\n        \"\"\"Load the config file.\n\n        By default, errors in loading config are handled, and a warning\n        printed on screen. For testing, the suppress_errors option is set\n        to False, so errors will make tests fail.\n        \"\"\"\n        self.log.debug(\"Searching %s for config files\", self.config_file_paths)\n        base_config = 'jupyter_config'\n        try:\n            super(JupyterApp, self).load_config_file(\n                base_config,\n                path=self.config_file_paths,\n            )\n        except ConfigFileNotFound:\n            # ignore errors loading parent\n            self.log.debug(\"Config file %s not found\", base_config)\n            pass\n\n        if self.config_file:\n            path, config_file_name = os.path.split(self.config_file)\n        else:\n            path = self.config_file_paths\n            config_file_name = self.config_file_name\n\n            if not config_file_name or (config_file_name == base_config):\n                return\n\n        try:\n            super(JupyterApp, self).load_config_file(\n                config_file_name,\n                path=path\n            )\n        except ConfigFileNotFound:\n            self.log.debug(\"Config file not found, skipping: %s\", config_file_name)\n        except Exception:\n            # Reraise errors for testing purposes, or if set in\n            # self.raise_config_file_errors\n            if (not suppress_errors) or self.raise_config_file_errors:\n                raise\n            self.log.warning(\"Error loading config file: %s\" %\n                            config_file_name, exc_info=True)\n\n    # subcommand-related\n    def _find_subcommand(self, name):\n        name = '{}-{}'.format(self.name, name)\n        return which(name)\n    \n    @property\n    def _dispatching(self):\n        \"\"\"Return whether we are dispatching to another command\n        \n        or running ourselves.\n        \"\"\"\n        return bool(self.generate_config or self.subapp or self.subcommand)\n    \n    subcommand = Unicode()\n    \n    @catch_config_error\n    def initialize(self, argv=None):\n        # don't hook up crash handler before parsing command-line\n        if argv is None:\n            argv = sys.argv[1:]\n        if argv:\n            subc = self._find_subcommand(argv[0])\n            if subc:\n                self.argv = argv\n                self.subcommand = subc\n                return\n        self.parse_command_line(argv)\n        cl_config = deepcopy(self.config)\n        if self._dispatching:\n            return\n        self.migrate_config()\n        self.load_config_file()\n        # enforce cl-opts override configfile opts:\n        self.update_config(cl_config)\n    \n    \n    def start(self):\n        \"\"\"Start the whole thing\"\"\"\n        if self.subcommand:\n            os.execv(self.subcommand, [self.subcommand] + self.argv[1:])\n            raise NoStart()\n        \n        if self.subapp:\n            self.subapp.start()\n            raise NoStart()\n        \n        if self.generate_config:\n            self.write_default_config()\n            raise NoStart()\n    \n    @classmethod\n    def launch_instance(cls, argv=None, **kwargs):\n        \"\"\"Launch an instance of a Jupyter Application\"\"\"\n        try:\n            return super(JupyterApp, cls).launch_instance(argv=argv, **kwargs)\n        except NoStart:\n            return\n\nif __name__ == '__main__':\n    JupyterApp.launch_instance()\n"
  },
  {
    "path": "lib/client/jupyter_core/command.py",
    "content": "\"\"\"The root `jupyter` command.\n\nThis does nothing other than dispatch to subcommands or output path info.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function\n\nimport argparse\nimport errno\nimport json\nimport os\nimport sys\nimport sysconfig\nfrom subprocess import Popen\n\ntry:\n     # py3\n     from shutil import which\nexcept ImportError:\n     from .utils.shutil_which import which\n\nfrom . import paths\nfrom .version import __version__\n\nclass JupyterParser(argparse.ArgumentParser):\n\n    @property\n    def epilog(self):\n        \"\"\"Add subcommands to epilog on request\n\n        Avoids searching PATH for subcommands unless help output is requested.\n        \"\"\"\n        return 'Available subcommands: %s' % ' '.join(list_subcommands())\n\n    @epilog.setter\n    def epilog(self, x):\n        \"\"\"Ignore epilog set in Parser.__init__\"\"\"\n        pass\n\ndef jupyter_parser():\n    parser = JupyterParser(\n        description=\"Jupyter: Interactive Computing\",\n    )\n    group = parser.add_mutually_exclusive_group(required=True)\n    # don't use argparse's version action because it prints to stderr on py2\n    group.add_argument('--version', action='store_true',\n        help=\"show the jupyter command's version and exit\")\n    group.add_argument('subcommand', type=str, nargs='?', help='the subcommand to launch')\n\n    group.add_argument('--config-dir', action='store_true',\n        help=\"show Jupyter config dir\")\n    group.add_argument('--data-dir', action='store_true',\n        help=\"show Jupyter data dir\")\n    group.add_argument('--runtime-dir', action='store_true',\n        help=\"show Jupyter runtime dir\")\n    group.add_argument('--paths', action='store_true',\n        help=\"show all Jupyter paths. Add --json for machine-readable format.\")\n    parser.add_argument('--json', action='store_true',\n        help=\"output paths as machine-readable json\")\n\n    return parser\n\n\ndef list_subcommands():\n    \"\"\"List all jupyter subcommands\n\n    searches PATH for `jupyter-name`\n\n    Returns a list of jupyter's subcommand names, without the `jupyter-` prefix.\n    Nested children (e.g. jupyter-sub-subsub) are not included.\n    \"\"\"\n    subcommand_tuples = set()\n    # construct a set of `('foo', 'bar') from `jupyter-foo-bar`\n    for d in _path_with_self():\n        try:\n            names = os.listdir(d)\n        except OSError:\n            continue\n        for name in names:\n            if name.startswith('jupyter-'):\n                if sys.platform.startswith('win'):\n                    # remove file-extension on Windows\n                    name = os.path.splitext(name)[0]\n                subcommand_tuples.add(tuple(name.split('-')[1:]))\n    # build a set of subcommand strings, excluding subcommands whose parents are defined\n    subcommands = set()\n    # Only include `jupyter-foo-bar` if `jupyter-foo` is not already present\n    for sub_tup in subcommand_tuples:\n        if not any(sub_tup[:i] in subcommand_tuples for i in range(1, len(sub_tup))):\n            subcommands.add('-'.join(sub_tup))\n    return sorted(subcommands)\n\n\ndef _execvp(cmd, argv):\n    \"\"\"execvp, except on Windows where it uses Popen\n\n    Python provides execvp on Windows, but its behavior is problematic (Python bug#9148).\n    \"\"\"\n    if sys.platform.startswith('win'):\n        # PATH is ignored when shell=False,\n        # so rely on shutil.which\n        try:\n            from shutil import which\n        except ImportError:\n            from .utils.shutil_which import which\n        cmd_path = which(cmd)\n        if cmd_path is None:\n            raise OSError('%r not found' % cmd, errno.ENOENT)\n        p = Popen([cmd_path] + argv[1:])\n        # Don't raise KeyboardInterrupt in the parent process.\n        # Set this after spawning, to avoid subprocess inheriting handler.\n        import signal\n        signal.signal(signal.SIGINT, signal.SIG_IGN)\n        p.wait()\n        sys.exit(p.returncode)\n    else:\n        os.execvp(cmd, argv)\n\n\ndef _jupyter_abspath(subcommand):\n    \"\"\"This method get the abspath of a specified jupyter-subcommand with no \n    changes on ENV.\n    \"\"\"\n    # get env PATH with self\n    search_path = os.pathsep.join(_path_with_self())\n    # get the abs path for the jupyter-<subcommand>\n    jupyter_subcommand = 'jupyter-{}'.format(subcommand)\n    abs_path = which(jupyter_subcommand, path=search_path)\n    if abs_path is None:\n        raise Exception(\n            'Jupyter command `{}` not found.'.format(jupyter_subcommand)\n        )\n\n    if not os.access(abs_path, os.X_OK):\n        raise Exception(\n            'Jupyter command `{}` is not executable.'.format(jupyter_subcommand)\n        )\n\n    return abs_path\n\n\ndef _path_with_self():\n    \"\"\"Put `jupyter`'s dir at the front of PATH\n\n    Ensures that /path/to/jupyter subcommand\n    will do /path/to/jupyter-subcommand\n    even if /other/jupyter-subcommand is ahead of it on PATH\n    \"\"\"\n    path_list = (os.environ.get('PATH') or os.defpath).split(os.pathsep)\n\n    # Insert the \"scripts\" directory for this Python installation\n    # This allows the \"jupyter\" command to be relocated, while still\n    # finding subcommands that have been installed in the default\n    # location.\n    # We put the scripts directory at the *end* of PATH, so that\n    # if the user explicitly overrides a subcommand, that override\n    # still takes effect.\n    try:\n        bindir = sysconfig.get_path('scripts')\n    except KeyError:\n        # The Python environment does not specify a \"scripts\" location\n        pass\n    else:\n        path_list.append(bindir)\n\n    scripts = [sys.argv[0]]\n    if os.path.islink(scripts[0]):\n        # include realpath, if `jupyter` is a symlink\n        scripts.append(os.path.realpath(scripts[0]))\n\n    for script in scripts:\n        bindir = os.path.dirname(script)\n        if (\n            os.path.isdir(bindir)\n            and os.access(script, os.X_OK)  # only if it's a script\n        ):\n            # ensure executable's dir is on PATH\n            # avoids missing subcommands when jupyter is run via absolute path\n            path_list.insert(0, bindir)\n    return path_list\n\n\ndef main():\n    if len(sys.argv) > 1 and not sys.argv[1].startswith('-'):\n        # Don't parse if a subcommand is given\n        # Avoids argparse gobbling up args passed to subcommand, such as `-h`.\n        subcommand = sys.argv[1]\n    else:\n        parser = jupyter_parser()\n        args, opts = parser.parse_known_args()\n        subcommand = args.subcommand\n        if args.version:\n            print('{:<17}:'.format('jupyter core'), __version__)\n            for package, name in [\n                ('notebook', 'jupyter-notebook'),\n                ('qtconsole', 'qtconsole'),\n                ('IPython', 'ipython'),\n                ('ipykernel', 'ipykernel'),\n                ('jupyter_client', 'jupyter client'),\n                ('jupyterlab', 'jupyter lab'),\n                ('nbconvert', 'nbconvert'),\n                ('ipywidgets', 'ipywidgets'),\n                ('nbformat', 'nbformat'),\n                ('traitlets', 'traitlets'),\n            ]:\n                version = None\n                try:\n                    mod = __import__(package)\n                    version = mod.__version__\n                except ImportError:\n                    version = 'not installed'\n                print('{:<17}:'.format(name), version)\n            return\n        if args.json and not args.paths:\n            sys.exit(\"--json is only used with --paths\")\n        if args.config_dir:\n            print(paths.jupyter_config_dir())\n            return\n        if args.data_dir:\n            print(paths.jupyter_data_dir())\n            return\n        if args.runtime_dir:\n            print(paths.jupyter_runtime_dir())\n            return\n        if args.paths:\n            data = {}\n            data['runtime'] = [paths.jupyter_runtime_dir()]\n            data['config'] = paths.jupyter_config_path()\n            data['data'] = paths.jupyter_path()\n            if args.json:\n                print(json.dumps(data))\n            else:\n                for name in sorted(data):\n                    path = data[name]\n                    print('%s:' % name)\n                    for p in path:\n                        print('    ' + p)\n            return\n\n    if not subcommand:\n        parser.print_usage(file=sys.stderr)\n        sys.exit(\"subcommand is required\")\n\n    command = _jupyter_abspath(subcommand)\n\n    try:\n        _execvp(command, sys.argv[1:])\n    except OSError as e:\n        sys.exit(\"Error executing Jupyter command %r: %s\" % (subcommand, e))\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "lib/client/jupyter_core/migrate.py",
    "content": "from __future__ import unicode_literals\n\n\"\"\"Migrating IPython < 4.0 to Jupyter\n\nThis *copies* configuration and resources to their new locations in Jupyter\n\nMigrations:\n\n- .ipython/\n  - nbextensions -> JUPYTER_DATA_DIR/nbextensions\n  - kernels ->  JUPYTER_DATA_DIR/kernels\n- .ipython/profile_default/\n  - static/custom -> .jupyter/custom\n  - nbconfig -> .jupyter/nbconfig\n  - security/\n    - notebook_secret, notebook_cookie_secret, nbsignatures.db -> JUPYTER_DATA_DIR\n  - ipython_{notebook,nbconvert,qtconsole}_config.py -> .jupyter/jupyter_{name}_config.py\n\n\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport os\nimport re\nimport shutil\nfrom datetime import datetime\n\nfrom traitlets.config import PyFileConfigLoader, JSONFileConfigLoader\nfrom traitlets.log import get_logger\n\nfrom .utils import ensure_dir_exists\n\nfrom .paths import jupyter_config_dir, jupyter_data_dir\nfrom .application import JupyterApp\n\npjoin = os.path.join\n\nmigrations = {\n    pjoin('{ipython_dir}', 'nbextensions'): pjoin('{jupyter_data}', 'nbextensions'),\n    pjoin('{ipython_dir}', 'kernels'): pjoin('{jupyter_data}', 'kernels'),\n    pjoin('{profile}', 'nbconfig'): pjoin('{jupyter_config}', 'nbconfig'),\n}\n\ncustom_src_t = pjoin('{profile}', 'static', 'custom')\ncustom_dst_t = pjoin('{jupyter_config}', 'custom')\n\nfor security_file in ('notebook_secret', 'notebook_cookie_secret', 'nbsignatures.db'):\n    src = pjoin('{profile}', 'security', security_file)\n    dst = pjoin('{jupyter_data}', security_file)\n    migrations[src] = dst\n\nconfig_migrations = ['notebook', 'nbconvert', 'qtconsole']\n\nregex = re.compile\n\nconfig_substitutions = {\n    regex(r'\\bIPythonQtConsoleApp\\b'): 'JupyterQtConsoleApp',\n    regex(r'\\bIPythonWidget\\b'): 'JupyterWidget',\n    regex(r'\\bRichIPythonWidget\\b'): 'RichJupyterWidget',\n    regex(r'\\bIPython\\.html\\b'): 'notebook',\n    regex(r'\\bIPython\\.nbconvert\\b'): 'nbconvert',\n}\n\n\ndef get_ipython_dir():\n    \"\"\"Return the IPython directory location.\n\n    Not imported from IPython because the IPython implementation\n    ensures that a writable directory exists,\n    creating a temporary directory if not.\n    We don't want to trigger that when checking if migration should happen.\n\n    We only need to support the IPython < 4 behavior for migration,\n    so importing for forward-compatibility and edge cases is not important.\n    \"\"\"\n    return os.environ.get('IPYTHONDIR', os.path.expanduser('~/.ipython'))\n\n\ndef migrate_dir(src, dst):\n    \"\"\"Migrate a directory from src to dst\"\"\"\n    log = get_logger()\n    if not os.listdir(src):\n        log.debug(\"No files in %s\" % src)\n        return False\n    if os.path.exists(dst):\n        if os.listdir(dst):\n            # already exists, non-empty\n            log.debug(\"%s already exists\" % dst)\n            return False\n        else:\n            os.rmdir(dst)\n    log.info(\"Copying %s -> %s\" % (src, dst))\n    ensure_dir_exists(os.path.dirname(dst))\n    shutil.copytree(src, dst, symlinks=True)\n    return True\n\n\ndef migrate_file(src, dst, substitutions=None):\n    \"\"\"Migrate a single file from src to dst\n    \n    substitutions is an optional dict of {regex: replacement} for performing replacements on the file.\n    \"\"\"\n    log = get_logger()\n    if os.path.exists(dst):\n        # already exists\n        log.debug(\"%s already exists\" % dst)\n        return False\n    log.info(\"Copying %s -> %s\" % (src, dst))\n    ensure_dir_exists(os.path.dirname(dst))\n    shutil.copy(src, dst)\n    if substitutions:\n        with open(dst) as f:\n            text = f.read()\n        for pat, replacement in substitutions.items():\n            text = pat.sub(replacement, text)\n        with open(dst, 'w') as f:\n            f.write(text)\n    return True\n\n\ndef migrate_one(src, dst):\n    \"\"\"Migrate one item\n    \n    dispatches to migrate_dir/_file\n    \"\"\"\n    log = get_logger()\n    if os.path.isfile(src):\n        return migrate_file(src, dst)\n    elif os.path.isdir(src):\n        return migrate_dir(src, dst)\n    else:\n        log.debug(\"Nothing to migrate for %s\" % src)\n        return False\n\n\ndef migrate_static_custom(src, dst):\n    \"\"\"Migrate non-empty custom.js,css from src to dst\n    \n    src, dst are 'custom' directories containing custom.{js,css}\n    \"\"\"\n    log = get_logger()\n    migrated = False\n    \n    custom_js = pjoin(src, 'custom.js')\n    custom_css = pjoin(src, 'custom.css')\n    # check if custom_js is empty:\n    custom_js_empty = True\n    if os.path.isfile(custom_js):\n        with open(custom_js) as f:\n            js = f.read().strip()\n            for line in js.splitlines():\n                if not (\n                    line.isspace()\n                    or line.strip().startswith(('/*', '*', '//'))\n                ):\n                    custom_js_empty = False\n                    break\n    \n    # check if custom_css is empty:\n    custom_css_empty = True\n    if os.path.isfile(custom_css):\n        with open(custom_css) as f:\n            css = f.read().strip()\n            custom_css_empty = css.startswith('/*') and css.endswith('*/')\n    \n    if custom_js_empty:\n        log.debug(\"Ignoring empty %s\" % custom_js)\n    if custom_css_empty:\n        log.debug(\"Ignoring empty %s\" % custom_css)\n    \n    if custom_js_empty and custom_css_empty:\n        # nothing to migrate\n        return False\n    ensure_dir_exists(dst)\n    \n    if not custom_js_empty or not custom_css_empty:\n        ensure_dir_exists(dst)\n    \n    if not custom_js_empty:\n        if migrate_file(custom_js, pjoin(dst, 'custom.js')):\n            migrated = True\n    if not custom_css_empty:\n        if migrate_file(custom_css, pjoin(dst, 'custom.css')):\n            migrated = True\n    \n    return migrated\n\n\ndef migrate_config(name, env):\n    \"\"\"Migrate a config file\n    \n    Includes substitutions for updated configurable names.\n    \"\"\"\n    log = get_logger()\n    src_base = pjoin('{profile}', 'ipython_{name}_config').format(name=name, **env)\n    dst_base = pjoin('{jupyter_config}', 'jupyter_{name}_config').format(name=name, **env)\n    loaders = {\n        '.py': PyFileConfigLoader,\n        '.json': JSONFileConfigLoader,\n    }\n    migrated = []\n    for ext in ('.py', '.json'):\n        src = src_base + ext\n        dst = dst_base + ext\n        if os.path.exists(src):\n            cfg = loaders[ext](src).load_config()\n            if cfg:\n                if migrate_file(src, dst, substitutions=config_substitutions):\n                    migrated.append(src)\n            else:\n                # don't migrate empty config files\n                log.debug(\"Not migrating empty config file: %s\" % src)\n    return migrated\n\n\ndef migrate():\n    \"\"\"Migrate IPython configuration to Jupyter\"\"\"\n    env = {\n        'jupyter_data': jupyter_data_dir(),\n        'jupyter_config': jupyter_config_dir(),\n        'ipython_dir': get_ipython_dir(),\n        'profile': os.path.join(get_ipython_dir(), 'profile_default'),\n    }\n    migrated = False\n    for src_t, dst_t in migrations.items():\n        src = src_t.format(**env)\n        dst = dst_t.format(**env)\n        if os.path.exists(src):\n            if migrate_one(src, dst):\n                migrated = True\n    \n    for name in config_migrations:\n        if migrate_config(name, env):\n            migrated = True\n    \n    custom_src = custom_src_t.format(**env)\n    custom_dst = custom_dst_t.format(**env)\n    \n    if os.path.exists(custom_src):\n        if migrate_static_custom(custom_src, custom_dst):\n            migrated = True\n    \n    # write a marker to avoid re-running migration checks\n    ensure_dir_exists(env['jupyter_config'])\n    with open(os.path.join(env['jupyter_config'], 'migrated'), 'w') as f:\n        f.write(datetime.utcnow().isoformat())\n    \n    return migrated\n\n\n\nclass JupyterMigrate(JupyterApp):\n    name = 'jupyter-migrate'\n    description = \"\"\"\n    Migrate configuration and data from .ipython prior to 4.0 to Jupyter locations.\n    \n    This migrates:\n    \n    - config files in the default profile\n    - kernels in ~/.ipython/kernels\n    - notebook javascript extensions in ~/.ipython/extensions\n    - custom.js/css to .jupyter/custom\n    \n    to their new Jupyter locations.\n    \n    All files are copied, not moved.\n    If the destinations already exist, nothing will be done.\n    \"\"\"\n    \n    def start(self):\n        if not migrate():\n            self.log.info(\"Found nothing to migrate.\")\n\n\nmain = JupyterMigrate.launch_instance\n\n\nif __name__ == '__main__':\n    main()\n\n"
  },
  {
    "path": "lib/client/jupyter_core/paths.py",
    "content": "# encoding: utf-8\n\"\"\"Path utility functions.\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\n# Derived from IPython.utils.path, which is\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\n\nimport os\nimport sys\nimport stat\nimport errno\nimport tempfile\nfrom ipython_genutils import py3compat\n\nfrom contextlib import contextmanager\nfrom ipython_genutils import py3compat\n\npjoin = os.path.join\n\n# UF_HIDDEN is a stat flag not defined in the stat module.\n# It is used by BSD to indicate hidden files.\nUF_HIDDEN = getattr(stat, 'UF_HIDDEN', 32768)\n\n\ndef get_home_dir():\n    \"\"\"Get the real path of the home directory\"\"\"\n    homedir = os.path.expanduser('~')\n    # Next line will make things work even when /home/ is a symlink to\n    # /usr/home as it is on FreeBSD, for example\n    homedir = os.path.realpath(homedir)\n    homedir = py3compat.str_to_unicode(homedir, encoding=sys.getfilesystemencoding()) \n    return homedir\n\n_dtemps = {}\ndef _mkdtemp_once(name):\n    \"\"\"Make or reuse a temporary directory.\n\n    If this is called with the same name in the same process, it will return\n    the same directory.\n    \"\"\"\n    try:\n        return _dtemps[name]\n    except KeyError:\n        d = _dtemps[name] = tempfile.mkdtemp(prefix=name + '-')\n        return d\n\ndef jupyter_config_dir():\n    \"\"\"Get the Jupyter config directory for this platform and user.\n\n    Returns JUPYTER_CONFIG_DIR if defined, else ~/.jupyter\n    \"\"\"\n\n    env = os.environ\n    home_dir = get_home_dir()\n\n    if env.get('JUPYTER_NO_CONFIG'):\n        return _mkdtemp_once('jupyter-clean-cfg')\n\n    if env.get('JUPYTER_CONFIG_DIR'):\n        return env['JUPYTER_CONFIG_DIR']\n\n    return pjoin(home_dir, '.jupyter')\n\n\ndef jupyter_data_dir():\n    \"\"\"Get the config directory for Jupyter data files.\n\n    These are non-transient, non-configuration files.\n\n    Returns JUPYTER_DATA_DIR if defined, else a platform-appropriate path.\n    \"\"\"\n    env = os.environ\n\n    if env.get('JUPYTER_DATA_DIR'):\n        return env['JUPYTER_DATA_DIR']\n\n    home = get_home_dir()\n\n    if sys.platform == 'darwin':\n        return os.path.join(home, 'Library', 'Jupyter')\n    elif os.name == 'nt':\n        appdata = os.environ.get('APPDATA', None)\n        if appdata:\n            return pjoin(appdata, 'jupyter')\n        else:\n            return pjoin(jupyter_config_dir(), 'data')\n    else:\n        # Linux, non-OS X Unix, AIX, etc.\n        xdg = env.get(\"XDG_DATA_HOME\", None)\n        if not xdg:\n            xdg = pjoin(home, '.local', 'share')\n        return pjoin(xdg, 'jupyter')\n\n\ndef jupyter_runtime_dir():\n    \"\"\"Return the runtime dir for transient jupyter files.\n\n    Returns JUPYTER_RUNTIME_DIR if defined.\n\n    The default is now (data_dir)/runtime on all platforms;\n    we no longer use XDG_RUNTIME_DIR after various problems.\n    \"\"\"\n    env = os.environ\n\n    if env.get('JUPYTER_RUNTIME_DIR'):\n        return env['JUPYTER_RUNTIME_DIR']\n\n    return pjoin(jupyter_data_dir(), 'runtime')\n\n\nif os.name == 'nt':\n    programdata = os.environ.get('PROGRAMDATA', None)\n    if programdata:\n        SYSTEM_JUPYTER_PATH = [pjoin(programdata, 'jupyter')]\n    else:  # PROGRAMDATA is not defined by default on XP.\n        SYSTEM_JUPYTER_PATH = [os.path.join(sys.prefix, 'share', 'jupyter')]\nelse:\n    SYSTEM_JUPYTER_PATH = [\n        \"/usr/local/share/jupyter\",\n        \"/usr/share/jupyter\",\n    ]\n\nENV_JUPYTER_PATH = [os.path.join(sys.prefix, 'share', 'jupyter')]\n\n\ndef jupyter_path(*subdirs):\n    \"\"\"Return a list of directories to search for data files\n\n    JUPYTER_PATH environment variable has highest priority.\n\n    If ``*subdirs`` are given, that subdirectory will be added to each element.\n\n    Examples:\n\n    >>> jupyter_path()\n    ['~/.local/jupyter', '/usr/local/share/jupyter']\n    >>> jupyter_path('kernels')\n    ['~/.local/jupyter/kernels', '/usr/local/share/jupyter/kernels']\n    \"\"\"\n\n    paths = []\n    # highest priority is env\n    if os.environ.get('JUPYTER_PATH'):\n        paths.extend(\n            p.rstrip(os.sep)\n            for p in os.environ['JUPYTER_PATH'].split(os.pathsep)\n        )\n    # then user dir\n    paths.append(jupyter_data_dir())\n    # then sys.prefix\n    for p in ENV_JUPYTER_PATH:\n        if p not in SYSTEM_JUPYTER_PATH:\n            paths.append(p)\n    # finally, system\n    paths.extend(SYSTEM_JUPYTER_PATH)\n\n    # add subdir, if requested\n    if subdirs:\n        paths = [ pjoin(p, *subdirs) for p in paths ]\n    return paths\n\n\nif os.name == 'nt':\n    programdata = os.environ.get('PROGRAMDATA', None)\n    if programdata:\n        SYSTEM_CONFIG_PATH = [os.path.join(programdata, 'jupyter')]\n    else:  # PROGRAMDATA is not defined by default on XP.\n        SYSTEM_CONFIG_PATH = []\nelse:\n    SYSTEM_CONFIG_PATH = [\n        \"/usr/local/etc/jupyter\",\n        \"/etc/jupyter\",\n    ]\n\nENV_CONFIG_PATH = [os.path.join(sys.prefix, 'etc', 'jupyter')]\n\n\ndef jupyter_config_path():\n    \"\"\"Return the search path for Jupyter config files as a list.\"\"\"\n    paths = [jupyter_config_dir()]\n    if os.environ.get('JUPYTER_NO_CONFIG'):\n        return paths\n\n    # highest priority is env\n    if os.environ.get('JUPYTER_CONFIG_PATH'):\n        paths.extend(\n            p.rstrip(os.sep)\n            for p in os.environ['JUPYTER_CONFIG_PATH'].split(os.pathsep)\n        )\n\n    # then sys.prefix\n    for p in ENV_CONFIG_PATH:\n        if p not in SYSTEM_CONFIG_PATH:\n            paths.append(p)\n    paths.extend(SYSTEM_CONFIG_PATH)\n    return paths\n\n\ndef exists(path):\n    \"\"\"Replacement for `os.path.exists` which works for host mapped volumes\n    on Windows containers\n    \"\"\"\n    try:\n        os.lstat(path)\n    except OSError:\n        return False\n    return True\n\n\ndef is_file_hidden_win(abs_path, stat_res=None):\n    \"\"\"Is a file hidden?\n\n    This only checks the file itself; it should be called in combination with\n    checking the directory containing the file.\n\n    Use is_hidden() instead to check the file and its parent directories.\n\n    Parameters\n    ----------\n    abs_path : unicode\n        The absolute path to check.\n    stat_res : os.stat_result, optional\n        Ignored on Windows, exists for compatibility with POSIX version of the\n        function.\n    \"\"\"\n    if os.path.basename(abs_path).startswith('.'):\n        return True\n\n    win32_FILE_ATTRIBUTE_HIDDEN = 0x02\n    import ctypes\n    try:\n        attrs = ctypes.windll.kernel32.GetFileAttributesW(\n            py3compat.cast_unicode(abs_path)\n        )\n    except AttributeError:\n        pass\n    else:\n        if attrs > 0 and attrs & win32_FILE_ATTRIBUTE_HIDDEN:\n            return True\n\n    return False\n\n\ndef is_file_hidden_posix(abs_path, stat_res=None):\n    \"\"\"Is a file hidden?\n\n    This only checks the file itself; it should be called in combination with\n    checking the directory containing the file.\n\n    Use is_hidden() instead to check the file and its parent directories.\n\n    Parameters\n    ----------\n    abs_path : unicode\n        The absolute path to check.\n    stat_res : os.stat_result, optional\n        The result of calling stat() on abs_path. If not passed, this function\n        will call stat() internally.\n    \"\"\"\n    if os.path.basename(abs_path).startswith('.'):\n        return True\n\n    if stat_res is None or stat.S_ISLNK(stat_res.st_mode):\n        try:\n            stat_res = os.stat(abs_path)\n        except OSError as e:\n            if e.errno == errno.ENOENT:\n                return False\n            raise\n\n    # check that dirs can be listed\n    if stat.S_ISDIR(stat_res.st_mode):\n        # use x-access, not actual listing, in case of slow/large listings\n        if not os.access(abs_path, os.X_OK | os.R_OK):\n            return True\n\n    # check UF_HIDDEN\n    if getattr(stat_res, 'st_flags', 0) & UF_HIDDEN:\n        return True\n\n    return False\n\n\nif sys.platform == 'win32':\n    is_file_hidden = is_file_hidden_win\nelse:\n    is_file_hidden = is_file_hidden_posix\n\n\ndef is_hidden(abs_path, abs_root=''):\n    \"\"\"Is a file hidden or contained in a hidden directory?\n\n    This will start with the rightmost path element and work backwards to the\n    given root to see if a path is hidden or in a hidden directory. Hidden is\n    determined by either name starting with '.' or the UF_HIDDEN flag as\n    reported by stat.\n\n    If abs_path is the same directory as abs_root, it will be visible even if\n    that is a hidden folder. This only checks the visibility of files\n    and directories *within* abs_root.\n\n    Parameters\n    ----------\n    abs_path : unicode\n        The absolute path to check for hidden directories.\n    abs_root : unicode\n        The absolute path of the root directory in which hidden directories\n        should be checked for.\n    \"\"\"\n    if os.path.normpath(abs_path) == os.path.normpath(abs_root):\n        return False\n\n    if is_file_hidden(abs_path):\n        return True\n\n    if not abs_root:\n        abs_root = abs_path.split(os.sep, 1)[0] + os.sep\n    inside_root = abs_path[len(abs_root):]\n    if any(part.startswith('.') for part in inside_root.split(os.sep)):\n        return True\n\n    # check UF_HIDDEN on any location up to root.\n    # is_file_hidden() already checked the file, so start from its parent dir\n    path = os.path.dirname(abs_path)\n    while path and path.startswith(abs_root) and path != abs_root:\n        if not exists(path):\n            path = os.path.dirname(path)\n            continue\n        try:\n            # may fail on Windows junctions\n            st = os.lstat(path)\n        except OSError:\n            return True\n        if getattr(st, 'st_flags', 0) & UF_HIDDEN:\n            return True\n        path = os.path.dirname(path)\n\n    return False\n\n\ndef win32_restrict_file_to_user(fname):\n    \"\"\"Secure a windows file to read-only access for the user.\n    Follows guidance from win32 library creator:\n    http://timgolden.me.uk/python/win32_how_do_i/add-security-to-a-file.html\n\n    This method should be executed against an already generated file which\n    has no secrets written to it yet.\n\n    Parameters\n    ----------\n\n    fname : unicode\n        The path to the file to secure\n    \"\"\"\n    import win32api\n    import win32security\n    import ntsecuritycon as con\n\n    # everyone, _domain, _type = win32security.LookupAccountName(\"\", \"Everyone\")\n    admins = win32security.CreateWellKnownSid(win32security.WinBuiltinAdministratorsSid)\n    user, _domain, _type = win32security.LookupAccountName(\"\", win32api.GetUserNameEx(win32api.NameSamCompatible))\n\n    sd = win32security.GetFileSecurity(fname, win32security.DACL_SECURITY_INFORMATION)\n\n    dacl = win32security.ACL()\n    # dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_ALL_ACCESS, everyone)\n    dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_GENERIC_READ | con.FILE_GENERIC_WRITE, user)\n    dacl.AddAccessAllowedAce(win32security.ACL_REVISION, con.FILE_ALL_ACCESS, admins)\n\n    sd.SetSecurityDescriptorDacl(1, dacl, 0)\n    win32security.SetFileSecurity(fname, win32security.DACL_SECURITY_INFORMATION, sd)\n\n\ndef get_file_mode(fname):\n    \"\"\"Retrieves the file mode corresponding to fname in a filesystem-tolerant manner.\n\n    Parameters\n    ----------\n\n    fname : unicode\n        The path to the file to get mode from\n\n    \"\"\"\n    # Some filesystems (e.g., CIFS) auto-enable the execute bit on files.  As a result, we\n    # should tolerate the execute bit on the file's owner when validating permissions - thus\n    # the missing one's bit on the third octet.\n    return stat.S_IMODE(os.stat(fname).st_mode) & 0o7677  # Use 4 octets since S_IMODE does the same\n\n\n@contextmanager\ndef secure_write(fname, binary=False):\n    \"\"\"Opens a file in the most restricted pattern available for\n    writing content. This limits the file mode to `0o0600` and yields\n    the resulting opened filed handle.\n\n    Parameters\n    ----------\n\n    fname : unicode\n        The path to the file to write\n\n    binary: boolean\n        Indicates that the file is binary\n    \"\"\"\n    mode = 'wb' if binary else 'w'\n    open_flag = os.O_CREAT | os.O_WRONLY | os.O_TRUNC\n    try:\n        os.remove(fname)\n    except (IOError, OSError):\n        # Skip any issues with the file not existing\n        pass\n\n    if os.name == 'nt':\n        # Python on windows does not respect the group and public bits for chmod, so we need\n        # to take additional steps to secure the contents.\n        # Touch file pre-emptively to avoid editing permissions in open files in Windows\n        fd = os.open(fname, os.O_CREAT | os.O_WRONLY | os.O_TRUNC, 0o0600)\n        os.close(fd)\n        open_flag = os.O_WRONLY | os.O_TRUNC\n        win32_restrict_file_to_user(fname)\n\n    with os.fdopen(os.open(fname, open_flag, 0o0600), mode) as f:\n        if os.name != 'nt':\n            # Enforce that the file got the requested permissions before writing\n            file_mode = get_file_mode(fname)\n            if 0o0600 != file_mode:\n                raise RuntimeError(\"Permissions assignment failed for secure file: '{file}'.\"\n                    \"Got '{permissions}' instead of '0o0600'\"\n                    .format(file=fname, permissions=oct(file_mode)))\n        yield f\n"
  },
  {
    "path": "lib/client/jupyter_core/troubleshoot.py",
    "content": "#!/usr/bin/env python\n\"\"\"\ndisplay environment information that isfrequently\nused to troubleshoot installations of Jupyter or IPython\n\"\"\"\n\n# import argparse\nimport os\nimport platform\nimport subprocess\nimport sys\n\n\n# def get_args():\n#     \"\"\"\n#     TODO: output in JSON or xml? maybe?\n#     \"\"\"\n#     pass\n\ndef subs(cmd):\n    \"\"\"\n    get data from commands that we need to run outside of python\n    \"\"\"\n    try:\n        stdout = subprocess.check_output(cmd)\n        return stdout.decode('utf-8', 'replace').strip()\n    except (OSError, subprocess.CalledProcessError):\n        return None\n\n\ndef get_data():\n    \"\"\"\n    returns a dict of various user environment data\n    \"\"\"\n    env = {}\n    env['path'] = os.environ.get('PATH')\n    env['sys_path'] = sys.path\n    env['sys_exe'] = sys.executable\n    env['sys_version'] = sys.version\n    env['platform'] = platform.platform()\n    # FIXME: which on Windows?\n    if sys.platform == 'win32':\n        env['where'] = subs(['where', 'jupyter'])\n        env['which'] = None\n    else:\n        env['which'] = subs(['which', '-a', 'jupyter'])\n        env['where'] = None\n    env['pip'] = subs([sys.executable, '-m', 'pip', 'list'])\n    env['conda'] = subs(['conda', 'list'])\n    return env\n\n\ndef main():\n    \"\"\"\n    print out useful info\n    \"\"\"\n    #pylint: disable=superfluous-parens\n    # args = get_args()\n    environment_data = get_data()\n\n    print('$PATH:')\n    for directory in environment_data['path'].split(os.pathsep):\n        print('\\t' + directory)\n\n    print('\\n' + 'sys.path:')\n    for directory in environment_data['sys_path']:\n        print('\\t' + directory)\n\n    print('\\n' + 'sys.executable:')\n    print('\\t' + environment_data['sys_exe'])\n\n    print('\\n' + 'sys.version:')\n    if '\\n' in environment_data['sys_version']:\n        for data in environment_data['sys_version'].split('\\n'):\n            print('\\t' + data)\n    else:\n        print('\\t' + environment_data['sys_version'])\n\n    print('\\n' + 'platform.platform():')\n    print('\\t' + environment_data['platform'])\n\n    if environment_data['which']:\n        print('\\n' + 'which -a jupyter:')\n        for line in environment_data['which'].split('\\n'):\n            print('\\t' + line)\n\n    if environment_data['where']:\n        print('\\n' + 'where jupyter:')\n        for line in environment_data['where'].split('\\n'):\n            print('\\t' + line)\n\n    if environment_data['pip']:\n        print('\\n' + 'pip list:')\n        for package in environment_data['pip'].split('\\n'):\n            print('\\t' + package)\n\n    if environment_data['conda']:\n        print('\\n' + 'conda list:')\n        for package in environment_data['conda'].split('\\n'):\n            print('\\t' + package)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "lib/client/jupyter_core/utils/__init__.py",
    "content": "import errno\nimport os\n\ndef ensure_dir_exists(path, mode=0o777):\n    \"\"\"ensure that a directory exists\n\n    If it doesn't exist, try to create it, protecting against a race condition\n    if another process is doing the same.\n\n    The default permissions are determined by the current umask.\n    \"\"\"\n    try:\n        os.makedirs(path, mode=mode)\n    except OSError as e:\n        if e.errno != errno.EEXIST:\n            raise\n    if not os.path.isdir(path):\n        raise IOError(\"%r exists but is not a directory\" % path)\n"
  },
  {
    "path": "lib/client/jupyter_core/utils/shutil_which.py",
    "content": "# Verbatim copy of shutil.which from Python 3.4.3\n# License: PSF\n# Only used on Python < 3\n\nimport os, sys\n\ndef which(cmd, mode=os.F_OK | os.X_OK, path=None):\n    \"\"\"Given a command, mode, and a PATH string, return the path which\n    conforms to the given mode on the PATH, or None if there is no such\n    file.\n\n    `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result\n    of os.environ.get(\"PATH\"), or can be overridden with a custom search\n    path.\n\n    \"\"\"\n    # Check that a given file can be accessed with the correct mode.\n    # Additionally check that `file` is not a directory, as on Windows\n    # directories pass the os.access check.\n    def _access_check(fn, mode):\n        return (os.path.exists(fn) and os.access(fn, mode)\n                and not os.path.isdir(fn))\n\n    # If we're given a path with a directory part, look it up directly rather\n    # than referring to PATH directories. This includes checking relative to the\n    # current directory, e.g. ./script\n    if os.path.dirname(cmd):\n        if _access_check(cmd, mode):\n            return cmd\n        return None\n\n    if path is None:\n        path = os.environ.get(\"PATH\", os.defpath)\n    if not path:\n        return None\n    path = path.split(os.pathsep)\n\n    if sys.platform == \"win32\":\n        # The current directory takes precedence on Windows.\n        if not os.curdir in path:\n            path.insert(0, os.curdir)\n\n        # PATHEXT is necessary to check on Windows.\n        pathext = os.environ.get(\"PATHEXT\", \"\").split(os.pathsep)\n        # See if the given file matches any of the expected path extensions.\n        # This will allow us to short circuit when given \"python.exe\".\n        # If it does match, only test that one, otherwise we have to try\n        # others.\n        if any(cmd.lower().endswith(ext.lower()) for ext in pathext):\n            files = [cmd]\n        else:\n            files = [cmd + ext for ext in pathext]\n    else:\n        # On other platforms you don't have things like PATHEXT to tell you\n        # what file suffixes are executable, so just pass on cmd as-is.\n        files = [cmd]\n\n    seen = set()\n    for dir in path:\n        normdir = os.path.normcase(dir)\n        if not normdir in seen:\n            seen.add(normdir)\n            for thefile in files:\n                name = os.path.join(dir, thefile)\n                if _access_check(name, mode):\n                    return name\n    return None\n"
  },
  {
    "path": "lib/client/jupyter_core/version.py",
    "content": "# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nversion_info = (4, 6, 1)\n\n__version__ = '.'.join(map(str, version_info))\n"
  },
  {
    "path": "lib/client/traitlets/__init__.py",
    "content": "from .traitlets import *\nfrom .utils.importstring import import_item\nfrom ._version import version_info, __version__\n"
  },
  {
    "path": "lib/client/traitlets/_version.py",
    "content": "version_info = (4, 3, 3)\n__version__ = '.'.join(map(str, version_info))\n"
  },
  {
    "path": "lib/client/traitlets/config/__init__.py",
    "content": "# encoding: utf-8\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom .application import *\nfrom .configurable import *\nfrom .loader import Config\n"
  },
  {
    "path": "lib/client/traitlets/config/application.py",
    "content": "# encoding: utf-8\n\"\"\"A base class for a configurable application.\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function\n\nfrom copy import deepcopy\nimport json\nimport logging\nimport os\nimport re\nimport sys\nfrom collections import defaultdict, OrderedDict\n\nfrom decorator import decorator\n\nfrom traitlets.config.configurable import Configurable, SingletonConfigurable\nfrom traitlets.config.loader import (\n    KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound, JSONFileConfigLoader\n)\n\nfrom traitlets.traitlets import (\n    Bool, Unicode, List, Enum, Dict, Instance, TraitError, observe, observe_compat, default,\n)\nfrom ipython_genutils.importstring import import_item\nfrom ipython_genutils.text import indent, wrap_paragraphs, dedent\nfrom ipython_genutils import py3compat\n\nimport six\n\n#-----------------------------------------------------------------------------\n# Descriptions for the various sections\n#-----------------------------------------------------------------------------\n\n# merge flags&aliases into options\noption_description = \"\"\"\nArguments that take values are actually convenience aliases to full\nConfigurables, whose aliases are listed on the help line. For more information\non full configurables, see '--help-all'.\n\"\"\".strip() # trim newlines of front and back\n\nkeyvalue_description = \"\"\"\nParameters are set from command-line arguments of the form:\n`--Class.trait=value`.\nThis line is evaluated in Python, so simple expressions are allowed, e.g.::\n`--C.a='range(3)'` For setting C.a=[0,1,2].\n\"\"\".strip() # trim newlines of front and back\n\n# sys.argv can be missing, for example when python is embedded. See the docs\n# for details: http://docs.python.org/2/c-api/intro.html#embedding-python\nif not hasattr(sys, \"argv\"):\n    sys.argv = [\"\"]\n\nsubcommand_description = \"\"\"\nSubcommands are launched as `{app} cmd [args]`. For information on using\nsubcommand 'cmd', do: `{app} cmd -h`.\n\"\"\"\n# get running program name\n\n#-----------------------------------------------------------------------------\n# Application class\n#-----------------------------------------------------------------------------\n\n\n\n_envvar = os.environ.get('TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR','')\nif _envvar.lower() in {'1','true'}:\n    TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = True\nelif _envvar.lower() in {'0','false',''} :\n    TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR = False\nelse:\n    raise ValueError(\"Unsupported value for environment variable: 'TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR' is set to '%s' which is none of  {'0', '1', 'false', 'true', ''}.\"% _envvar )\n\n\n@decorator\ndef catch_config_error(method, app, *args, **kwargs):\n    \"\"\"Method decorator for catching invalid config (Trait/ArgumentErrors) during init.\n\n    On a TraitError (generally caused by bad config), this will print the trait's\n    message, and exit the app.\n\n    For use on init methods, to prevent invoking excepthook on invalid input.\n    \"\"\"\n    try:\n        return method(app, *args, **kwargs)\n    except (TraitError, ArgumentError) as e:\n        app.print_help()\n        app.log.fatal(\"Bad config encountered during initialization:\")\n        app.log.fatal(str(e))\n        app.log.debug(\"Config at the time: %s\", app.config)\n        app.exit(1)\n\n\nclass ApplicationError(Exception):\n    pass\n\n\nclass LevelFormatter(logging.Formatter):\n    \"\"\"Formatter with additional `highlevel` record\n\n    This field is empty if log level is less than highlevel_limit,\n    otherwise it is formatted with self.highlevel_format.\n\n    Useful for adding 'WARNING' to warning messages,\n    without adding 'INFO' to info, etc.\n    \"\"\"\n    highlevel_limit = logging.WARN\n    highlevel_format = \" %(levelname)s |\"\n\n    def format(self, record):\n        if record.levelno >= self.highlevel_limit:\n            record.highlevel = self.highlevel_format % record.__dict__\n        else:\n            record.highlevel = \"\"\n        return super(LevelFormatter, self).format(record)\n\n\nclass Application(SingletonConfigurable):\n    \"\"\"A singleton application with full configuration support.\"\"\"\n\n    # The name of the application, will usually match the name of the command\n    # line application\n    name = Unicode(u'application')\n\n    # The description of the application that is printed at the beginning\n    # of the help.\n    description = Unicode(u'This is an application.')\n    # default section descriptions\n    option_description = Unicode(option_description)\n    keyvalue_description = Unicode(keyvalue_description)\n    subcommand_description = Unicode(subcommand_description)\n\n    python_config_loader_class = PyFileConfigLoader\n    json_config_loader_class = JSONFileConfigLoader\n\n    # The usage and example string that goes at the end of the help string.\n    examples = Unicode()\n\n    # A sequence of Configurable subclasses whose config=True attributes will\n    # be exposed at the command line.\n    classes = []\n\n    def _classes_inc_parents(self):\n        \"\"\"Iterate through configurable classes, including configurable parents\n\n        Children should always be after parents, and each class should only be\n        yielded once.\n        \"\"\"\n        seen = set()\n        for c in self.classes:\n            # We want to sort parents before children, so we reverse the MRO\n            for parent in reversed(c.mro()):\n                if issubclass(parent, Configurable) and (parent not in seen):\n                    seen.add(parent)\n                    yield parent\n\n    # The version string of this application.\n    version = Unicode(u'0.0')\n\n    # the argv used to initialize the application\n    argv = List()\n\n    # Whether failing to load config files should prevent startup\n    raise_config_file_errors = Bool(TRAITLETS_APPLICATION_RAISE_CONFIG_FILE_ERROR)\n\n    # The log level for the application\n    log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),\n                    default_value=logging.WARN,\n                    help=\"Set the log level by value or name.\").tag(config=True)\n\n    @observe('log_level')\n    @observe_compat\n    def _log_level_changed(self, change):\n        \"\"\"Adjust the log level when log_level is set.\"\"\"\n        new = change.new\n        if isinstance(new, six.string_types):\n            new = getattr(logging, new)\n            self.log_level = new\n        self.log.setLevel(new)\n\n    _log_formatter_cls = LevelFormatter\n\n    log_datefmt = Unicode(\"%Y-%m-%d %H:%M:%S\",\n        help=\"The date format used by logging formatters for %(asctime)s\"\n    ).tag(config=True)\n\n    log_format = Unicode(\"[%(name)s]%(highlevel)s %(message)s\",\n        help=\"The Logging format template\",\n    ).tag(config=True)\n\n    @observe('log_datefmt', 'log_format')\n    @observe_compat\n    def _log_format_changed(self, change):\n        \"\"\"Change the log formatter when log_format is set.\"\"\"\n        _log_handler = self.log.handlers[0]\n        _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt)\n        _log_handler.setFormatter(_log_formatter)\n\n    @default('log')\n    def _log_default(self):\n        \"\"\"Start logging for this application.\n\n        The default is to log to stderr using a StreamHandler, if no default\n        handler already exists.  The log level starts at logging.WARN, but this\n        can be adjusted by setting the ``log_level`` attribute.\n        \"\"\"\n        log = logging.getLogger(self.__class__.__name__)\n        log.setLevel(self.log_level)\n        log.propagate = False\n        _log = log # copied from Logger.hasHandlers() (new in Python 3.2)\n        while _log:\n            if _log.handlers:\n                return log\n            if not _log.propagate:\n                break\n            else:\n                _log = _log.parent\n        if sys.executable and sys.executable.endswith('pythonw.exe'):\n            # this should really go to a file, but file-logging is only\n            # hooked up in parallel applications\n            _log_handler = logging.StreamHandler(open(os.devnull, 'w'))\n        else:\n            _log_handler = logging.StreamHandler()\n        _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt)\n        _log_handler.setFormatter(_log_formatter)\n        log.addHandler(_log_handler)\n        return log\n\n    # the alias map for configurables\n    aliases = Dict({'log-level' : 'Application.log_level'})\n\n    # flags for loading Configurables or store_const style flags\n    # flags are loaded from this dict by '--key' flags\n    # this must be a dict of two-tuples, the first element being the Config/dict\n    # and the second being the help string for the flag\n    flags = Dict()\n    @observe('flags')\n    @observe_compat\n    def _flags_changed(self, change):\n        \"\"\"ensure flags dict is valid\"\"\"\n        new = change.new\n        for key, value in new.items():\n            assert len(value) == 2, \"Bad flag: %r:%s\" % (key, value)\n            assert isinstance(value[0], (dict, Config)), \"Bad flag: %r:%s\" % (key, value)\n            assert isinstance(value[1], six.string_types), \"Bad flag: %r:%s\" % (key, value)\n\n\n    # subcommands for launching other applications\n    # if this is not empty, this will be a parent Application\n    # this must be a dict of two-tuples,\n    # the first element being the application class/import string\n    # and the second being the help string for the subcommand\n    subcommands = Dict()\n    # parse_command_line will initialize a subapp, if requested\n    subapp = Instance('traitlets.config.application.Application', allow_none=True)\n\n    # extra command-line arguments that don't set config values\n    extra_args = List(Unicode())\n\n    cli_config = Instance(Config, (), {},\n        help=\"\"\"The subset of our configuration that came from the command-line\n\n        We re-load this configuration after loading config files,\n        to ensure that it maintains highest priority.\n        \"\"\"\n    )\n\n    _loaded_config_files = List()\n\n    def __init__(self, **kwargs):\n        SingletonConfigurable.__init__(self, **kwargs)\n        # Ensure my class is in self.classes, so my attributes appear in command line\n        # options and config files.\n        cls = self.__class__\n        if cls not in self.classes:\n            if self.classes is cls.classes:\n                # class attr, assign instead of insert\n                cls.classes = [cls] + self.classes\n            else:\n                self.classes.insert(0, self.__class__)\n\n    @observe('config')\n    @observe_compat\n    def _config_changed(self, change):\n        super(Application, self)._config_changed(change)\n        self.log.debug('Config changed:')\n        self.log.debug(repr(change.new))\n\n    @catch_config_error\n    def initialize(self, argv=None):\n        \"\"\"Do the basic steps to configure me.\n\n        Override in subclasses.\n        \"\"\"\n        self.parse_command_line(argv)\n\n\n    def start(self):\n        \"\"\"Start the app mainloop.\n\n        Override in subclasses.\n        \"\"\"\n        if self.subapp is not None:\n            return self.subapp.start()\n\n    def print_alias_help(self):\n        \"\"\"Print the alias part of the help.\"\"\"\n        if not self.aliases:\n            return\n\n        lines = []\n        classdict = {}\n        for cls in self.classes:\n            # include all parents (up to, but excluding Configurable) in available names\n            for c in cls.mro()[:-3]:\n                classdict[c.__name__] = c\n\n        for alias, longname in self.aliases.items():\n            classname, traitname = longname.split('.',1)\n            cls = classdict[classname]\n\n            trait = cls.class_traits(config=True)[traitname]\n            help = cls.class_get_trait_help(trait).splitlines()\n            # reformat first line\n            help[0] = help[0].replace(longname, alias) + ' (%s)'%longname\n            if len(alias) == 1:\n                help[0] = help[0].replace('--%s='%alias, '-%s '%alias)\n            lines.extend(help)\n        # lines.append('')\n        print(os.linesep.join(lines))\n\n    def print_flag_help(self):\n        \"\"\"Print the flag part of the help.\"\"\"\n        if not self.flags:\n            return\n\n        lines = []\n        for m, (cfg,help) in self.flags.items():\n            prefix = '--' if len(m) > 1 else '-'\n            lines.append(prefix+m)\n            lines.append(indent(dedent(help.strip())))\n        # lines.append('')\n        print(os.linesep.join(lines))\n\n    def print_options(self):\n        if not self.flags and not self.aliases:\n            return\n        lines = ['Options']\n        lines.append('-'*len(lines[0]))\n        lines.append('')\n        for p in wrap_paragraphs(self.option_description):\n            lines.append(p)\n            lines.append('')\n        print(os.linesep.join(lines))\n        self.print_flag_help()\n        self.print_alias_help()\n        print()\n\n    def print_subcommands(self):\n        \"\"\"Print the subcommand part of the help.\"\"\"\n        if not self.subcommands:\n            return\n\n        lines = [\"Subcommands\"]\n        lines.append('-'*len(lines[0]))\n        lines.append('')\n        for p in wrap_paragraphs(self.subcommand_description.format(\n                    app=self.name)):\n            lines.append(p)\n            lines.append('')\n        for subc, (cls, help) in self.subcommands.items():\n            lines.append(subc)\n            if help:\n                lines.append(indent(dedent(help.strip())))\n        lines.append('')\n        print(os.linesep.join(lines))\n\n    def print_help(self, classes=False):\n        \"\"\"Print the help for each Configurable class in self.classes.\n\n        If classes=False (the default), only flags and aliases are printed.\n        \"\"\"\n        self.print_description()\n        self.print_subcommands()\n        self.print_options()\n\n        if classes:\n            help_classes = self.classes\n            if help_classes:\n                print(\"Class parameters\")\n                print(\"----------------\")\n                print()\n                for p in wrap_paragraphs(self.keyvalue_description):\n                    print(p)\n                    print()\n\n            for cls in help_classes:\n                cls.class_print_help()\n                print()\n        else:\n            print(\"To see all available configurables, use `--help-all`\")\n            print()\n\n        self.print_examples()\n\n    def document_config_options(self):\n        \"\"\"Generate rST format documentation for the config options this application\n\n        Returns a multiline string.\n        \"\"\"\n        return '\\n'.join(c.class_config_rst_doc()\n                         for c in self._classes_inc_parents())\n\n\n    def print_description(self):\n        \"\"\"Print the application description.\"\"\"\n        for p in wrap_paragraphs(self.description):\n            print(p)\n            print()\n\n    def print_examples(self):\n        \"\"\"Print usage and examples.\n\n        This usage string goes at the end of the command line help string\n        and should contain examples of the application's usage.\n        \"\"\"\n        if self.examples:\n            print(\"Examples\")\n            print(\"--------\")\n            print()\n            print(indent(dedent(self.examples.strip())))\n            print()\n\n    def print_version(self):\n        \"\"\"Print the version string.\"\"\"\n        print(self.version)\n\n    @catch_config_error\n    def initialize_subcommand(self, subc, argv=None):\n        \"\"\"Initialize a subcommand with argv.\"\"\"\n        subapp,help = self.subcommands.get(subc)\n\n        if isinstance(subapp, six.string_types):\n            subapp = import_item(subapp)\n\n        # clear existing instances\n        self.__class__.clear_instance()\n        # instantiate\n        self.subapp = subapp.instance(parent=self)\n        # and initialize subapp\n        self.subapp.initialize(argv)\n\n    def flatten_flags(self):\n        \"\"\"flatten flags and aliases, so cl-args override as expected.\n\n        This prevents issues such as an alias pointing to InteractiveShell,\n        but a config file setting the same trait in TerminalInteraciveShell\n        getting inappropriate priority over the command-line arg.\n\n        Only aliases with exactly one descendent in the class list\n        will be promoted.\n\n        \"\"\"\n        # build a tree of classes in our list that inherit from a particular\n        # it will be a dict by parent classname of classes in our list\n        # that are descendents\n        mro_tree = defaultdict(list)\n        for cls in self.classes:\n            clsname = cls.__name__\n            for parent in cls.mro()[1:-3]:\n                # exclude cls itself and Configurable,HasTraits,object\n                mro_tree[parent.__name__].append(clsname)\n        # flatten aliases, which have the form:\n        # { 'alias' : 'Class.trait' }\n        aliases = {}\n        for alias, cls_trait in self.aliases.items():\n            cls,trait = cls_trait.split('.',1)\n            children = mro_tree[cls]\n            if len(children) == 1:\n                # exactly one descendent, promote alias\n                cls = children[0]\n            aliases[alias] = '.'.join([cls,trait])\n\n        # flatten flags, which are of the form:\n        # { 'key' : ({'Cls' : {'trait' : value}}, 'help')}\n        flags = {}\n        for key, (flagdict, help) in self.flags.items():\n            newflag = {}\n            for cls, subdict in flagdict.items():\n                children = mro_tree[cls]\n                # exactly one descendent, promote flag section\n                if len(children) == 1:\n                    cls = children[0]\n                newflag[cls] = subdict\n            flags[key] = (newflag, help)\n        return flags, aliases\n\n    @catch_config_error\n    def parse_command_line(self, argv=None):\n        \"\"\"Parse the command line arguments.\"\"\"\n        argv = sys.argv[1:] if argv is None else argv\n        self.argv = [ py3compat.cast_unicode(arg) for arg in argv ]\n\n        if argv and argv[0] == 'help':\n            # turn `ipython help notebook` into `ipython notebook -h`\n            argv = argv[1:] + ['-h']\n\n        if self.subcommands and len(argv) > 0:\n            # we have subcommands, and one may have been specified\n            subc, subargv = argv[0], argv[1:]\n            if re.match(r'^\\w(\\-?\\w)*$', subc) and subc in self.subcommands:\n                # it's a subcommand, and *not* a flag or class parameter\n                return self.initialize_subcommand(subc, subargv)\n\n        # Arguments after a '--' argument are for the script IPython may be\n        # about to run, not IPython iteslf. For arguments parsed here (help and\n        # version), we want to only search the arguments up to the first\n        # occurrence of '--', which we're calling interpreted_argv.\n        try:\n            interpreted_argv = argv[:argv.index('--')]\n        except ValueError:\n            interpreted_argv = argv\n\n        if any(x in interpreted_argv for x in ('-h', '--help-all', '--help')):\n            self.print_help('--help-all' in interpreted_argv)\n            self.exit(0)\n\n        if '--version' in interpreted_argv or '-V' in interpreted_argv:\n            self.print_version()\n            self.exit(0)\n\n        # flatten flags&aliases, so cl-args get appropriate priority:\n        flags,aliases = self.flatten_flags()\n        loader = KVArgParseConfigLoader(argv=argv, aliases=aliases,\n                                        flags=flags, log=self.log)\n        self.cli_config = deepcopy(loader.load_config())\n        self.update_config(self.cli_config)\n        # store unparsed args in extra_args\n        self.extra_args = loader.extra_args\n\n    @classmethod\n    def _load_config_files(cls, basefilename, path=None, log=None, raise_config_file_errors=False):\n        \"\"\"Load config files (py,json) by filename and path.\n\n        yield each config object in turn.\n        \"\"\"\n\n        if not isinstance(path, list):\n            path = [path]\n        for path in path[::-1]:\n            # path list is in descending priority order, so load files backwards:\n            pyloader = cls.python_config_loader_class(basefilename+'.py', path=path, log=log)\n            if log:\n                log.debug(\"Looking for %s in %s\", basefilename, path or os.getcwd())\n            jsonloader = cls.json_config_loader_class(basefilename+'.json', path=path, log=log)\n            loaded = []\n            filenames = []\n            for loader in [pyloader, jsonloader]:\n                config = None\n                try:\n                    config = loader.load_config()\n                except ConfigFileNotFound:\n                    pass\n                except Exception:\n                    # try to get the full filename, but it will be empty in the\n                    # unlikely event that the error raised before filefind finished\n                    filename = loader.full_filename or basefilename\n                    # problem while running the file\n                    if raise_config_file_errors:\n                        raise\n                    if log:\n                        log.error(\"Exception while loading config file %s\",\n                                filename, exc_info=True)\n                else:\n                    if log:\n                        log.debug(\"Loaded config file: %s\", loader.full_filename)\n                if config:\n                    for filename, earlier_config in zip(filenames, loaded):\n                        collisions = earlier_config.collisions(config)\n                        if collisions and log:\n                            log.warning(\"Collisions detected in {0} and {1} config files.\"\n                                \" {1} has higher priority: {2}\".format(\n                                filename, loader.full_filename, json.dumps(collisions, indent=2),\n                            ))\n                    yield (config, loader.full_filename)\n                    loaded.append(config)\n                    filenames.append(loader.full_filename)\n\n    @property\n    def loaded_config_files(self):\n        \"\"\"Currently loaded configuration files\"\"\"\n        return self._loaded_config_files[:]\n\n    @catch_config_error\n    def load_config_file(self, filename, path=None):\n        \"\"\"Load config files by filename and path.\"\"\"\n        filename, ext = os.path.splitext(filename)\n        new_config = Config()\n        for (config, filename) in self._load_config_files(filename, path=path, log=self.log,\n            raise_config_file_errors=self.raise_config_file_errors,\n        ):\n            new_config.merge(config)\n            if filename not in self._loaded_config_files:  # only add to list of loaded files if not previously loaded\n                self._loaded_config_files.append(filename)\n        # add self.cli_config to preserve CLI config priority\n        new_config.merge(self.cli_config)\n        self.update_config(new_config)\n\n\n    def _classes_in_config_sample(self):\n        \"\"\"\n        Yields only classes with own traits, and their subclasses.\n\n        Thus, produced sample config-file will contain all classes\n        on which a trait-value may be overridden:\n\n        - either on the class owning the trait,\n        - or on its subclasses, even if those subclasses do not define\n          any traits themselves.\n        \"\"\"\n        cls_to_config = OrderedDict( (cls, bool(cls.class_own_traits(config=True)))\n                              for cls\n                              in self._classes_inc_parents())\n\n        def is_any_parent_included(cls):\n            return any(b in cls_to_config and cls_to_config[b] for b in cls.__bases__)\n\n        ## Mark \"empty\" classes for inclusion if their parents own-traits,\n        #  and loop until no more classes gets marked.\n        #\n        while True:\n            to_incl_orig = cls_to_config.copy()\n            cls_to_config = OrderedDict( (cls, inc_yes or is_any_parent_included(cls))\n                                  for cls, inc_yes\n                                  in cls_to_config.items())\n            if cls_to_config == to_incl_orig:\n                break\n        for cl, inc_yes in cls_to_config.items():\n            if inc_yes:\n                yield cl\n\n    def generate_config_file(self):\n        \"\"\"generate default config file from Configurables\"\"\"\n        lines = [\"# Configuration file for %s.\" % self.name]\n        lines.append('')\n        for cls in self._classes_in_config_sample():\n            lines.append(cls.class_config_section())\n        return '\\n'.join(lines)\n\n    def exit(self, exit_status=0):\n        self.log.debug(\"Exiting application: %s\" % self.name)\n        sys.exit(exit_status)\n\n    @classmethod\n    def launch_instance(cls, argv=None, **kwargs):\n        \"\"\"Launch a global instance of this Application\n\n        If a global instance already exists, this reinitializes and starts it\n        \"\"\"\n        app = cls.instance(**kwargs)\n        app.initialize(argv)\n        app.start()\n\n#-----------------------------------------------------------------------------\n# utility functions, for convenience\n#-----------------------------------------------------------------------------\n\ndef boolean_flag(name, configurable, set_help='', unset_help=''):\n    \"\"\"Helper for building basic --trait, --no-trait flags.\n\n    Parameters\n    ----------\n\n    name : str\n        The name of the flag.\n    configurable : str\n        The 'Class.trait' string of the trait to be set/unset with the flag\n    set_help : unicode\n        help string for --name flag\n    unset_help : unicode\n        help string for --no-name flag\n\n    Returns\n    -------\n\n    cfg : dict\n        A dict with two keys: 'name', and 'no-name', for setting and unsetting\n        the trait, respectively.\n    \"\"\"\n    # default helpstrings\n    set_help = set_help or \"set %s=True\"%configurable\n    unset_help = unset_help or \"set %s=False\"%configurable\n\n    cls,trait = configurable.split('.')\n\n    setter = {cls : {trait : True}}\n    unsetter = {cls : {trait : False}}\n    return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}\n\n\ndef get_config():\n    \"\"\"Get the config object for the global Application instance, if there is one\n\n    otherwise return an empty config object\n    \"\"\"\n    if Application.initialized():\n        return Application.instance().config\n    else:\n        return Config()\n"
  },
  {
    "path": "lib/client/traitlets/config/configurable.py",
    "content": "# encoding: utf-8\n\"\"\"A base class for objects that are configurable.\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom __future__ import print_function, absolute_import\n\nfrom copy import deepcopy\nimport warnings\n\nfrom .loader import Config, LazyConfigValue, _is_section_key\nfrom traitlets.traitlets import HasTraits, Instance, observe, observe_compat, default\nfrom ipython_genutils.text import indent, dedent, wrap_paragraphs\n\n\n#-----------------------------------------------------------------------------\n# Helper classes for Configurables\n#-----------------------------------------------------------------------------\n\n\nclass ConfigurableError(Exception):\n    pass\n\n\nclass MultipleInstanceError(ConfigurableError):\n    pass\n\n#-----------------------------------------------------------------------------\n# Configurable implementation\n#-----------------------------------------------------------------------------\n\nclass Configurable(HasTraits):\n\n    config = Instance(Config, (), {})\n    parent = Instance('traitlets.config.configurable.Configurable', allow_none=True)\n\n    def __init__(self, **kwargs):\n        \"\"\"Create a configurable given a config config.\n\n        Parameters\n        ----------\n        config : Config\n            If this is empty, default values are used. If config is a\n            :class:`Config` instance, it will be used to configure the\n            instance.\n        parent : Configurable instance, optional\n            The parent Configurable instance of this object.\n\n        Notes\n        -----\n        Subclasses of Configurable must call the :meth:`__init__` method of\n        :class:`Configurable` *before* doing anything else and using\n        :func:`super`::\n\n            class MyConfigurable(Configurable):\n                def __init__(self, config=None):\n                    super(MyConfigurable, self).__init__(config=config)\n                    # Then any other code you need to finish initialization.\n\n        This ensures that instances will be configured properly.\n        \"\"\"\n        parent = kwargs.pop('parent', None)\n        if parent is not None:\n            # config is implied from parent\n            if kwargs.get('config', None) is None:\n                kwargs['config'] = parent.config\n            self.parent = parent\n\n        config = kwargs.pop('config', None)\n\n        # load kwarg traits, other than config\n        super(Configurable, self).__init__(**kwargs)\n\n        # load config\n        if config is not None:\n            # We used to deepcopy, but for now we are trying to just save\n            # by reference.  This *could* have side effects as all components\n            # will share config. In fact, I did find such a side effect in\n            # _config_changed below. If a config attribute value was a mutable type\n            # all instances of a component were getting the same copy, effectively\n            # making that a class attribute.\n            # self.config = deepcopy(config)\n            self.config = config\n        else:\n            # allow _config_default to return something\n            self._load_config(self.config)\n\n        # Ensure explicit kwargs are applied after loading config.\n        # This is usually redundant, but ensures config doesn't override\n        # explicitly assigned values.\n        for key, value in kwargs.items():\n            setattr(self, key, value)\n\n    #-------------------------------------------------------------------------\n    # Static trait notifiations\n    #-------------------------------------------------------------------------\n\n    @classmethod\n    def section_names(cls):\n        \"\"\"return section names as a list\"\"\"\n        return  [c.__name__ for c in reversed(cls.__mro__) if\n            issubclass(c, Configurable) and issubclass(cls, c)\n        ]\n\n    def _find_my_config(self, cfg):\n        \"\"\"extract my config from a global Config object\n\n        will construct a Config object of only the config values that apply to me\n        based on my mro(), as well as those of my parent(s) if they exist.\n\n        If I am Bar and my parent is Foo, and their parent is Tim,\n        this will return merge following config sections, in this order::\n\n            [Bar, Foo.bar, Tim.Foo.Bar]\n\n        With the last item being the highest priority.\n        \"\"\"\n        cfgs = [cfg]\n        if self.parent:\n            cfgs.append(self.parent._find_my_config(cfg))\n        my_config = Config()\n        for c in cfgs:\n            for sname in self.section_names():\n                # Don't do a blind getattr as that would cause the config to\n                # dynamically create the section with name Class.__name__.\n                if c._has_section(sname):\n                    my_config.merge(c[sname])\n        return my_config\n\n    def _load_config(self, cfg, section_names=None, traits=None):\n        \"\"\"load traits from a Config object\"\"\"\n\n        if traits is None:\n            traits = self.traits(config=True)\n        if section_names is None:\n            section_names = self.section_names()\n\n        my_config = self._find_my_config(cfg)\n\n        # hold trait notifications until after all config has been loaded\n        with self.hold_trait_notifications():\n            for name, config_value in my_config.items():\n                if name in traits:\n                    if isinstance(config_value, LazyConfigValue):\n                        # ConfigValue is a wrapper for using append / update on containers\n                        # without having to copy the initial value\n                        initial = getattr(self, name)\n                        config_value = config_value.get_value(initial)\n                    # We have to do a deepcopy here if we don't deepcopy the entire\n                    # config object. If we don't, a mutable config_value will be\n                    # shared by all instances, effectively making it a class attribute.\n                    setattr(self, name, deepcopy(config_value))\n                elif not _is_section_key(name) and not isinstance(config_value, Config):\n                    from difflib import get_close_matches\n                    if isinstance(self, LoggingConfigurable):\n                        warn = self.log.warning\n                    else:\n                        warn = lambda msg: warnings.warn(msg, stacklevel=9)\n                    matches = get_close_matches(name, traits)\n                    msg = u\"Config option `{option}` not recognized by `{klass}`.\".format(\n                        option=name, klass=self.__class__.__name__)\n\n                    if len(matches) == 1:\n                        msg += u\"  Did you mean `{matches}`?\".format(matches=matches[0])\n                    elif len(matches) >= 1:\n                        msg +=\"  Did you mean one of: `{matches}`?\".format(matches=', '.join(sorted(matches)))\n                    warn(msg)\n\n    @observe('config')\n    @observe_compat\n    def _config_changed(self, change):\n        \"\"\"Update all the class traits having ``config=True`` in metadata.\n\n        For any class trait with a ``config`` metadata attribute that is\n        ``True``, we update the trait with the value of the corresponding\n        config entry.\n        \"\"\"\n        # Get all traits with a config metadata entry that is True\n        traits = self.traits(config=True)\n\n        # We auto-load config section for this class as well as any parent\n        # classes that are Configurable subclasses.  This starts with Configurable\n        # and works down the mro loading the config for each section.\n        section_names = self.section_names()\n        self._load_config(change.new, traits=traits, section_names=section_names)\n\n    def update_config(self, config):\n        \"\"\"Update config and load the new values\"\"\"\n        # traitlets prior to 4.2 created a copy of self.config in order to trigger change events.\n        # Some projects (IPython < 5) relied upon one side effect of this,\n        # that self.config prior to update_config was not modified in-place.\n        # For backward-compatibility, we must ensure that self.config\n        # is a new object and not modified in-place,\n        # but config consumers should not rely on this behavior.\n        self.config = deepcopy(self.config)\n        # load config\n        self._load_config(config)\n        # merge it into self.config\n        self.config.merge(config)\n        # TODO: trigger change event if/when dict-update change events take place\n        # DO NOT trigger full trait-change\n\n    @classmethod\n    def class_get_help(cls, inst=None):\n        \"\"\"Get the help string for this class in ReST format.\n\n        If `inst` is given, it's current trait values will be used in place of\n        class defaults.\n        \"\"\"\n        assert inst is None or isinstance(inst, cls)\n        final_help = []\n        final_help.append(u'%s options' % cls.__name__)\n        final_help.append(len(final_help[0])*u'-')\n        for k, v in sorted(cls.class_traits(config=True).items()):\n            help = cls.class_get_trait_help(v, inst)\n            final_help.append(help)\n        return '\\n'.join(final_help)\n\n    @classmethod\n    def class_get_trait_help(cls, trait, inst=None):\n        \"\"\"Get the help string for a single trait.\n\n        If `inst` is given, it's current trait values will be used in place of\n        the class default.\n        \"\"\"\n        assert inst is None or isinstance(inst, cls)\n        lines = []\n        header = \"--%s.%s=<%s>\" % (cls.__name__, trait.name, trait.__class__.__name__)\n        lines.append(header)\n        if inst is not None:\n            lines.append(indent('Current: %r' % getattr(inst, trait.name), 4))\n        else:\n            try:\n                dvr = trait.default_value_repr()\n            except Exception:\n                dvr = None # ignore defaults we can't construct\n            if dvr is not None:\n                if len(dvr) > 64:\n                    dvr = dvr[:61]+'...'\n                lines.append(indent('Default: %s' % dvr, 4))\n        if 'Enum' in trait.__class__.__name__:\n            # include Enum choices\n            lines.append(indent('Choices: %r' % (trait.values,)))\n\n        help = trait.help\n        if help != '':\n            help = '\\n'.join(wrap_paragraphs(help, 76))\n            lines.append(indent(help, 4))\n        return '\\n'.join(lines)\n\n    @classmethod\n    def class_print_help(cls, inst=None):\n        \"\"\"Get the help string for a single trait and print it.\"\"\"\n        print(cls.class_get_help(inst))\n\n    @classmethod\n    def class_config_section(cls):\n        \"\"\"Get the config class config section\"\"\"\n        def c(s):\n            \"\"\"return a commented, wrapped block.\"\"\"\n            s = '\\n\\n'.join(wrap_paragraphs(s, 78))\n\n            return '## ' + s.replace('\\n', '\\n#  ')\n\n        # section header\n        breaker = '#' + '-'*78\n        parent_classes = ','.join(p.__name__ for p in cls.__bases__)\n        s = \"# %s(%s) configuration\" % (cls.__name__, parent_classes)\n        lines = [breaker, s, breaker, '']\n        # get the description trait\n        desc = cls.class_traits().get('description')\n        if desc:\n            desc = desc.default_value\n        if not desc:\n            # no description from trait, use __doc__\n            desc = getattr(cls, '__doc__', '')\n        if desc:\n            lines.append(c(desc))\n            lines.append('')\n\n        for name, trait in sorted(cls.class_own_traits(config=True).items()):\n            lines.append(c(trait.help))\n            lines.append('#c.%s.%s = %s' % (cls.__name__, name, trait.default_value_repr()))\n            lines.append('')\n        return '\\n'.join(lines)\n\n    @classmethod\n    def class_config_rst_doc(cls):\n        \"\"\"Generate rST documentation for this class' config options.\n\n        Excludes traits defined on parent classes.\n        \"\"\"\n        lines = []\n        classname = cls.__name__\n        for k, trait in sorted(cls.class_own_traits(config=True).items()):\n            ttype = trait.__class__.__name__\n\n            termline = classname + '.' + trait.name\n\n            # Choices or type\n            if 'Enum' in ttype:\n                # include Enum choices\n                termline += ' : ' + '|'.join(repr(x) for x in trait.values)\n            else:\n                termline += ' : ' + ttype\n            lines.append(termline)\n\n            # Default value\n            try:\n                dvr = trait.default_value_repr()\n            except Exception:\n                dvr = None # ignore defaults we can't construct\n            if dvr is not None:\n                if len(dvr) > 64:\n                    dvr = dvr[:61]+'...'\n                # Double up backslashes, so they get to the rendered docs\n                dvr = dvr.replace('\\\\n', '\\\\\\\\n')\n                lines.append('    Default: ``%s``' % dvr)\n                lines.append('')\n\n            help = trait.help or 'No description'\n            lines.append(indent(dedent(help), 4))\n\n            # Blank line\n            lines.append('')\n\n        return '\\n'.join(lines)\n\n\n\nclass LoggingConfigurable(Configurable):\n    \"\"\"A parent class for Configurables that log.\n\n    Subclasses have a log trait, and the default behavior\n    is to get the logger from the currently running Application.\n    \"\"\"\n\n    log = Instance('logging.Logger')\n    @default('log')\n    def _log_default(self):\n        from traitlets import log\n        return log.get_logger()\n\n\nclass SingletonConfigurable(LoggingConfigurable):\n    \"\"\"A configurable that only allows one instance.\n\n    This class is for classes that should only have one instance of itself\n    or *any* subclass. To create and retrieve such a class use the\n    :meth:`SingletonConfigurable.instance` method.\n    \"\"\"\n\n    _instance = None\n\n    @classmethod\n    def _walk_mro(cls):\n        \"\"\"Walk the cls.mro() for parent classes that are also singletons\n\n        For use in instance()\n        \"\"\"\n\n        for subclass in cls.mro():\n            if issubclass(cls, subclass) and \\\n                    issubclass(subclass, SingletonConfigurable) and \\\n                    subclass != SingletonConfigurable:\n                yield subclass\n\n    @classmethod\n    def clear_instance(cls):\n        \"\"\"unset _instance for this class and singleton parents.\n        \"\"\"\n        if not cls.initialized():\n            return\n        for subclass in cls._walk_mro():\n            if isinstance(subclass._instance, cls):\n                # only clear instances that are instances\n                # of the calling class\n                subclass._instance = None\n\n    @classmethod\n    def instance(cls, *args, **kwargs):\n        \"\"\"Returns a global instance of this class.\n\n        This method create a new instance if none have previously been created\n        and returns a previously created instance is one already exists.\n\n        The arguments and keyword arguments passed to this method are passed\n        on to the :meth:`__init__` method of the class upon instantiation.\n\n        Examples\n        --------\n\n        Create a singleton class using instance, and retrieve it::\n\n            >>> from traitlets.config.configurable import SingletonConfigurable\n            >>> class Foo(SingletonConfigurable): pass\n            >>> foo = Foo.instance()\n            >>> foo == Foo.instance()\n            True\n\n        Create a subclass that is retrived using the base class instance::\n\n            >>> class Bar(SingletonConfigurable): pass\n            >>> class Bam(Bar): pass\n            >>> bam = Bam.instance()\n            >>> bam == Bar.instance()\n            True\n        \"\"\"\n        # Create and save the instance\n        if cls._instance is None:\n            inst = cls(*args, **kwargs)\n            # Now make sure that the instance will also be returned by\n            # parent classes' _instance attribute.\n            for subclass in cls._walk_mro():\n                subclass._instance = inst\n\n        if isinstance(cls._instance, cls):\n            return cls._instance\n        else:\n            raise MultipleInstanceError(\n                'Multiple incompatible subclass instances of '\n                '%s are being created.' % cls.__name__\n            )\n\n    @classmethod\n    def initialized(cls):\n        \"\"\"Has an instance been created?\"\"\"\n        return hasattr(cls, \"_instance\") and cls._instance is not None\n\n\n\n"
  },
  {
    "path": "lib/client/traitlets/config/loader.py",
    "content": "# encoding: utf-8\n\"\"\"A simple configuration system.\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport argparse\nimport copy\nimport logging\nimport os\nimport re\nimport sys\nimport json\nfrom ast import literal_eval\n\nfrom ipython_genutils.path import filefind\nfrom ipython_genutils import py3compat\nfrom ipython_genutils.encoding import DEFAULT_ENCODING\nfrom six import text_type\nfrom traitlets.traitlets import HasTraits, List, Any\n\n#-----------------------------------------------------------------------------\n# Exceptions\n#-----------------------------------------------------------------------------\n\n\nclass ConfigError(Exception):\n    pass\n\nclass ConfigLoaderError(ConfigError):\n    pass\n\nclass ConfigFileNotFound(ConfigError):\n    pass\n\nclass ArgumentError(ConfigLoaderError):\n    pass\n\n#-----------------------------------------------------------------------------\n# Argparse fix\n#-----------------------------------------------------------------------------\n\n# Unfortunately argparse by default prints help messages to stderr instead of\n# stdout.  This makes it annoying to capture long help screens at the command\n# line, since one must know how to pipe stderr, which many users don't know how\n# to do.  So we override the print_help method with one that defaults to\n# stdout and use our class instead.\n\nclass ArgumentParser(argparse.ArgumentParser):\n    \"\"\"Simple argparse subclass that prints help to stdout by default.\"\"\"\n\n    def print_help(self, file=None):\n        if file is None:\n            file = sys.stdout\n        return super(ArgumentParser, self).print_help(file)\n\n    print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__\n\n#-----------------------------------------------------------------------------\n# Config class for holding config information\n#-----------------------------------------------------------------------------\n\nclass LazyConfigValue(HasTraits):\n    \"\"\"Proxy object for exposing methods on configurable containers\n    \n    Exposes:\n    \n    - append, extend, insert on lists\n    - update on dicts\n    - update, add on sets\n    \"\"\"\n    \n    _value = None\n    \n    # list methods\n    _extend = List()\n    _prepend = List()\n    \n    def append(self, obj):\n        self._extend.append(obj)\n    \n    def extend(self, other):\n        self._extend.extend(other)\n    \n    def prepend(self, other):\n        \"\"\"like list.extend, but for the front\"\"\"\n        self._prepend[:0] = other\n    \n    _inserts = List()\n    def insert(self, index, other):\n        if not isinstance(index, int):\n            raise TypeError(\"An integer is required\")\n        self._inserts.append((index, other))\n    \n    # dict methods\n    # update is used for both dict and set\n    _update = Any()\n    def update(self, other):\n        if self._update is None:\n            if isinstance(other, dict):\n                self._update = {}\n            else:\n                self._update = set()\n        self._update.update(other)\n    \n    # set methods\n    def add(self, obj):\n        self.update({obj})\n    \n    def get_value(self, initial):\n        \"\"\"construct the value from the initial one\n        \n        after applying any insert / extend / update changes\n        \"\"\"\n        if self._value is not None:\n            return self._value\n        value = copy.deepcopy(initial)\n        if isinstance(value, list):\n            for idx, obj in self._inserts:\n                value.insert(idx, obj)\n            value[:0] = self._prepend\n            value.extend(self._extend)\n        \n        elif isinstance(value, dict):\n            if self._update:\n                value.update(self._update)\n        elif isinstance(value, set):\n            if self._update:\n                value.update(self._update)\n        self._value = value\n        return value\n    \n    def to_dict(self):\n        \"\"\"return JSONable dict form of my data\n        \n        Currently update as dict or set, extend, prepend as lists, and inserts as list of tuples.\n        \"\"\"\n        d = {}\n        if self._update:\n            d['update'] = self._update\n        if self._extend:\n            d['extend'] = self._extend\n        if self._prepend:\n            d['prepend'] = self._prepend\n        elif self._inserts:\n            d['inserts'] = self._inserts\n        return d\n\n\ndef _is_section_key(key):\n    \"\"\"Is a Config key a section name (does it start with a capital)?\"\"\"\n    if key and key[0].upper()==key[0] and not key.startswith('_'):\n        return True\n    else:\n        return False\n\n\nclass Config(dict):\n    \"\"\"An attribute based dict that can do smart merges.\"\"\"\n\n    def __init__(self, *args, **kwds):\n        dict.__init__(self, *args, **kwds)\n        self._ensure_subconfig()\n    \n    def _ensure_subconfig(self):\n        \"\"\"ensure that sub-dicts that should be Config objects are\n        \n        casts dicts that are under section keys to Config objects,\n        which is necessary for constructing Config objects from dict literals.\n        \"\"\"\n        for key in self:\n            obj = self[key]\n            if _is_section_key(key) \\\n                    and isinstance(obj, dict) \\\n                    and not isinstance(obj, Config):\n                setattr(self, key, Config(obj))\n    \n    def _merge(self, other):\n        \"\"\"deprecated alias, use Config.merge()\"\"\"\n        self.merge(other)\n    \n    def merge(self, other):\n        \"\"\"merge another config object into this one\"\"\"\n        to_update = {}\n        for k, v in other.items():\n            if k not in self:\n                to_update[k] = v\n            else: # I have this key\n                if isinstance(v, Config) and isinstance(self[k], Config):\n                    # Recursively merge common sub Configs\n                    self[k].merge(v)\n                else:\n                    # Plain updates for non-Configs\n                    to_update[k] = v\n\n        self.update(to_update)\n    \n    def collisions(self, other):\n        \"\"\"Check for collisions between two config objects.\n        \n        Returns a dict of the form {\"Class\": {\"trait\": \"collision message\"}}`,\n        indicating which values have been ignored.\n        \n        An empty dict indicates no collisions.\n        \"\"\"\n        collisions = {}\n        for section in self:\n            if section not in other:\n                continue\n            mine = self[section]\n            theirs = other[section]\n            for key in mine:\n                if key in theirs and mine[key] != theirs[key]:\n                    collisions.setdefault(section, {})\n                    collisions[section][key] = \"%r ignored, using %r\" % (mine[key], theirs[key])\n        return collisions\n    \n    def __contains__(self, key):\n        # allow nested contains of the form `\"Section.key\" in config`\n        if '.' in key:\n            first, remainder = key.split('.', 1)\n            if first not in self:\n                return False\n            return remainder in self[first]\n        \n        return super(Config, self).__contains__(key)\n    \n    # .has_key is deprecated for dictionaries.\n    has_key = __contains__\n    \n    def _has_section(self, key):\n        return _is_section_key(key) and key in self\n    \n    def copy(self):\n        return type(self)(dict.copy(self))\n\n    def __copy__(self):\n        return self.copy()\n\n    def __deepcopy__(self, memo):\n        new_config = type(self)()\n        for key, value in self.items():\n            if isinstance(value, (Config, LazyConfigValue)):\n                # deep copy config objects\n                value = copy.deepcopy(value, memo)\n            elif type(value) in {dict, list, set, tuple}:\n                # shallow copy plain container traits\n                value = copy.copy(value)\n            new_config[key] = value\n        return new_config\n    \n    def __getitem__(self, key):\n        try:\n            return dict.__getitem__(self, key)\n        except KeyError:\n            if _is_section_key(key):\n                c = Config()\n                dict.__setitem__(self, key, c)\n                return c\n            elif not key.startswith('_'):\n                # undefined, create lazy value, used for container methods\n                v = LazyConfigValue()\n                dict.__setitem__(self, key, v)\n                return v\n            else:\n                raise KeyError\n\n    def __setitem__(self, key, value):\n        if _is_section_key(key):\n            if not isinstance(value, Config):\n                raise ValueError('values whose keys begin with an uppercase '\n                                 'char must be Config instances: %r, %r' % (key, value))\n        dict.__setitem__(self, key, value)\n\n    def __getattr__(self, key):\n        if key.startswith('__'):\n            return dict.__getattr__(self, key)\n        try:\n            return self.__getitem__(key)\n        except KeyError as e:\n            raise AttributeError(e)\n\n    def __setattr__(self, key, value):\n        if key.startswith('__'):\n            return dict.__setattr__(self, key, value)\n        try:\n            self.__setitem__(key, value)\n        except KeyError as e:\n            raise AttributeError(e)\n\n    def __delattr__(self, key):\n        if key.startswith('__'):\n            return dict.__delattr__(self, key)\n        try:\n            dict.__delitem__(self, key)\n        except KeyError as e:\n            raise AttributeError(e)\n\n\n#-----------------------------------------------------------------------------\n# Config loading classes\n#-----------------------------------------------------------------------------\n\n\nclass ConfigLoader(object):\n    \"\"\"A object for loading configurations from just about anywhere.\n\n    The resulting configuration is packaged as a :class:`Config`.\n\n    Notes\n    -----\n    A :class:`ConfigLoader` does one thing: load a config from a source\n    (file, command line arguments) and returns the data as a :class:`Config` object.\n    There are lots of things that :class:`ConfigLoader` does not do.  It does\n    not implement complex logic for finding config files.  It does not handle\n    default values or merge multiple configs.  These things need to be\n    handled elsewhere.\n    \"\"\"\n\n    def _log_default(self):\n        from traitlets.log import get_logger\n        return get_logger()\n\n    def __init__(self, log=None):\n        \"\"\"A base class for config loaders.\n\n        log : instance of :class:`logging.Logger` to use.\n              By default loger of :meth:`traitlets.config.application.Application.instance()`\n              will be used\n\n        Examples\n        --------\n\n        >>> cl = ConfigLoader()\n        >>> config = cl.load_config()\n        >>> config\n        {}\n        \"\"\"\n        self.clear()\n        if log is None:\n            self.log = self._log_default()\n            self.log.debug('Using default logger')\n        else:\n            self.log = log\n\n    def clear(self):\n        self.config = Config()\n\n    def load_config(self):\n        \"\"\"Load a config from somewhere, return a :class:`Config` instance.\n\n        Usually, this will cause self.config to be set and then returned.\n        However, in most cases, :meth:`ConfigLoader.clear` should be called\n        to erase any previous state.\n        \"\"\"\n        self.clear()\n        return self.config\n\n\nclass FileConfigLoader(ConfigLoader):\n    \"\"\"A base class for file based configurations.\n\n    As we add more file based config loaders, the common logic should go\n    here.\n    \"\"\"\n\n    def __init__(self, filename, path=None, **kw):\n        \"\"\"Build a config loader for a filename and path.\n\n        Parameters\n        ----------\n        filename : str\n            The file name of the config file.\n        path : str, list, tuple\n            The path to search for the config file on, or a sequence of\n            paths to try in order.\n        \"\"\"\n        super(FileConfigLoader, self).__init__(**kw)\n        self.filename = filename\n        self.path = path\n        self.full_filename = ''\n\n    def _find_file(self):\n        \"\"\"Try to find the file by searching the paths.\"\"\"\n        self.full_filename = filefind(self.filename, self.path)\n\nclass JSONFileConfigLoader(FileConfigLoader):\n    \"\"\"A JSON file loader for config\n\n    Can also act as a context manager that rewrite the configuration file to disk on exit.\n\n    Example::\n\n        with JSONFileConfigLoader('myapp.json','/home/jupyter/configurations/') as c:\n            c.MyNewConfigurable.new_value = 'Updated'\n\n    \"\"\"\n\n    def load_config(self):\n        \"\"\"Load the config from a file and return it as a Config object.\"\"\"\n        self.clear()\n        try:\n            self._find_file()\n        except IOError as e:\n            raise ConfigFileNotFound(str(e))\n        dct = self._read_file_as_dict()\n        self.config = self._convert_to_config(dct)\n        return self.config\n\n    def _read_file_as_dict(self):\n        with open(self.full_filename) as f:\n            return json.load(f)\n\n    def _convert_to_config(self, dictionary):\n        if 'version' in dictionary:\n            version = dictionary.pop('version')\n        else:\n            version = 1\n\n        if version == 1:\n            return Config(dictionary)\n        else:\n            raise ValueError('Unknown version of JSON config file: {version}'.format(version=version))\n\n    def __enter__(self):\n        self.load_config()\n        return self.config\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        \"\"\"\n        Exit the context manager but do not handle any errors.\n\n        In case of any error, we do not want to write the potentially broken\n        configuration to disk.\n        \"\"\"\n        self.config.version = 1\n        json_config = json.dumps(self.config, indent=2)\n        with open(self.full_filename, 'w') as f:\n            f.write(json_config)\n\n\n\nclass PyFileConfigLoader(FileConfigLoader):\n    \"\"\"A config loader for pure python files.\n\n    This is responsible for locating a Python config file by filename and\n    path, then executing it to construct a Config object.\n    \"\"\"\n\n    def load_config(self):\n        \"\"\"Load the config from a file and return it as a Config object.\"\"\"\n        self.clear()\n        try:\n            self._find_file()\n        except IOError as e:\n            raise ConfigFileNotFound(str(e))\n        self._read_file_as_dict()\n        return self.config\n    \n    def load_subconfig(self, fname, path=None):\n        \"\"\"Injected into config file namespace as load_subconfig\"\"\"\n        if path is None:\n            path = self.path\n        \n        loader = self.__class__(fname, path)\n        try:\n            sub_config = loader.load_config()\n        except ConfigFileNotFound:\n            # Pass silently if the sub config is not there,\n            # treat it as an empty config file.\n            pass\n        else:\n            self.config.merge(sub_config)\n    \n    def _read_file_as_dict(self):\n        \"\"\"Load the config file into self.config, with recursive loading.\"\"\"\n        def get_config():\n            \"\"\"Unnecessary now, but a deprecation warning is more trouble than it's worth.\"\"\"\n            return self.config\n        \n        namespace = dict(\n            c=self.config,\n            load_subconfig=self.load_subconfig,\n            get_config=get_config,\n            __file__=self.full_filename,\n        )\n        fs_encoding = sys.getfilesystemencoding() or 'ascii'\n        conf_filename = self.full_filename.encode(fs_encoding)\n        py3compat.execfile(conf_filename, namespace)\n\n\nclass CommandLineConfigLoader(ConfigLoader):\n    \"\"\"A config loader for command line arguments.\n\n    As we add more command line based loaders, the common logic should go\n    here.\n    \"\"\"\n\n    def _exec_config_str(self, lhs, rhs):\n        \"\"\"execute self.config.<lhs> = <rhs>\n        \n        * expands ~ with expanduser\n        * tries to assign with literal_eval, otherwise assigns with just the string,\n          allowing `--C.a=foobar` and `--C.a=\"foobar\"` to be equivalent.  *Not*\n          equivalent are `--C.a=4` and `--C.a='4'`.\n        \"\"\"\n        rhs = os.path.expanduser(rhs)\n        try:\n            # Try to see if regular Python syntax will work. This\n            # won't handle strings as the quote marks are removed\n            # by the system shell.\n            value = literal_eval(rhs)\n        except (NameError, SyntaxError, ValueError):\n            # This case happens if the rhs is a string.\n            value = rhs\n\n        exec(u'self.config.%s = value' % lhs)\n\n    def _load_flag(self, cfg):\n        \"\"\"update self.config from a flag, which can be a dict or Config\"\"\"\n        if isinstance(cfg, (dict, Config)):\n            # don't clobber whole config sections, update\n            # each section from config:\n            for sec,c in cfg.items():\n                self.config[sec].update(c)\n        else:\n            raise TypeError(\"Invalid flag: %r\" % cfg)\n\n# raw --identifier=value pattern\n# but *also* accept '-' as wordsep, for aliases\n# accepts:  --foo=a\n#           --Class.trait=value\n#           --alias-name=value\n# rejects:  -foo=value\n#           --foo\n#           --Class.trait\nkv_pattern = re.compile(r'\\-\\-[A-Za-z][\\w\\-]*(\\.[\\w\\-]+)*\\=.*')\n\n# just flags, no assignments, with two *or one* leading '-'\n# accepts:  --foo\n#           -foo-bar-again\n# rejects:  --anything=anything\n#           --two.word\n\nflag_pattern = re.compile(r'\\-\\-?\\w[\\-\\w]*$')\n\nclass KeyValueConfigLoader(CommandLineConfigLoader):\n    \"\"\"A config loader that loads key value pairs from the command line.\n\n    This allows command line options to be gives in the following form::\n\n        ipython --profile=\"foo\" --InteractiveShell.autocall=False\n    \"\"\"\n\n    def __init__(self, argv=None, aliases=None, flags=None, **kw):\n        \"\"\"Create a key value pair config loader.\n\n        Parameters\n        ----------\n        argv : list\n            A list that has the form of sys.argv[1:] which has unicode\n            elements of the form u\"key=value\". If this is None (default),\n            then sys.argv[1:] will be used.\n        aliases : dict\n            A dict of aliases for configurable traits.\n            Keys are the short aliases, Values are the resolved trait.\n            Of the form: `{'alias' : 'Configurable.trait'}`\n        flags : dict\n            A dict of flags, keyed by str name. Vaues can be Config objects,\n            dicts, or \"key=value\" strings.  If Config or dict, when the flag\n            is triggered, The flag is loaded as `self.config.update(m)`.\n\n        Returns\n        -------\n        config : Config\n            The resulting Config object.\n\n        Examples\n        --------\n\n            >>> from traitlets.config.loader import KeyValueConfigLoader\n            >>> cl = KeyValueConfigLoader()\n            >>> d = cl.load_config([\"--A.name='brian'\",\"--B.number=0\"])\n            >>> sorted(d.items())\n            [('A', {'name': 'brian'}), ('B', {'number': 0})]\n        \"\"\"\n        super(KeyValueConfigLoader, self).__init__(**kw)\n        if argv is None:\n            argv = sys.argv[1:]\n        self.argv = argv\n        self.aliases = aliases or {}\n        self.flags = flags or {}\n\n\n    def clear(self):\n        super(KeyValueConfigLoader, self).clear()\n        self.extra_args = []\n\n\n    def _decode_argv(self, argv, enc=None):\n        \"\"\"decode argv if bytes, using stdin.encoding, falling back on default enc\"\"\"\n        uargv = []\n        if enc is None:\n            enc = DEFAULT_ENCODING\n        for arg in argv:\n            if not isinstance(arg, text_type):\n                # only decode if not already decoded\n                arg = arg.decode(enc)\n            uargv.append(arg)\n        return uargv\n\n\n    def load_config(self, argv=None, aliases=None, flags=None):\n        \"\"\"Parse the configuration and generate the Config object.\n\n        After loading, any arguments that are not key-value or\n        flags will be stored in self.extra_args - a list of\n        unparsed command-line arguments.  This is used for\n        arguments such as input files or subcommands.\n\n        Parameters\n        ----------\n        argv : list, optional\n            A list that has the form of sys.argv[1:] which has unicode\n            elements of the form u\"key=value\". If this is None (default),\n            then self.argv will be used.\n        aliases : dict\n            A dict of aliases for configurable traits.\n            Keys are the short aliases, Values are the resolved trait.\n            Of the form: `{'alias' : 'Configurable.trait'}`\n        flags : dict\n            A dict of flags, keyed by str name. Values can be Config objects\n            or dicts.  When the flag is triggered, The config is loaded as\n            `self.config.update(cfg)`.\n        \"\"\"\n        self.clear()\n        if argv is None:\n            argv = self.argv\n        if aliases is None:\n            aliases = self.aliases\n        if flags is None:\n            flags = self.flags\n\n        # ensure argv is a list of unicode strings:\n        uargv = self._decode_argv(argv)\n        for idx,raw in enumerate(uargv):\n            # strip leading '-'\n            item = raw.lstrip('-')\n\n            if raw == '--':\n                # don't parse arguments after '--'\n                # this is useful for relaying arguments to scripts, e.g.\n                # ipython -i foo.py --matplotlib=qt -- args after '--' go-to-foo.py\n                self.extra_args.extend(uargv[idx+1:])\n                break\n\n            if kv_pattern.match(raw):\n                lhs,rhs = item.split('=',1)\n                # Substitute longnames for aliases.\n                if lhs in aliases:\n                    lhs = aliases[lhs]\n                if '.' not in lhs:\n                    # probably a mistyped alias, but not technically illegal\n                    self.log.warning(\"Unrecognized alias: '%s', it will probably have no effect.\", raw)\n                try:\n                    self._exec_config_str(lhs, rhs)\n                except Exception:\n                    raise ArgumentError(\"Invalid argument: '%s'\" % raw)\n\n            elif flag_pattern.match(raw):\n                if item in flags:\n                    cfg,_ = flags[item]\n                    self._load_flag(cfg)\n                else:\n                    raise ArgumentError(\"Unrecognized flag: '%s'\"%raw)\n            elif raw.startswith('-'):\n                kv = '--'+item\n                if kv_pattern.match(kv):\n                    raise ArgumentError(\"Invalid argument: '%s', did you mean '%s'?\"%(raw, kv))\n                else:\n                    raise ArgumentError(\"Invalid argument: '%s'\"%raw)\n            else:\n                # keep all args that aren't valid in a list,\n                # in case our parent knows what to do with them.\n                self.extra_args.append(item)\n        return self.config\n\nclass ArgParseConfigLoader(CommandLineConfigLoader):\n    \"\"\"A loader that uses the argparse module to load from the command line.\"\"\"\n\n    def __init__(self, argv=None, aliases=None, flags=None, log=None,  *parser_args, **parser_kw):\n        \"\"\"Create a config loader for use with argparse.\n\n        Parameters\n        ----------\n\n        argv : optional, list\n          If given, used to read command-line arguments from, otherwise\n          sys.argv[1:] is used.\n\n        parser_args : tuple\n          A tuple of positional arguments that will be passed to the\n          constructor of :class:`argparse.ArgumentParser`.\n\n        parser_kw : dict\n          A tuple of keyword arguments that will be passed to the\n          constructor of :class:`argparse.ArgumentParser`.\n\n        Returns\n        -------\n        config : Config\n            The resulting Config object.\n        \"\"\"\n        super(CommandLineConfigLoader, self).__init__(log=log)\n        self.clear()\n        if argv is None:\n            argv = sys.argv[1:]\n        self.argv = argv\n        self.aliases = aliases or {}\n        self.flags = flags or {}\n\n        self.parser_args = parser_args\n        self.version = parser_kw.pop(\"version\", None)\n        kwargs = dict(argument_default=argparse.SUPPRESS)\n        kwargs.update(parser_kw)\n        self.parser_kw = kwargs\n\n    def load_config(self, argv=None, aliases=None, flags=None):\n        \"\"\"Parse command line arguments and return as a Config object.\n\n        Parameters\n        ----------\n\n        args : optional, list\n          If given, a list with the structure of sys.argv[1:] to parse\n          arguments from. If not given, the instance's self.argv attribute\n          (given at construction time) is used.\"\"\"\n        self.clear()\n        if argv is None:\n            argv = self.argv\n        if aliases is None:\n            aliases = self.aliases\n        if flags is None:\n            flags = self.flags\n        self._create_parser(aliases, flags)\n        self._parse_args(argv)\n        self._convert_to_config()\n        return self.config\n\n    def get_extra_args(self):\n        if hasattr(self, 'extra_args'):\n            return self.extra_args\n        else:\n            return []\n\n    def _create_parser(self, aliases=None, flags=None):\n        self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)\n        self._add_arguments(aliases, flags)\n\n    def _add_arguments(self, aliases=None, flags=None):\n        raise NotImplementedError(\"subclasses must implement _add_arguments\")\n\n    def _parse_args(self, args):\n        \"\"\"self.parser->self.parsed_data\"\"\"\n        # decode sys.argv to support unicode command-line options\n        enc = DEFAULT_ENCODING\n        uargs = [py3compat.cast_unicode(a, enc) for a in args]\n        self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)\n\n    def _convert_to_config(self):\n        \"\"\"self.parsed_data->self.config\"\"\"\n        for k, v in vars(self.parsed_data).items():\n            exec(\"self.config.%s = v\"%k, locals(), globals())\n\nclass KVArgParseConfigLoader(ArgParseConfigLoader):\n    \"\"\"A config loader that loads aliases and flags with argparse,\n    but will use KVLoader for the rest.  This allows better parsing\n    of common args, such as `ipython -c 'print 5'`, but still gets\n    arbitrary config with `ipython --InteractiveShell.use_readline=False`\"\"\"\n\n    def _add_arguments(self, aliases=None, flags=None):\n        self.alias_flags = {}\n        # print aliases, flags\n        if aliases is None:\n            aliases = self.aliases\n        if flags is None:\n            flags = self.flags\n        paa = self.parser.add_argument\n        for key,value in aliases.items():\n            if key in flags:\n                # flags\n                nargs = '?'\n            else:\n                nargs = None\n            if len(key) == 1:\n                paa('-'+key, '--'+key, type=text_type, dest=value, nargs=nargs)\n            else:\n                paa('--'+key, type=text_type, dest=value, nargs=nargs)\n        for key, (value, help) in flags.items():\n            if key in self.aliases:\n                #\n                self.alias_flags[self.aliases[key]] = value\n                continue\n            if len(key) == 1:\n                paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)\n            else:\n                paa('--'+key, action='append_const', dest='_flags', const=value)\n\n    def _convert_to_config(self):\n        \"\"\"self.parsed_data->self.config, parse unrecognized extra args via KVLoader.\"\"\"\n        # remove subconfigs list from namespace before transforming the Namespace\n        if '_flags' in self.parsed_data:\n            subcs = self.parsed_data._flags\n            del self.parsed_data._flags\n        else:\n            subcs = []\n\n        for k, v in vars(self.parsed_data).items():\n            if v is None:\n                # it was a flag that shares the name of an alias\n                subcs.append(self.alias_flags[k])\n            else:\n                # eval the KV assignment\n                self._exec_config_str(k, v)\n\n        for subc in subcs:\n            self._load_flag(subc)\n\n        if self.extra_args:\n            sub_parser = KeyValueConfigLoader(log=self.log)\n            sub_parser.load_config(self.extra_args)\n            self.config.merge(sub_parser.config)\n            self.extra_args = sub_parser.extra_args\n\n\ndef load_pyconfig_files(config_files, path):\n    \"\"\"Load multiple Python config files, merging each of them in turn.\n\n    Parameters\n    ==========\n    config_files : list of str\n        List of config files names to load and merge into the config.\n    path : unicode\n        The full path to the location of the config files.\n    \"\"\"\n    config = Config()\n    for cf in config_files:\n        loader = PyFileConfigLoader(cf, path=path)\n        try:\n            next_config = loader.load_config()\n        except ConfigFileNotFound:\n            pass\n        except:\n            raise\n        else:\n            config.merge(next_config)\n    return config\n"
  },
  {
    "path": "lib/client/traitlets/config/manager.py",
    "content": "\"\"\"Manager to read and modify config data in JSON files.\n\"\"\"\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\nimport errno\nimport io\nimport json\nimport os\n\nfrom six import PY3\nfrom traitlets.config import LoggingConfigurable\nfrom traitlets.traitlets import Unicode\n\n\ndef recursive_update(target, new):\n    \"\"\"Recursively update one dictionary using another.\n\n    None values will delete their keys.\n    \"\"\"\n    for k, v in new.items():\n        if isinstance(v, dict):\n            if k not in target:\n                target[k] = {}\n            recursive_update(target[k], v)\n            if not target[k]:\n                # Prune empty subdicts\n                del target[k]\n\n        elif v is None:\n            target.pop(k, None)\n\n        else:\n            target[k] = v\n\n\nclass BaseJSONConfigManager(LoggingConfigurable):\n    \"\"\"General JSON config manager\n    \n    Deals with persisting/storing config in a json file\n    \"\"\"\n\n    config_dir = Unicode('.')\n\n    def ensure_config_dir_exists(self):\n        try:\n            os.makedirs(self.config_dir, 0o755)\n        except OSError as e:\n            if e.errno != errno.EEXIST:\n                raise\n\n    def file_name(self, section_name):\n        return os.path.join(self.config_dir, section_name+'.json')\n\n    def get(self, section_name):\n        \"\"\"Retrieve the config data for the specified section.\n\n        Returns the data as a dictionary, or an empty dictionary if the file\n        doesn't exist.\n        \"\"\"\n        filename = self.file_name(section_name)\n        if os.path.isfile(filename):\n            with io.open(filename, encoding='utf-8') as f:\n                return json.load(f)\n        else:\n            return {}\n\n    def set(self, section_name, data):\n        \"\"\"Store the given config data.\n        \"\"\"\n        filename = self.file_name(section_name)\n        self.ensure_config_dir_exists()\n\n        if PY3:\n            f = io.open(filename, 'w', encoding='utf-8')\n        else:\n            f = open(filename, 'wb')\n        with f:\n            json.dump(data, f, indent=2)\n\n    def update(self, section_name, new_data):\n        \"\"\"Modify the config section by recursively updating it with new_data.\n\n        Returns the modified config data as a dictionary.\n        \"\"\"\n        data = self.get(section_name)\n        recursive_update(data, new_data)\n        self.set(section_name, data)\n        return data\n"
  },
  {
    "path": "lib/client/traitlets/log.py",
    "content": "\"\"\"Grab the global logger instance.\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nimport logging\n\n_logger = None\n\ndef get_logger():\n    \"\"\"Grab the global logger instance.\n\n    If a global Application is instantiated, grab its logger.\n    Otherwise, grab the root logger.\n    \"\"\"\n    global _logger\n\n    if _logger is None:\n        from .config import Application\n        if Application.initialized():\n            _logger = Application.instance().log\n        else:\n            _logger = logging.getLogger('traitlets')\n            # Add a NullHandler to silence warnings about not being\n            # initialized, per best practice for libraries.\n            _logger.addHandler(logging.NullHandler())\n    return _logger\n"
  },
  {
    "path": "lib/client/traitlets/traitlets.py",
    "content": "# encoding: utf-8\n\"\"\"\nA lightweight Traits like module.\n\nThis is designed to provide a lightweight, simple, pure Python version of\nmany of the capabilities of enthought.traits.  This includes:\n\n* Validation\n* Type specification with defaults\n* Static and dynamic notification\n* Basic predefined types\n* An API that is similar to enthought.traits\n\nWe don't support:\n\n* Delegation\n* Automatic GUI generation\n* A full set of trait types.  Most importantly, we don't provide container\n  traits (list, dict, tuple) that can trigger notifications if their\n  contents change.\n* API compatibility with enthought.traits\n\nThere are also some important difference in our design:\n\n* enthought.traits does not validate default values.  We do.\n\nWe choose to create this module because we need these capabilities, but\nwe need them to be pure Python so they work in all Python implementations,\nincluding Jython and IronPython.\n\nInheritance diagram:\n\n.. inheritance-diagram:: traitlets.traitlets\n   :parts: 3\n\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n#\n# Adapted from enthought.traits, Copyright (c) Enthought, Inc.,\n# also under the terms of the Modified BSD License.\n\nimport contextlib\nimport inspect\nimport os\nimport re\nimport sys\nimport types\nimport enum\ntry:\n    from types import ClassType, InstanceType\n    ClassTypes = (ClassType, type)\nexcept:\n    ClassTypes = (type,)\nfrom warnings import warn, warn_explicit\n\nimport six\n\nfrom .utils.getargspec import getargspec\nfrom .utils.importstring import import_item\nfrom .utils.sentinel import Sentinel\nfrom .utils.bunch import Bunch\n\nSequenceTypes = (list, tuple, set, frozenset)\n\n#-----------------------------------------------------------------------------\n# Basic classes\n#-----------------------------------------------------------------------------\n\n\nUndefined = Sentinel('Undefined', 'traitlets',\n'''\nUsed in Traitlets to specify that no defaults are set in kwargs\n'''\n)\n\nAll = Sentinel('All', 'traitlets',\n'''\nUsed in Traitlets to listen to all types of notification or to notifications\nfrom all trait attributes.\n'''\n)\n\n# Deprecated alias\nNoDefaultSpecified = Undefined\n\nclass TraitError(Exception):\n    pass\n\n#-----------------------------------------------------------------------------\n# Utilities\n#-----------------------------------------------------------------------------\n\nfrom ipython_genutils.py3compat import cast_unicode_py2\n\n_name_re = re.compile(r\"[a-zA-Z_][a-zA-Z0-9_]*$\")\n\ndef isidentifier(s):\n    if six.PY2:\n        return bool(_name_re.match(s))\n    else:\n        return s.isidentifier()\n\n_deprecations_shown = set()\ndef _should_warn(key):\n    \"\"\"Add our own checks for too many deprecation warnings.\n\n    Limit to once per package.\n    \"\"\"\n    env_flag = os.environ.get('TRAITLETS_ALL_DEPRECATIONS')\n    if env_flag and env_flag != '0':\n        return True\n\n    if key not in _deprecations_shown:\n        _deprecations_shown.add(key)\n        return True\n    else:\n        return False\n\ndef _deprecated_method(method, cls, method_name, msg):\n    \"\"\"Show deprecation warning about a magic method definition.\n\n    Uses warn_explicit to bind warning to method definition instead of triggering code,\n    which isn't relevant.\n    \"\"\"\n    warn_msg = \"{classname}.{method_name} is deprecated in traitlets 4.1: {msg}\".format(\n        classname=cls.__name__, method_name=method_name, msg=msg\n    )\n\n    for parent in inspect.getmro(cls):\n        if method_name in parent.__dict__:\n            cls = parent\n            break\n    # limit deprecation messages to once per package\n    package_name = cls.__module__.split('.', 1)[0]\n    key = (package_name, msg)\n    if not _should_warn(key):\n        return\n    try:\n        fname = inspect.getsourcefile(method) or \"<unknown>\"\n        lineno = inspect.getsourcelines(method)[1] or 0\n    except (IOError, TypeError) as e:\n        # Failed to inspect for some reason\n        warn(warn_msg + ('\\n(inspection failed) %s' % e), DeprecationWarning)\n    else:\n        warn_explicit(warn_msg, DeprecationWarning, fname, lineno)\n\ndef class_of(object):\n    \"\"\" Returns a string containing the class name of an object with the\n    correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image',\n    'a PlotValue').\n    \"\"\"\n    if isinstance( object, six.string_types ):\n        return add_article( object )\n\n    return add_article( object.__class__.__name__ )\n\n\ndef add_article(name):\n    \"\"\" Returns a string containing the correct indefinite article ('a' or 'an')\n    prefixed to the specified string.\n    \"\"\"\n    if name[:1].lower() in 'aeiou':\n       return 'an ' + name\n\n    return 'a ' + name\n\n\ndef repr_type(obj):\n    \"\"\" Return a string representation of a value and its type for readable\n    error messages.\n    \"\"\"\n    the_type = type(obj)\n    if six.PY2 and the_type is InstanceType:\n        # Old-style class.\n        the_type = obj.__class__\n    msg = '%r %r' % (obj, the_type)\n    return msg\n\n\ndef is_trait(t):\n    \"\"\" Returns whether the given value is an instance or subclass of TraitType.\n    \"\"\"\n    return (isinstance(t, TraitType) or\n            (isinstance(t, type) and issubclass(t, TraitType)))\n\n\ndef parse_notifier_name(names):\n    \"\"\"Convert the name argument to a list of names.\n\n    Examples\n    --------\n\n    >>> parse_notifier_name([])\n    [All]\n    >>> parse_notifier_name('a')\n    ['a']\n    >>> parse_notifier_name(['a', 'b'])\n    ['a', 'b']\n    >>> parse_notifier_name(All)\n    [All]\n    \"\"\"\n    if names is All or isinstance(names, six.string_types):\n        return [names]\n    else:\n        if not names or All in names:\n            return [All]\n        for n in names:\n            if not isinstance(n, six.string_types):\n                raise TypeError(\"names must be strings, not %r\" % n)\n        return names\n\n\nclass _SimpleTest:\n    def __init__ ( self, value ): self.value = value\n    def __call__ ( self, test  ):\n        return test == self.value\n    def __repr__(self):\n        return \"<SimpleTest(%r)\" % self.value\n    def __str__(self):\n        return self.__repr__()\n\n\ndef getmembers(object, predicate=None):\n    \"\"\"A safe version of inspect.getmembers that handles missing attributes.\n\n    This is useful when there are descriptor based attributes that for\n    some reason raise AttributeError even though they exist.  This happens\n    in zope.inteface with the __provides__ attribute.\n    \"\"\"\n    results = []\n    for key in dir(object):\n        try:\n            value = getattr(object, key)\n        except AttributeError:\n            pass\n        else:\n            if not predicate or predicate(value):\n                results.append((key, value))\n    results.sort()\n    return results\n\ndef _validate_link(*tuples):\n    \"\"\"Validate arguments for traitlet link functions\"\"\"\n    for t in tuples:\n        if not len(t) == 2:\n            raise TypeError(\"Each linked traitlet must be specified as (HasTraits, 'trait_name'), not %r\" % t)\n        obj, trait_name = t\n        if not isinstance(obj, HasTraits):\n            raise TypeError(\"Each object must be HasTraits, not %r\" % type(obj))\n        if not trait_name in obj.traits():\n            raise TypeError(\"%r has no trait %r\" % (obj, trait_name))\n\nclass link(object):\n    \"\"\"Link traits from different objects together so they remain in sync.\n\n    Parameters\n    ----------\n    source : (object / attribute name) pair\n    target : (object / attribute name) pair\n\n    Examples\n    --------\n\n    >>> c = link((src, 'value'), (tgt, 'value'))\n    >>> src.value = 5  # updates other objects as well\n    \"\"\"\n    updating = False\n\n    def __init__(self, source, target):\n        _validate_link(source, target)\n        self.source, self.target = source, target\n        try:\n            setattr(target[0], target[1], getattr(source[0], source[1]))\n        finally:\n            source[0].observe(self._update_target, names=source[1])\n            target[0].observe(self._update_source, names=target[1])\n\n    @contextlib.contextmanager\n    def _busy_updating(self):\n        self.updating = True\n        try:\n            yield\n        finally:\n            self.updating = False\n\n    def _update_target(self, change):\n        if self.updating:\n            return\n        with self._busy_updating():\n            setattr(self.target[0], self.target[1], change.new)\n\n    def _update_source(self, change):\n        if self.updating:\n            return\n        with self._busy_updating():\n            setattr(self.source[0], self.source[1], change.new)\n\n    def unlink(self):\n        self.source[0].unobserve(self._update_target, names=self.source[1])\n        self.target[0].unobserve(self._update_source, names=self.target[1])\n        self.source, self.target = None, None\n\n\nclass directional_link(object):\n    \"\"\"Link the trait of a source object with traits of target objects.\n\n    Parameters\n    ----------\n    source : (object, attribute name) pair\n    target : (object, attribute name) pair\n    transform: callable (optional)\n        Data transformation between source and target.\n\n    Examples\n    --------\n\n    >>> c = directional_link((src, 'value'), (tgt, 'value'))\n    >>> src.value = 5  # updates target objects\n    >>> tgt.value = 6  # does not update source object\n    \"\"\"\n    updating = False\n\n    def __init__(self, source, target, transform=None):\n        self._transform = transform if transform else lambda x: x\n        _validate_link(source, target)\n        self.source, self.target = source, target\n        try:\n            setattr(target[0], target[1],\n                    self._transform(getattr(source[0], source[1])))\n        finally:\n            self.source[0].observe(self._update, names=self.source[1])\n\n    @contextlib.contextmanager\n    def _busy_updating(self):\n        self.updating = True\n        try:\n            yield\n        finally:\n            self.updating = False\n\n    def _update(self, change):\n        if self.updating:\n            return\n        with self._busy_updating():\n            setattr(self.target[0], self.target[1],\n                    self._transform(change.new))\n\n    def unlink(self):\n        self.source[0].unobserve(self._update, names=self.source[1])\n        self.source, self.target = None, None\n\ndlink = directional_link\n\n\n#-----------------------------------------------------------------------------\n# Base Descriptor Class\n#-----------------------------------------------------------------------------\n\n\nclass BaseDescriptor(object):\n    \"\"\"Base descriptor class\n\n    Notes\n    -----\n    This implements Python's descriptor prototol.\n\n    This class is the base class for all such descriptors.  The\n    only magic we use is a custom metaclass for the main :class:`HasTraits`\n    class that does the following:\n\n    1. Sets the :attr:`name` attribute of every :class:`BaseDescriptor`\n       instance in the class dict to the name of the attribute.\n    2. Sets the :attr:`this_class` attribute of every :class:`BaseDescriptor`\n       instance in the class dict to the *class* that declared the trait.\n       This is used by the :class:`This` trait to allow subclasses to\n       accept superclasses for :class:`This` values.\n    \"\"\"\n\n    name = None\n    this_class = None\n\n    def class_init(self, cls, name):\n        \"\"\"Part of the initialization which may depend on the underlying\n        HasDescriptors class.\n\n        It is typically overloaded for specific types.\n\n        This method is called by :meth:`MetaHasDescriptors.__init__`\n        passing the class (`cls`) and `name` under which the descriptor\n        has been assigned.\n        \"\"\"\n        self.this_class = cls\n        self.name = name\n\n    def instance_init(self, obj):\n        \"\"\"Part of the initialization which may depend on the underlying\n        HasDescriptors instance.\n\n        It is typically overloaded for specific types.\n\n        This method is called by :meth:`HasTraits.__new__` and in the\n        :meth:`BaseDescriptor.instance_init` method of descriptors holding\n        other descriptors.\n        \"\"\"\n        pass\n\n\nclass TraitType(BaseDescriptor):\n    \"\"\"A base class for all trait types.\n    \"\"\"\n\n    metadata = {}\n    default_value = Undefined\n    allow_none = False\n    read_only = False\n    info_text = 'any value'\n\n    def __init__(self, default_value=Undefined, allow_none=False, read_only=None, help=None,\n        config=None, **kwargs):\n        \"\"\"Declare a traitlet.\n\n        If *allow_none* is True, None is a valid value in addition to any\n        values that are normally valid. The default is up to the subclass.\n        For most trait types, the default value for ``allow_none`` is False.\n\n        Extra metadata can be associated with the traitlet using the .tag() convenience method\n        or by using the traitlet instance's .metadata dictionary.\n        \"\"\"\n        if default_value is not Undefined:\n            self.default_value = default_value\n        if allow_none:\n            self.allow_none = allow_none\n        if read_only is not None:\n            self.read_only = read_only\n        self.help = help if help is not None else ''\n\n        if len(kwargs) > 0:\n            stacklevel = 1\n            f = inspect.currentframe()\n            # count supers to determine stacklevel for warning\n            while f.f_code.co_name == '__init__':\n                stacklevel += 1\n                f = f.f_back\n            mod = f.f_globals.get('__name__') or ''\n            pkg = mod.split('.', 1)[0]\n            key = tuple(['metadata-tag', pkg] + sorted(kwargs))\n            if _should_warn(key):\n                warn(\"metadata %s was set from the constructor. \"\n                     \"With traitlets 4.1, metadata should be set using the .tag() method, \"\n                     \"e.g., Int().tag(key1='value1', key2='value2')\" % (kwargs,),\n                     DeprecationWarning, stacklevel=stacklevel)\n            if len(self.metadata) > 0:\n                self.metadata = self.metadata.copy()\n                self.metadata.update(kwargs)\n            else:\n                self.metadata = kwargs\n        else:\n            self.metadata = self.metadata.copy()\n        if config is not None:\n            self.metadata['config'] = config\n\n        # We add help to the metadata during a deprecation period so that\n        # code that looks for the help string there can find it.\n        if help is not None:\n            self.metadata['help'] = help\n\n    def get_default_value(self):\n        \"\"\"DEPRECATED: Retrieve the static default value for this trait.\n\n        Use self.default_value instead\n        \"\"\"\n        warn(\"get_default_value is deprecated in traitlets 4.0: use the .default_value attribute\", DeprecationWarning,\n             stacklevel=2)\n        return self.default_value\n\n    def init_default_value(self, obj):\n        \"\"\"DEPRECATED: Set the static default value for the trait type.\n        \"\"\"\n        warn(\"init_default_value is deprecated in traitlets 4.0, and may be removed in the future\", DeprecationWarning,\n             stacklevel=2)\n        value = self._validate(obj, self.default_value)\n        obj._trait_values[self.name] = value\n        return value\n\n    def _dynamic_default_callable(self, obj):\n        \"\"\"Retrieve a callable to calculate the default for this traitlet.\n\n        This looks for:\n\n        * default generators registered with the @default descriptor.\n        * obj._{name}_default() on the class with the traitlet, or a subclass\n          that obj belongs to.\n        * trait.make_dynamic_default, which is defined by Instance\n\n        If neither exist, it returns None\n        \"\"\"\n        # Traitlets without a name are not on the instance, e.g. in List or Union\n        if self.name:\n\n            # Only look for default handlers in classes derived from self.this_class.\n            mro = type(obj).mro()\n            meth_name = '_%s_default' % self.name\n            for cls in mro[:mro.index(self.this_class) + 1]:\n                if hasattr(cls, '_trait_default_generators'):\n                    default_handler = cls._trait_default_generators.get(self.name)\n                    if default_handler is not None and default_handler.this_class == cls:\n                        return types.MethodType(default_handler.func, obj)\n\n                if meth_name in cls.__dict__:\n                    method = getattr(obj, meth_name)\n                    return method\n\n        return getattr(self, 'make_dynamic_default', None)\n\n    def instance_init(self, obj):\n        # If no dynamic initialiser is present, and the trait implementation or\n        # use provides a static default, transfer that to obj._trait_values.\n        with obj.cross_validation_lock:\n            if (self._dynamic_default_callable(obj) is None) \\\n                    and (self.default_value is not Undefined):\n                v = self._validate(obj, self.default_value)\n                if self.name is not None:\n                    obj._trait_values[self.name] = v\n\n    def get(self, obj, cls=None):\n        try:\n            value = obj._trait_values[self.name]\n        except KeyError:\n            # Check for a dynamic initializer.\n            dynamic_default = self._dynamic_default_callable(obj)\n            if dynamic_default is None:\n                raise TraitError(\"No default value found for %s trait of %r\"\n                                 % (self.name, obj))\n            value = self._validate(obj, dynamic_default())\n            obj._trait_values[self.name] = value\n            return value\n        except Exception:\n            # This should never be reached.\n            raise TraitError('Unexpected error in TraitType: '\n                             'default value not set properly')\n        else:\n            return value\n\n    def __get__(self, obj, cls=None):\n        \"\"\"Get the value of the trait by self.name for the instance.\n\n        Default values are instantiated when :meth:`HasTraits.__new__`\n        is called.  Thus by the time this method gets called either the\n        default value or a user defined value (they called :meth:`__set__`)\n        is in the :class:`HasTraits` instance.\n        \"\"\"\n        if obj is None:\n            return self\n        else:\n            return self.get(obj, cls)\n\n    def set(self, obj, value):\n        new_value = self._validate(obj, value)\n        try:\n            old_value = obj._trait_values[self.name]\n        except KeyError:\n            old_value = self.default_value\n\n        obj._trait_values[self.name] = new_value\n        try:\n            silent = bool(old_value == new_value)\n        except:\n            # if there is an error in comparing, default to notify\n            silent = False\n        if silent is not True:\n            # we explicitly compare silent to True just in case the equality\n            # comparison above returns something other than True/False\n            obj._notify_trait(self.name, old_value, new_value)\n\n    def __set__(self, obj, value):\n        \"\"\"Set the value of the trait by self.name for the instance.\n\n        Values pass through a validation stage where errors are raised when\n        impropper types, or types that cannot be coerced, are encountered.\n        \"\"\"\n        if self.read_only:\n            raise TraitError('The \"%s\" trait is read-only.' % self.name)\n        else:\n            self.set(obj, value)\n\n    def _validate(self, obj, value):\n        if value is None and self.allow_none:\n            return value\n        if hasattr(self, 'validate'):\n            value = self.validate(obj, value)\n        if obj._cross_validation_lock is False:\n            value = self._cross_validate(obj, value)\n        return value\n\n    def _cross_validate(self, obj, value):\n        if self.name in obj._trait_validators:\n            proposal = Bunch({'trait': self, 'value': value, 'owner': obj})\n            value = obj._trait_validators[self.name](obj, proposal)\n        elif hasattr(obj, '_%s_validate' % self.name):\n            meth_name = '_%s_validate' % self.name\n            cross_validate = getattr(obj, meth_name)\n            _deprecated_method(cross_validate, obj.__class__, meth_name,\n                \"use @validate decorator instead.\")\n            value = cross_validate(value, self)\n        return value\n\n    def __or__(self, other):\n        if isinstance(other, Union):\n            return Union([self] + other.trait_types)\n        else:\n            return Union([self, other])\n\n    def info(self):\n        return self.info_text\n\n    def error(self, obj, value):\n        if obj is not None:\n            e = \"The '%s' trait of %s instance must be %s, but a value of %s was specified.\" \\\n                % (self.name, class_of(obj),\n                   self.info(), repr_type(value))\n        else:\n            e = \"The '%s' trait must be %s, but a value of %r was specified.\" \\\n                % (self.name, self.info(), repr_type(value))\n        raise TraitError(e)\n\n    def get_metadata(self, key, default=None):\n        \"\"\"DEPRECATED: Get a metadata value.\n\n        Use .metadata[key] or .metadata.get(key, default) instead.\n        \"\"\"\n        if key == 'help':\n            msg = \"use the instance .help string directly, like x.help\"\n        else:\n            msg = \"use the instance .metadata dictionary directly, like x.metadata[key] or x.metadata.get(key, default)\"\n        warn(\"Deprecated in traitlets 4.1, \" + msg, DeprecationWarning, stacklevel=2)\n        return self.metadata.get(key, default)\n\n    def set_metadata(self, key, value):\n        \"\"\"DEPRECATED: Set a metadata key/value.\n\n        Use .metadata[key] = value instead.\n        \"\"\"\n        if key == 'help':\n            msg = \"use the instance .help string directly, like x.help = value\"\n        else:\n            msg = \"use the instance .metadata dictionary directly, like x.metadata[key] = value\"\n        warn(\"Deprecated in traitlets 4.1, \" + msg, DeprecationWarning, stacklevel=2)\n        self.metadata[key] = value\n\n    def tag(self, **metadata):\n        \"\"\"Sets metadata and returns self.\n\n        This allows convenient metadata tagging when initializing the trait, such as:\n\n        >>> Int(0).tag(config=True, sync=True)\n        \"\"\"\n        maybe_constructor_keywords = set(metadata.keys()).intersection({'help','allow_none', 'read_only', 'default_value'})\n        if maybe_constructor_keywords:\n            warn('The following attributes are set in using `tag`, but seem to be constructor keywords arguments: %s '%\n                    maybe_constructor_keywords, UserWarning, stacklevel=2)\n\n        self.metadata.update(metadata)\n        return self\n\n    def default_value_repr(self):\n        return repr(self.default_value)\n\n#-----------------------------------------------------------------------------\n# The HasTraits implementation\n#-----------------------------------------------------------------------------\n\nclass _CallbackWrapper(object):\n    \"\"\"An object adapting a on_trait_change callback into an observe callback.\n\n    The comparison operator __eq__ is implemented to enable removal of wrapped\n    callbacks.\n    \"\"\"\n\n    def __init__(self, cb):\n        self.cb = cb\n        # Bound methods have an additional 'self' argument.\n        offset = -1 if isinstance(self.cb, types.MethodType) else 0\n        self.nargs = len(getargspec(cb)[0]) + offset\n        if (self.nargs > 4):\n            raise TraitError('a trait changed callback must have 0-4 arguments.')\n\n    def __eq__(self, other):\n        # The wrapper is equal to the wrapped element\n        if isinstance(other, _CallbackWrapper):\n            return self.cb == other.cb\n        else:\n            return self.cb == other\n\n    def __call__(self, change):\n        # The wrapper is callable\n        if self.nargs == 0:\n            self.cb()\n        elif self.nargs == 1:\n            self.cb(change.name)\n        elif self.nargs == 2:\n            self.cb(change.name, change.new)\n        elif self.nargs == 3:\n            self.cb(change.name, change.old, change.new)\n        elif self.nargs == 4:\n            self.cb(change.name, change.old, change.new, change.owner)\n\ndef _callback_wrapper(cb):\n    if isinstance(cb, _CallbackWrapper):\n        return cb\n    else:\n        return _CallbackWrapper(cb)\n\n\nclass MetaHasDescriptors(type):\n    \"\"\"A metaclass for HasDescriptors.\n\n    This metaclass makes sure that any TraitType class attributes are\n    instantiated and sets their name attribute.\n    \"\"\"\n\n    def __new__(mcls, name, bases, classdict):\n        \"\"\"Create the HasDescriptors class.\"\"\"\n        for k, v in classdict.items():\n            # ----------------------------------------------------------------\n            # Support of deprecated behavior allowing for TraitType types\n            # to be used instead of TraitType instances.\n            if inspect.isclass(v) and issubclass(v, TraitType):\n                warn(\"Traits should be given as instances, not types (for example, `Int()`, not `Int`).\"\n                     \" Passing types is deprecated in traitlets 4.1.\",\n                     DeprecationWarning, stacklevel=2)\n                classdict[k] = v()\n            # ----------------------------------------------------------------\n\n        return super(MetaHasDescriptors, mcls).__new__(mcls, name, bases, classdict)\n\n    def __init__(cls, name, bases, classdict):\n        \"\"\"Finish initializing the HasDescriptors class.\"\"\"\n        super(MetaHasDescriptors, cls).__init__(name, bases, classdict)\n        cls.setup_class(classdict)\n\n    def setup_class(cls, classdict):\n        \"\"\"Setup descriptor instance on the class\n\n        This sets the :attr:`this_class` and :attr:`name` attributes of each\n        BaseDescriptor in the class dict of the newly created ``cls`` before\n        calling their :attr:`class_init` method.\n        \"\"\"\n        for k, v in classdict.items():\n            if isinstance(v, BaseDescriptor):\n                v.class_init(cls, k)\n\n\nclass MetaHasTraits(MetaHasDescriptors):\n    \"\"\"A metaclass for HasTraits.\"\"\"\n\n    def setup_class(cls, classdict):\n        cls._trait_default_generators = {}\n        super(MetaHasTraits, cls).setup_class(classdict)\n\n\ndef observe(*names, **kwargs):\n    \"\"\"A decorator which can be used to observe Traits on a class.\n\n    The handler passed to the decorator will be called with one ``change``\n    dict argument. The change dictionary at least holds a 'type' key and a\n    'name' key, corresponding respectively to the type of notification and the\n    name of the attribute that triggered the notification.\n\n    Other keys may be passed depending on the value of 'type'. In the case\n    where type is 'change', we also have the following keys:\n    * ``owner`` : the HasTraits instance\n    * ``old`` : the old value of the modified trait attribute\n    * ``new`` : the new value of the modified trait attribute\n    * ``name`` : the name of the modified trait attribute.\n\n    Parameters\n    ----------\n    *names\n        The str names of the Traits to observe on the object.\n    type: str, kwarg-only\n        The type of event to observe (e.g. 'change')\n    \"\"\"\n    if not names:\n        raise TypeError(\"Please specify at least one trait name to observe.\")\n    for name in names:\n        if name is not All and not isinstance(name, six.string_types):\n            raise TypeError(\"trait names to observe must be strings or All, not %r\" % name)\n    return ObserveHandler(names, type=kwargs.get('type', 'change'))\n\n\ndef observe_compat(func):\n    \"\"\"Backward-compatibility shim decorator for observers\n\n    Use with:\n\n    @observe('name')\n    @observe_compat\n    def _foo_changed(self, change):\n        ...\n\n    With this, `super()._foo_changed(self, name, old, new)` in subclasses will still work.\n    Allows adoption of new observer API without breaking subclasses that override and super.\n    \"\"\"\n    def compatible_observer(self, change_or_name, old=Undefined, new=Undefined):\n        if isinstance(change_or_name, dict):\n            change = change_or_name\n        else:\n            clsname = self.__class__.__name__\n            warn(\"A parent of %s._%s_changed has adopted the new (traitlets 4.1) @observe(change) API\" % (\n                clsname, change_or_name), DeprecationWarning)\n            change = Bunch(\n                type='change',\n                old=old,\n                new=new,\n                name=change_or_name,\n                owner=self,\n            )\n        return func(self, change)\n    return compatible_observer\n\n\ndef validate(*names):\n    \"\"\"A decorator to register cross validator of HasTraits object's state\n    when a Trait is set.\n\n    The handler passed to the decorator must have one ``proposal`` dict argument.\n    The proposal dictionary must hold the following keys:\n    * ``owner`` : the HasTraits instance\n    * ``value`` : the proposed value for the modified trait attribute\n    * ``trait`` : the TraitType instance associated with the attribute\n\n    Parameters\n    ----------\n    names\n        The str names of the Traits to validate.\n\n    Notes\n    -----\n    Since the owner has access to the ``HasTraits`` instance via the 'owner' key,\n    the registered cross validator could potentially make changes to attributes\n    of the ``HasTraits`` instance. However, we recommend not to do so. The reason\n    is that the cross-validation of attributes may run in arbitrary order when\n    exiting the ``hold_trait_notifications`` context, and such changes may not\n    commute.\n    \"\"\"\n    if not names:\n        raise TypeError(\"Please specify at least one trait name to validate.\")\n    for name in names:\n        if name is not All and not isinstance(name, six.string_types):\n            raise TypeError(\"trait names to validate must be strings or All, not %r\" % name)\n    return ValidateHandler(names)\n\n\ndef default(name):\n    \"\"\" A decorator which assigns a dynamic default for a Trait on a HasTraits object.\n\n    Parameters\n    ----------\n    name\n        The str name of the Trait on the object whose default should be generated.\n\n    Notes\n    -----\n    Unlike observers and validators which are properties of the HasTraits\n    instance, default value generators are class-level properties.\n\n    Besides, default generators are only invoked if they are registered in\n    subclasses of `this_type`.\n\n    ::\n\n        class A(HasTraits):\n            bar = Int()\n\n            @default('bar')\n            def get_bar_default(self):\n                return 11\n\n\n        class B(A):\n            bar = Float()  # This trait ignores the default generator defined in\n                           # the base class A\n\n\n        class C(B):\n\n            @default('bar')\n            def some_other_default(self):  # This default generator should not be\n                return 3.0                 # ignored since it is defined in a\n                                           # class derived from B.a.this_class.\n    \"\"\"\n    if not isinstance(name, six.string_types):\n        raise TypeError(\"Trait name must be a string or All, not %r\" % name)\n    return DefaultHandler(name)\n\n\nclass EventHandler(BaseDescriptor):\n\n    def _init_call(self, func):\n        self.func = func\n        return self\n\n    def __call__(self, *args, **kwargs):\n        \"\"\"Pass `*args` and `**kwargs` to the handler's function if it exists.\"\"\"\n        if hasattr(self, 'func'):\n            return self.func(*args, **kwargs)\n        else:\n            return self._init_call(*args, **kwargs)\n\n    def __get__(self, inst, cls=None):\n        if inst is None:\n            return self\n        return types.MethodType(self.func, inst)\n\n\nclass ObserveHandler(EventHandler):\n\n    def __init__(self, names, type):\n        self.trait_names = names\n        self.type = type\n\n    def instance_init(self, inst):\n        inst.observe(self, self.trait_names, type=self.type)\n\n\nclass ValidateHandler(EventHandler):\n\n    def __init__(self, names):\n        self.trait_names = names\n\n    def instance_init(self, inst):\n        inst._register_validator(self, self.trait_names)\n\n\nclass DefaultHandler(EventHandler):\n\n    def __init__(self, name):\n        self.trait_name = name\n\n    def class_init(self, cls, name):\n        super(DefaultHandler, self).class_init(cls, name)\n        cls._trait_default_generators[self.trait_name] = self\n\n\nclass HasDescriptors(six.with_metaclass(MetaHasDescriptors, object)):\n    \"\"\"The base class for all classes that have descriptors.\n    \"\"\"\n\n    def __new__(cls, *args, **kwargs):\n        # This is needed because object.__new__ only accepts\n        # the cls argument.\n        new_meth = super(HasDescriptors, cls).__new__\n        if new_meth is object.__new__:\n            inst = new_meth(cls)\n        else:\n            inst = new_meth(cls, *args, **kwargs)\n        inst.setup_instance(*args, **kwargs)\n        return inst\n\n    def setup_instance(self, *args, **kwargs):\n        \"\"\"\n        This is called **before** self.__init__ is called.\n        \"\"\"\n        self._cross_validation_lock = False\n        cls = self.__class__\n        for key in dir(cls):\n            # Some descriptors raise AttributeError like zope.interface's\n            # __provides__ attributes even though they exist.  This causes\n            # AttributeErrors even though they are listed in dir(cls).\n            try:\n                value = getattr(cls, key)\n            except AttributeError:\n                pass\n            else:\n                if isinstance(value, BaseDescriptor):\n                    value.instance_init(self)\n\n\nclass HasTraits(six.with_metaclass(MetaHasTraits, HasDescriptors)):\n\n    def setup_instance(self, *args, **kwargs):\n        self._trait_values = {}\n        self._trait_notifiers = {}\n        self._trait_validators = {}\n        super(HasTraits, self).setup_instance(*args, **kwargs)\n\n    def __init__(self, *args, **kwargs):\n        # Allow trait values to be set using keyword arguments.\n        # We need to use setattr for this to trigger validation and\n        # notifications.\n        super_args = args\n        super_kwargs = {}\n        with self.hold_trait_notifications():\n            for key, value in kwargs.items():\n                if self.has_trait(key):\n                    setattr(self, key, value)\n                else:\n                    # passthrough args that don't set traits to super\n                    super_kwargs[key] = value\n        try:\n            super(HasTraits, self).__init__(*super_args, **super_kwargs)\n        except TypeError as e:\n            arg_s_list = [ repr(arg) for arg in super_args ]\n            for k, v in super_kwargs.items():\n                arg_s_list.append(\"%s=%r\" % (k, v))\n            arg_s = ', '.join(arg_s_list)\n            warn(\n                \"Passing unrecoginized arguments to super({classname}).__init__({arg_s}).\\n\"\n                \"{error}\\n\"\n                \"This is deprecated in traitlets 4.2.\"\n                \"This error will be raised in a future release of traitlets.\"\n                .format(\n                    arg_s=arg_s, classname=self.__class__.__name__,\n                    error=e,\n                ),\n                DeprecationWarning,\n                stacklevel=2,\n            )\n\n    def __getstate__(self):\n        d = self.__dict__.copy()\n        # event handlers stored on an instance are\n        # expected to be reinstantiated during a\n        # recall of instance_init during __setstate__\n        d['_trait_notifiers'] = {}\n        d['_trait_validators'] = {}\n        return d\n\n    def __setstate__(self, state):\n        self.__dict__ = state.copy()\n\n        # event handlers are reassigned to self\n        cls = self.__class__\n        for key in dir(cls):\n            # Some descriptors raise AttributeError like zope.interface's\n            # __provides__ attributes even though they exist.  This causes\n            # AttributeErrors even though they are listed in dir(cls).\n            try:\n                value = getattr(cls, key)\n            except AttributeError:\n                pass\n            else:\n                if isinstance(value, EventHandler):\n                    value.instance_init(self)\n\n    @property\n    @contextlib.contextmanager\n    def cross_validation_lock(self):\n        \"\"\"\n        A contextmanager for running a block with our cross validation lock set\n        to True.\n\n        At the end of the block, the lock's value is restored to its value\n        prior to entering the block.\n        \"\"\"\n        if self._cross_validation_lock:\n            yield\n            return\n        else:\n            try:\n                self._cross_validation_lock = True\n                yield\n            finally:\n                self._cross_validation_lock = False\n\n    @contextlib.contextmanager\n    def hold_trait_notifications(self):\n        \"\"\"Context manager for bundling trait change notifications and cross\n        validation.\n\n        Use this when doing multiple trait assignments (init, config), to avoid\n        race conditions in trait notifiers requesting other trait values.\n        All trait notifications will fire after all values have been assigned.\n        \"\"\"\n        if self._cross_validation_lock:\n            yield\n            return\n        else:\n            cache = {}\n            notify_change = self.notify_change\n\n            def compress(past_changes, change):\n                \"\"\"Merges the provided change with the last if possible.\"\"\"\n                if past_changes is None:\n                    return [change]\n                else:\n                    if past_changes[-1]['type'] == 'change' and change.type == 'change':\n                        past_changes[-1]['new'] = change.new\n                    else:\n                        # In case of changes other than 'change', append the notification.\n                        past_changes.append(change)\n                    return past_changes\n\n            def hold(change):\n                name = change.name\n                cache[name] = compress(cache.get(name), change)\n\n            try:\n                # Replace notify_change with `hold`, caching and compressing\n                # notifications, disable cross validation and yield.\n                self.notify_change = hold\n                self._cross_validation_lock = True\n                yield\n                # Cross validate final values when context is released.\n                for name in list(cache.keys()):\n                    trait = getattr(self.__class__, name)\n                    value = trait._cross_validate(self, getattr(self, name))\n                    self.set_trait(name, value)\n            except TraitError as e:\n                # Roll back in case of TraitError during final cross validation.\n                self.notify_change = lambda x: None\n                for name, changes in cache.items():\n                    for change in changes[::-1]:\n                        # TODO: Separate in a rollback function per notification type.\n                        if change.type == 'change':\n                            if change.old is not Undefined:\n                                self.set_trait(name, change.old)\n                            else:\n                                self._trait_values.pop(name)\n                cache = {}\n                raise e\n            finally:\n                self._cross_validation_lock = False\n                # Restore method retrieval from class\n                del self.notify_change\n\n                # trigger delayed notifications\n                for changes in cache.values():\n                    for change in changes:\n                        self.notify_change(change)\n\n    def _notify_trait(self, name, old_value, new_value):\n        self.notify_change(Bunch(\n            name=name,\n            old=old_value,\n            new=new_value,\n            owner=self,\n            type='change',\n        ))\n\n    def notify_change(self, change):\n        if not isinstance(change, Bunch):\n            # cast to bunch if given a dict\n            change = Bunch(change)\n        name, type = change.name, change.type\n\n        callables = []\n        callables.extend(self._trait_notifiers.get(name, {}).get(type, []))\n        callables.extend(self._trait_notifiers.get(name, {}).get(All, []))\n        callables.extend(self._trait_notifiers.get(All, {}).get(type, []))\n        callables.extend(self._trait_notifiers.get(All, {}).get(All, []))\n\n        # Now static ones\n        magic_name = '_%s_changed' % name\n        if hasattr(self, magic_name):\n            class_value = getattr(self.__class__, magic_name)\n            if not isinstance(class_value, ObserveHandler):\n                _deprecated_method(class_value, self.__class__, magic_name,\n                    \"use @observe and @unobserve instead.\")\n                cb = getattr(self, magic_name)\n                # Only append the magic method if it was not manually registered\n                if cb not in callables:\n                    callables.append(_callback_wrapper(cb))\n\n        # Call them all now\n        # Traits catches and logs errors here.  I allow them to raise\n        for c in callables:\n            # Bound methods have an additional 'self' argument.\n\n            if isinstance(c, _CallbackWrapper):\n                c = c.__call__\n            elif isinstance(c, EventHandler) and c.name is not None:\n                c = getattr(self, c.name)\n\n            c(change)\n\n    def _add_notifiers(self, handler, name, type):\n        if name not in self._trait_notifiers:\n            nlist = []\n            self._trait_notifiers[name] = {type: nlist}\n        else:\n            if type not in self._trait_notifiers[name]:\n                nlist = []\n                self._trait_notifiers[name][type] = nlist\n            else:\n                nlist = self._trait_notifiers[name][type]\n        if handler not in nlist:\n            nlist.append(handler)\n\n    def _remove_notifiers(self, handler, name, type):\n        try:\n            if handler is None:\n                del self._trait_notifiers[name][type]\n            else:\n                self._trait_notifiers[name][type].remove(handler)\n        except KeyError:\n            pass\n\n    def on_trait_change(self, handler=None, name=None, remove=False):\n        \"\"\"DEPRECATED: Setup a handler to be called when a trait changes.\n\n        This is used to setup dynamic notifications of trait changes.\n\n        Static handlers can be created by creating methods on a HasTraits\n        subclass with the naming convention '_[traitname]_changed'.  Thus,\n        to create static handler for the trait 'a', create the method\n        _a_changed(self, name, old, new) (fewer arguments can be used, see\n        below).\n\n        If `remove` is True and `handler` is not specified, all change\n        handlers for the specified name are uninstalled.\n\n        Parameters\n        ----------\n        handler : callable, None\n            A callable that is called when a trait changes.  Its\n            signature can be handler(), handler(name), handler(name, new),\n            handler(name, old, new), or handler(name, old, new, self).\n        name : list, str, None\n            If None, the handler will apply to all traits.  If a list\n            of str, handler will apply to all names in the list.  If a\n            str, the handler will apply just to that name.\n        remove : bool\n            If False (the default), then install the handler.  If True\n            then unintall it.\n        \"\"\"\n        warn(\"on_trait_change is deprecated in traitlets 4.1: use observe instead\",\n             DeprecationWarning, stacklevel=2)\n        if name is None:\n            name = All\n        if remove:\n            self.unobserve(_callback_wrapper(handler), names=name)\n        else:\n            self.observe(_callback_wrapper(handler), names=name)\n\n    def observe(self, handler, names=All, type='change'):\n        \"\"\"Setup a handler to be called when a trait changes.\n\n        This is used to setup dynamic notifications of trait changes.\n\n        Parameters\n        ----------\n        handler : callable\n            A callable that is called when a trait changes. Its\n            signature should be ``handler(change)``, where ``change`` is a\n            dictionary. The change dictionary at least holds a 'type' key.\n            * ``type``: the type of notification.\n            Other keys may be passed depending on the value of 'type'. In the\n            case where type is 'change', we also have the following keys:\n            * ``owner`` : the HasTraits instance\n            * ``old`` : the old value of the modified trait attribute\n            * ``new`` : the new value of the modified trait attribute\n            * ``name`` : the name of the modified trait attribute.\n        names : list, str, All\n            If names is All, the handler will apply to all traits.  If a list\n            of str, handler will apply to all names in the list.  If a\n            str, the handler will apply just to that name.\n        type : str, All (default: 'change')\n            The type of notification to filter by. If equal to All, then all\n            notifications are passed to the observe handler.\n        \"\"\"\n        names = parse_notifier_name(names)\n        for n in names:\n            self._add_notifiers(handler, n, type)\n\n    def unobserve(self, handler, names=All, type='change'):\n        \"\"\"Remove a trait change handler.\n\n        This is used to unregister handlers to trait change notifications.\n\n        Parameters\n        ----------\n        handler : callable\n            The callable called when a trait attribute changes.\n        names : list, str, All (default: All)\n            The names of the traits for which the specified handler should be\n            uninstalled. If names is All, the specified handler is uninstalled\n            from the list of notifiers corresponding to all changes.\n        type : str or All (default: 'change')\n            The type of notification to filter by. If All, the specified handler\n            is uninstalled from the list of notifiers corresponding to all types.\n        \"\"\"\n        names = parse_notifier_name(names)\n        for n in names:\n            self._remove_notifiers(handler, n, type)\n\n    def unobserve_all(self, name=All):\n        \"\"\"Remove trait change handlers of any type for the specified name.\n        If name is not specified, removes all trait notifiers.\"\"\"\n        if name is All:\n            self._trait_notifiers = {}\n        else:\n            try:\n                del self._trait_notifiers[name]\n            except KeyError:\n                pass\n\n    def _register_validator(self, handler, names):\n        \"\"\"Setup a handler to be called when a trait should be cross validated.\n\n        This is used to setup dynamic notifications for cross-validation.\n\n        If a validator is already registered for any of the provided names, a\n        TraitError is raised and no new validator is registered.\n\n        Parameters\n        ----------\n        handler : callable\n            A callable that is called when the given trait is cross-validated.\n            Its signature is handler(proposal), where proposal is a Bunch (dictionary with attribute access)\n            with the following attributes/keys:\n                * ``owner`` : the HasTraits instance\n                * ``value`` : the proposed value for the modified trait attribute\n                * ``trait`` : the TraitType instance associated with the attribute\n        names : List of strings\n            The names of the traits that should be cross-validated\n        \"\"\"\n        for name in names:\n            magic_name = '_%s_validate' % name\n            if hasattr(self, magic_name):\n                class_value = getattr(self.__class__, magic_name)\n                if not isinstance(class_value, ValidateHandler):\n                    _deprecated_method(class_value, self.__class, magic_name,\n                        \"use @validate decorator instead.\")\n        for name in names:\n            self._trait_validators[name] = handler\n\n    def add_traits(self, **traits):\n        \"\"\"Dynamically add trait attributes to the HasTraits instance.\"\"\"\n        self.__class__ = type(self.__class__.__name__, (self.__class__,),\n                              traits)\n        for trait in traits.values():\n            trait.instance_init(self)\n\n    def set_trait(self, name, value):\n        \"\"\"Forcibly sets trait attribute, including read-only attributes.\"\"\"\n        cls = self.__class__\n        if not self.has_trait(name):\n            raise TraitError(\"Class %s does not have a trait named %s\" %\n                                (cls.__name__, name))\n        else:\n            getattr(cls, name).set(self, value)\n\n    @classmethod\n    def class_trait_names(cls, **metadata):\n        \"\"\"Get a list of all the names of this class' traits.\n\n        This method is just like the :meth:`trait_names` method,\n        but is unbound.\n        \"\"\"\n        return list(cls.class_traits(**metadata))\n\n    @classmethod\n    def class_traits(cls, **metadata):\n        \"\"\"Get a ``dict`` of all the traits of this class.  The dictionary\n        is keyed on the name and the values are the TraitType objects.\n\n        This method is just like the :meth:`traits` method, but is unbound.\n\n        The TraitTypes returned don't know anything about the values\n        that the various HasTrait's instances are holding.\n\n        The metadata kwargs allow functions to be passed in which\n        filter traits based on metadata values.  The functions should\n        take a single value as an argument and return a boolean.  If\n        any function returns False, then the trait is not included in\n        the output.  If a metadata key doesn't exist, None will be passed\n        to the function.\n        \"\"\"\n        traits = dict([memb for memb in getmembers(cls) if\n                     isinstance(memb[1], TraitType)])\n\n        if len(metadata) == 0:\n            return traits\n\n        result = {}\n        for name, trait in traits.items():\n            for meta_name, meta_eval in metadata.items():\n                if type(meta_eval) is not types.FunctionType:\n                    meta_eval = _SimpleTest(meta_eval)\n                if not meta_eval(trait.metadata.get(meta_name, None)):\n                    break\n            else:\n                result[name] = trait\n\n        return result\n\n    @classmethod\n    def class_own_traits(cls, **metadata):\n        \"\"\"Get a dict of all the traitlets defined on this class, not a parent.\n\n        Works like `class_traits`, except for excluding traits from parents.\n        \"\"\"\n        sup = super(cls, cls)\n        return {n: t for (n, t) in cls.class_traits(**metadata).items()\n                if getattr(sup, n, None) is not t}\n\n    def has_trait(self, name):\n        \"\"\"Returns True if the object has a trait with the specified name.\"\"\"\n        return isinstance(getattr(self.__class__, name, None), TraitType)\n\n    def trait_names(self, **metadata):\n        \"\"\"Get a list of all the names of this class' traits.\"\"\"\n        return list(self.traits(**metadata))\n\n    def traits(self, **metadata):\n        \"\"\"Get a ``dict`` of all the traits of this class.  The dictionary\n        is keyed on the name and the values are the TraitType objects.\n\n        The TraitTypes returned don't know anything about the values\n        that the various HasTrait's instances are holding.\n\n        The metadata kwargs allow functions to be passed in which\n        filter traits based on metadata values.  The functions should\n        take a single value as an argument and return a boolean.  If\n        any function returns False, then the trait is not included in\n        the output.  If a metadata key doesn't exist, None will be passed\n        to the function.\n        \"\"\"\n        traits = dict([memb for memb in getmembers(self.__class__) if\n                     isinstance(memb[1], TraitType)])\n\n        if len(metadata) == 0:\n            return traits\n\n        result = {}\n        for name, trait in traits.items():\n            for meta_name, meta_eval in metadata.items():\n                if type(meta_eval) is not types.FunctionType:\n                    meta_eval = _SimpleTest(meta_eval)\n                if not meta_eval(trait.metadata.get(meta_name, None)):\n                    break\n            else:\n                result[name] = trait\n\n        return result\n\n    def trait_metadata(self, traitname, key, default=None):\n        \"\"\"Get metadata values for trait by key.\"\"\"\n        try:\n            trait = getattr(self.__class__, traitname)\n        except AttributeError:\n            raise TraitError(\"Class %s does not have a trait named %s\" %\n                                (self.__class__.__name__, traitname))\n        metadata_name = '_' + traitname + '_metadata'\n        if hasattr(self, metadata_name) and key in getattr(self, metadata_name):\n            return getattr(self, metadata_name).get(key, default)\n        else:\n            return trait.metadata.get(key, default)\n\n    @classmethod\n    def class_own_trait_events(cls, name):\n        \"\"\"Get a dict of all event handlers defined on this class, not a parent.\n\n        Works like ``event_handlers``, except for excluding traits from parents.\n        \"\"\"\n        sup = super(cls, cls)\n        return {n: e for (n, e) in cls.events(name).items()\n                if getattr(sup, n, None) is not e}\n\n    @classmethod\n    def trait_events(cls, name=None):\n        \"\"\"Get a ``dict`` of all the event handlers of this class.\n\n        Parameters\n        ----------\n        name: str (default: None)\n            The name of a trait of this class. If name is ``None`` then all\n            the event handlers of this class will be returned instead.\n\n        Returns\n        -------\n        The event handlers associated with a trait name, or all event handlers.\n        \"\"\"\n        events = {}\n        for k, v in getmembers(cls):\n            if isinstance(v, EventHandler):\n                if name is None:\n                    events[k] = v\n                elif name in v.trait_names:\n                    events[k] = v\n                elif hasattr(v, 'tags'):\n                    if cls.trait_names(**v.tags):\n                        events[k] = v\n        return events\n\n#-----------------------------------------------------------------------------\n# Actual TraitTypes implementations/subclasses\n#-----------------------------------------------------------------------------\n\n#-----------------------------------------------------------------------------\n# TraitTypes subclasses for handling classes and instances of classes\n#-----------------------------------------------------------------------------\n\n\nclass ClassBasedTraitType(TraitType):\n    \"\"\"\n    A trait with error reporting and string -> type resolution for Type,\n    Instance and This.\n    \"\"\"\n\n    def _resolve_string(self, string):\n        \"\"\"\n        Resolve a string supplied for a type into an actual object.\n        \"\"\"\n        return import_item(string)\n\n    def error(self, obj, value):\n        kind = type(value)\n        if six.PY2 and kind is InstanceType:\n            msg = 'class %s' % value.__class__.__name__\n        else:\n            msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) )\n\n        if obj is not None:\n            e = \"The '%s' trait of %s instance must be %s, but a value of %s was specified.\" \\\n                % (self.name, class_of(obj),\n                   self.info(), msg)\n        else:\n            e = \"The '%s' trait must be %s, but a value of %r was specified.\" \\\n                % (self.name, self.info(), msg)\n\n        raise TraitError(e)\n\n\nclass Type(ClassBasedTraitType):\n    \"\"\"A trait whose value must be a subclass of a specified class.\"\"\"\n\n    def __init__ (self, default_value=Undefined, klass=None, **kwargs):\n        \"\"\"Construct a Type trait\n\n        A Type trait specifies that its values must be subclasses of\n        a particular class.\n\n        If only ``default_value`` is given, it is used for the ``klass`` as\n        well. If neither are given, both default to ``object``.\n\n        Parameters\n        ----------\n        default_value : class, str or None\n            The default value must be a subclass of klass.  If an str,\n            the str must be a fully specified class name, like 'foo.bar.Bah'.\n            The string is resolved into real class, when the parent\n            :class:`HasTraits` class is instantiated.\n        klass : class, str [ default object ]\n            Values of this trait must be a subclass of klass.  The klass\n            may be specified in a string like: 'foo.bar.MyClass'.\n            The string is resolved into real class, when the parent\n            :class:`HasTraits` class is instantiated.\n        allow_none : bool [ default False ]\n            Indicates whether None is allowed as an assignable value.\n        \"\"\"\n        if default_value is Undefined:\n            new_default_value = object if (klass is None) else klass\n        else:\n            new_default_value = default_value\n\n        if klass is None:\n            if (default_value is None) or (default_value is Undefined):\n                klass = object\n            else:\n                klass = default_value\n\n        if not (inspect.isclass(klass) or isinstance(klass, six.string_types)):\n            raise TraitError(\"A Type trait must specify a class.\")\n\n        self.klass = klass\n\n        super(Type, self).__init__(new_default_value, **kwargs)\n\n    def validate(self, obj, value):\n        \"\"\"Validates that the value is a valid object instance.\"\"\"\n        if isinstance(value, six.string_types):\n            try:\n                value = self._resolve_string(value)\n            except ImportError:\n                raise TraitError(\"The '%s' trait of %s instance must be a type, but \"\n                                 \"%r could not be imported\" % (self.name, obj, value))\n        try:\n            if issubclass(value, self.klass):\n                return value\n        except:\n            pass\n\n        self.error(obj, value)\n\n    def info(self):\n        \"\"\" Returns a description of the trait.\"\"\"\n        if isinstance(self.klass, six.string_types):\n            klass = self.klass\n        else:\n            klass = self.klass.__module__ + '.' + self.klass.__name__\n        result = \"a subclass of '%s'\" % klass\n        if self.allow_none:\n            return result + ' or None'\n        return result\n\n    def instance_init(self, obj):\n        self._resolve_classes()\n        super(Type, self).instance_init(obj)\n\n    def _resolve_classes(self):\n        if isinstance(self.klass, six.string_types):\n            self.klass = self._resolve_string(self.klass)\n        if isinstance(self.default_value, six.string_types):\n            self.default_value = self._resolve_string(self.default_value)\n\n    def default_value_repr(self):\n        value = self.default_value\n        if isinstance(value, six.string_types):\n            return repr(value)\n        else:\n            return repr('{}.{}'.format(value.__module__, value.__name__))\n\n\nclass Instance(ClassBasedTraitType):\n    \"\"\"A trait whose value must be an instance of a specified class.\n\n    The value can also be an instance of a subclass of the specified class.\n\n    Subclasses can declare default classes by overriding the klass attribute\n    \"\"\"\n\n    klass = None\n\n    def __init__(self, klass=None, args=None, kw=None, **kwargs):\n        \"\"\"Construct an Instance trait.\n\n        This trait allows values that are instances of a particular\n        class or its subclasses.  Our implementation is quite different\n        from that of enthough.traits as we don't allow instances to be used\n        for klass and we handle the ``args`` and ``kw`` arguments differently.\n\n        Parameters\n        ----------\n        klass : class, str\n            The class that forms the basis for the trait.  Class names\n            can also be specified as strings, like 'foo.bar.Bar'.\n        args : tuple\n            Positional arguments for generating the default value.\n        kw : dict\n            Keyword arguments for generating the default value.\n        allow_none : bool [ default False ]\n            Indicates whether None is allowed as a value.\n\n        Notes\n        -----\n        If both ``args`` and ``kw`` are None, then the default value is None.\n        If ``args`` is a tuple and ``kw`` is a dict, then the default is\n        created as ``klass(*args, **kw)``.  If exactly one of ``args`` or ``kw`` is\n        None, the None is replaced by ``()`` or ``{}``, respectively.\n        \"\"\"\n        if klass is None:\n            klass = self.klass\n\n        if (klass is not None) and (inspect.isclass(klass) or isinstance(klass, six.string_types)):\n            self.klass = klass\n        else:\n            raise TraitError('The klass attribute must be a class'\n                                ' not: %r' % klass)\n\n        if (kw is not None) and not isinstance(kw, dict):\n            raise TraitError(\"The 'kw' argument must be a dict or None.\")\n        if (args is not None) and not isinstance(args, tuple):\n            raise TraitError(\"The 'args' argument must be a tuple or None.\")\n\n        self.default_args = args\n        self.default_kwargs = kw\n\n        super(Instance, self).__init__(**kwargs)\n\n    def validate(self, obj, value):\n        if isinstance(value, self.klass):\n            return value\n        else:\n            self.error(obj, value)\n\n    def info(self):\n        if isinstance(self.klass, six.string_types):\n            klass = self.klass\n        else:\n            klass = self.klass.__name__\n        result = class_of(klass)\n        if self.allow_none:\n            return result + ' or None'\n\n        return result\n\n    def instance_init(self, obj):\n        self._resolve_classes()\n        super(Instance, self).instance_init(obj)\n\n    def _resolve_classes(self):\n        if isinstance(self.klass, six.string_types):\n            self.klass = self._resolve_string(self.klass)\n\n    def make_dynamic_default(self):\n        if (self.default_args is None) and (self.default_kwargs is None):\n            return None\n        return self.klass(*(self.default_args or ()),\n                          **(self.default_kwargs or {}))\n\n    def default_value_repr(self):\n        return repr(self.make_dynamic_default())\n\n\nclass ForwardDeclaredMixin(object):\n    \"\"\"\n    Mixin for forward-declared versions of Instance and Type.\n    \"\"\"\n    def _resolve_string(self, string):\n        \"\"\"\n        Find the specified class name by looking for it in the module in which\n        our this_class attribute was defined.\n        \"\"\"\n        modname = self.this_class.__module__\n        return import_item('.'.join([modname, string]))\n\n\nclass ForwardDeclaredType(ForwardDeclaredMixin, Type):\n    \"\"\"\n    Forward-declared version of Type.\n    \"\"\"\n    pass\n\n\nclass ForwardDeclaredInstance(ForwardDeclaredMixin, Instance):\n    \"\"\"\n    Forward-declared version of Instance.\n    \"\"\"\n    pass\n\n\nclass This(ClassBasedTraitType):\n    \"\"\"A trait for instances of the class containing this trait.\n\n    Because how how and when class bodies are executed, the ``This``\n    trait can only have a default value of None.  This, and because we\n    always validate default values, ``allow_none`` is *always* true.\n    \"\"\"\n\n    info_text = 'an instance of the same type as the receiver or None'\n\n    def __init__(self, **kwargs):\n        super(This, self).__init__(None, **kwargs)\n\n    def validate(self, obj, value):\n        # What if value is a superclass of obj.__class__?  This is\n        # complicated if it was the superclass that defined the This\n        # trait.\n        if isinstance(value, self.this_class) or (value is None):\n            return value\n        else:\n            self.error(obj, value)\n\n\nclass Union(TraitType):\n    \"\"\"A trait type representing a Union type.\"\"\"\n\n    def __init__(self, trait_types, **kwargs):\n        \"\"\"Construct a Union  trait.\n\n        This trait allows values that are allowed by at least one of the\n        specified trait types. A Union traitlet cannot have metadata on\n        its own, besides the metadata of the listed types.\n\n        Parameters\n        ----------\n        trait_types: sequence\n            The list of trait types of length at least 1.\n\n        Notes\n        -----\n        Union([Float(), Bool(), Int()]) attempts to validate the provided values\n        with the validation function of Float, then Bool, and finally Int.\n        \"\"\"\n        self.trait_types = trait_types\n        self.info_text = \" or \".join([tt.info() for tt in self.trait_types])\n        super(Union, self).__init__(**kwargs)\n\n    def class_init(self, cls, name):\n        for trait_type in self.trait_types:\n            trait_type.class_init(cls, None)\n        super(Union, self).class_init(cls, name)\n\n    def instance_init(self, obj):\n        for trait_type in self.trait_types:\n            trait_type.instance_init(obj)\n        super(Union, self).instance_init(obj)\n\n    def validate(self, obj, value):\n        with obj.cross_validation_lock:\n            for trait_type in self.trait_types:\n                try:\n                    v = trait_type._validate(obj, value)\n                    # In the case of an element trait, the name is None\n                    if self.name is not None:\n                        setattr(obj, '_' + self.name + '_metadata', trait_type.metadata)\n                    return v\n                except TraitError:\n                    continue\n        self.error(obj, value)\n\n    def __or__(self, other):\n        if isinstance(other, Union):\n            return Union(self.trait_types + other.trait_types)\n        else:\n            return Union(self.trait_types + [other])\n\n    def make_dynamic_default(self):\n        if self.default_value is not Undefined:\n            return self.default_value\n        for trait_type in self.trait_types:\n            if trait_type.default_value is not Undefined:\n                return trait_type.default_value\n            elif hasattr(trait_type, 'make_dynamic_default'):\n                return trait_type.make_dynamic_default()\n\n\n#-----------------------------------------------------------------------------\n# Basic TraitTypes implementations/subclasses\n#-----------------------------------------------------------------------------\n\n\nclass Any(TraitType):\n    \"\"\"A trait which allows any value.\"\"\"\n    default_value = None\n    info_text = 'any value'\n\n\ndef _validate_bounds(trait, obj, value):\n    \"\"\"\n    Validate that a number to be applied to a trait is between bounds.\n\n    If value is not between min_bound and max_bound, this raises a\n    TraitError with an error message appropriate for this trait.\n    \"\"\"\n    if trait.min is not None and value < trait.min:\n        raise TraitError(\n            \"The value of the '{name}' trait of {klass} instance should \"\n            \"not be less than {min_bound}, but a value of {value} was \"\n            \"specified\".format(\n                name=trait.name, klass=class_of(obj),\n                value=value, min_bound=trait.min))\n    if trait.max is not None and value > trait.max:\n        raise TraitError(\n            \"The value of the '{name}' trait of {klass} instance should \"\n            \"not be greater than {max_bound}, but a value of {value} was \"\n            \"specified\".format(\n                name=trait.name, klass=class_of(obj),\n                value=value, max_bound=trait.max))\n    return value\n\n\nclass Int(TraitType):\n    \"\"\"An int trait.\"\"\"\n\n    default_value = 0\n    info_text = 'an int'\n\n    def __init__(self, default_value=Undefined, allow_none=False, **kwargs):\n        self.min = kwargs.pop('min', None)\n        self.max = kwargs.pop('max', None)\n        super(Int, self).__init__(default_value=default_value,\n                                  allow_none=allow_none, **kwargs)\n\n    def validate(self, obj, value):\n        if not isinstance(value, int):\n            self.error(obj, value)\n        return _validate_bounds(self, obj, value)\n\n\nclass CInt(Int):\n    \"\"\"A casting version of the int trait.\"\"\"\n\n    def validate(self, obj, value):\n        try:\n            value = int(value)\n        except:\n            self.error(obj, value)\n        return _validate_bounds(self, obj, value)\n\n\nif six.PY2:\n    class Long(TraitType):\n        \"\"\"A long integer trait.\"\"\"\n\n        default_value = 0\n        info_text = 'a long'\n\n        def __init__(self, default_value=Undefined, allow_none=False, **kwargs):\n            self.min = kwargs.pop('min', None)\n            self.max = kwargs.pop('max', None)\n            super(Long, self).__init__(\n                default_value=default_value,\n                allow_none=allow_none, **kwargs)\n\n        def _validate_long(self, obj, value):\n            if isinstance(value, long):\n                return value\n            if isinstance(value, int):\n                return long(value)\n            self.error(obj, value)\n\n        def validate(self, obj, value):\n            value = self._validate_long(obj, value)\n            return _validate_bounds(self, obj, value)\n\n\n    class CLong(Long):\n        \"\"\"A casting version of the long integer trait.\"\"\"\n\n        def validate(self, obj, value):\n            try:\n                value = long(value)\n            except:\n                self.error(obj, value)\n            return _validate_bounds(self, obj, value)\n\n\n    class Integer(TraitType):\n        \"\"\"An integer trait.\n\n        Longs that are unnecessary (<= sys.maxint) are cast to ints.\"\"\"\n\n        default_value = 0\n        info_text = 'an integer'\n\n        def __init__(self, default_value=Undefined, allow_none=False, **kwargs):\n            self.min = kwargs.pop('min', None)\n            self.max = kwargs.pop('max', None)\n            super(Integer, self).__init__(\n                default_value=default_value,\n                allow_none=allow_none, **kwargs)\n\n        def _validate_int(self, obj, value):\n            if isinstance(value, int):\n                return value\n            if isinstance(value, long):\n                # downcast longs that fit in int:\n                # note that int(n > sys.maxint) returns a long, so\n                # we don't need a condition on this cast\n                return int(value)\n            if sys.platform == \"cli\":\n                from System import Int64\n                if isinstance(value, Int64):\n                    return int(value)\n            self.error(obj, value)\n\n        def validate(self, obj, value):\n            value = self._validate_int(obj, value)\n            return _validate_bounds(self, obj, value)\n\nelse:\n    Long, CLong = Int, CInt\n    Integer = Int\n\n\nclass Float(TraitType):\n    \"\"\"A float trait.\"\"\"\n\n    default_value = 0.0\n    info_text = 'a float'\n\n    def __init__(self, default_value=Undefined, allow_none=False, **kwargs):\n        self.min = kwargs.pop('min', -float('inf'))\n        self.max = kwargs.pop('max', float('inf'))\n        super(Float, self).__init__(default_value=default_value,\n                                    allow_none=allow_none, **kwargs)\n\n    def validate(self, obj, value):\n        if isinstance(value, int):\n            value = float(value)\n        if not isinstance(value, float):\n            self.error(obj, value)\n        return _validate_bounds(self, obj, value)\n\n\nclass CFloat(Float):\n    \"\"\"A casting version of the float trait.\"\"\"\n\n    def validate(self, obj, value):\n        try:\n            value = float(value)\n        except:\n            self.error(obj, value)\n        return _validate_bounds(self, obj, value)\n\n\nclass Complex(TraitType):\n    \"\"\"A trait for complex numbers.\"\"\"\n\n    default_value = 0.0 + 0.0j\n    info_text = 'a complex number'\n\n    def validate(self, obj, value):\n        if isinstance(value, complex):\n            return value\n        if isinstance(value, (float, int)):\n            return complex(value)\n        self.error(obj, value)\n\n\nclass CComplex(Complex):\n    \"\"\"A casting version of the complex number trait.\"\"\"\n\n    def validate (self, obj, value):\n        try:\n            return complex(value)\n        except:\n            self.error(obj, value)\n\n# We should always be explicit about whether we're using bytes or unicode, both\n# for Python 3 conversion and for reliable unicode behaviour on Python 2. So\n# we don't have a Str type.\nclass Bytes(TraitType):\n    \"\"\"A trait for byte strings.\"\"\"\n\n    default_value = b''\n    info_text = 'a bytes object'\n\n    def validate(self, obj, value):\n        if isinstance(value, bytes):\n            return value\n        self.error(obj, value)\n\n\nclass CBytes(Bytes):\n    \"\"\"A casting version of the byte string trait.\"\"\"\n\n    def validate(self, obj, value):\n        try:\n            return bytes(value)\n        except:\n            self.error(obj, value)\n\n\nclass Unicode(TraitType):\n    \"\"\"A trait for unicode strings.\"\"\"\n\n    default_value = u''\n    info_text = 'a unicode string'\n\n    def validate(self, obj, value):\n        if isinstance(value, six.text_type):\n            return value\n        if isinstance(value, bytes):\n            try:\n                return value.decode('ascii', 'strict')\n            except UnicodeDecodeError:\n                msg = \"Could not decode {!r} for unicode trait '{}' of {} instance.\"\n                raise TraitError(msg.format(value, self.name, class_of(obj)))\n        self.error(obj, value)\n\n\nclass CUnicode(Unicode):\n    \"\"\"A casting version of the unicode trait.\"\"\"\n\n    def validate(self, obj, value):\n        try:\n            return six.text_type(value)\n        except:\n            self.error(obj, value)\n\n\nclass ObjectName(TraitType):\n    \"\"\"A string holding a valid object name in this version of Python.\n\n    This does not check that the name exists in any scope.\"\"\"\n    info_text = \"a valid object identifier in Python\"\n\n    if six.PY2:\n        # Python 2:\n        def coerce_str(self, obj, value):\n            \"In Python 2, coerce ascii-only unicode to str\"\n            if isinstance(value, unicode):\n                try:\n                    return str(value)\n                except UnicodeEncodeError:\n                    self.error(obj, value)\n            return value\n    else:\n        coerce_str = staticmethod(lambda _,s: s)\n\n    def validate(self, obj, value):\n        value = self.coerce_str(obj, value)\n\n        if isinstance(value, six.string_types) and isidentifier(value):\n            return value\n        self.error(obj, value)\n\nclass DottedObjectName(ObjectName):\n    \"\"\"A string holding a valid dotted object name in Python, such as A.b3._c\"\"\"\n    def validate(self, obj, value):\n        value = self.coerce_str(obj, value)\n\n        if isinstance(value, six.string_types) and all(isidentifier(a)\n          for a in value.split('.')):\n            return value\n        self.error(obj, value)\n\n\nclass Bool(TraitType):\n    \"\"\"A boolean (True, False) trait.\"\"\"\n\n    default_value = False\n    info_text = 'a boolean'\n\n    def validate(self, obj, value):\n        if isinstance(value, bool):\n            return value\n        self.error(obj, value)\n\n\nclass CBool(Bool):\n    \"\"\"A casting version of the boolean trait.\"\"\"\n\n    def validate(self, obj, value):\n        try:\n            return bool(value)\n        except:\n            self.error(obj, value)\n\n\nclass Enum(TraitType):\n    \"\"\"An enum whose value must be in a given sequence.\"\"\"\n\n    def __init__(self, values, default_value=Undefined, **kwargs):\n        self.values = values\n        if kwargs.get('allow_none', False) and default_value is Undefined:\n            default_value = None\n        super(Enum, self).__init__(default_value, **kwargs)\n\n    def validate(self, obj, value):\n        if value in self.values:\n                return value\n        self.error(obj, value)\n\n    def info(self):\n        \"\"\" Returns a description of the trait.\"\"\"\n        result = 'any of ' + repr(self.values)\n        if self.allow_none:\n            return result + ' or None'\n        return result\n\nclass CaselessStrEnum(Enum):\n    \"\"\"An enum of strings where the case should be ignored.\"\"\"\n\n    def __init__(self, values, default_value=Undefined, **kwargs):\n        values = [cast_unicode_py2(value) for value in values]\n        super(CaselessStrEnum, self).__init__(values, default_value=default_value, **kwargs)\n\n    def validate(self, obj, value):\n        if isinstance(value, str):\n            value = cast_unicode_py2(value)\n        if not isinstance(value, six.string_types):\n            self.error(obj, value)\n\n        for v in self.values:\n            if v.lower() == value.lower():\n                return v\n        self.error(obj, value)\n\nclass Container(Instance):\n    \"\"\"An instance of a container (list, set, etc.)\n\n    To be subclassed by overriding klass.\n    \"\"\"\n    klass = None\n    _cast_types = ()\n    _valid_defaults = SequenceTypes\n    _trait = None\n\n    def __init__(self, trait=None, default_value=None, **kwargs):\n        \"\"\"Create a container trait type from a list, set, or tuple.\n\n        The default value is created by doing ``List(default_value)``,\n        which creates a copy of the ``default_value``.\n\n        ``trait`` can be specified, which restricts the type of elements\n        in the container to that TraitType.\n\n        If only one arg is given and it is not a Trait, it is taken as\n        ``default_value``:\n\n        ``c = List([1, 2, 3])``\n\n        Parameters\n        ----------\n\n        trait : TraitType [ optional ]\n            the type for restricting the contents of the Container.  If unspecified,\n            types are not checked.\n\n        default_value : SequenceType [ optional ]\n            The default value for the Trait.  Must be list/tuple/set, and\n            will be cast to the container type.\n\n        allow_none : bool [ default False ]\n            Whether to allow the value to be None\n\n        **kwargs : any\n            further keys for extensions to the Trait (e.g. config)\n\n        \"\"\"\n        # allow List([values]):\n        if default_value is None and not is_trait(trait):\n            default_value = trait\n            trait = None\n\n        if default_value is None:\n            args = ()\n        elif isinstance(default_value, self._valid_defaults):\n            args = (default_value,)\n        else:\n            raise TypeError('default value of %s was %s' %(self.__class__.__name__, default_value))\n\n        if is_trait(trait):\n            if isinstance(trait, type):\n                warn(\"Traits should be given as instances, not types (for example, `Int()`, not `Int`).\"\n                     \" Passing types is deprecated in traitlets 4.1.\",\n                     DeprecationWarning, stacklevel=3)\n            self._trait = trait() if isinstance(trait, type) else trait\n        elif trait is not None:\n            raise TypeError(\"`trait` must be a Trait or None, got %s\" % repr_type(trait))\n\n        super(Container,self).__init__(klass=self.klass, args=args, **kwargs)\n\n    def element_error(self, obj, element, validator):\n        e = \"Element of the '%s' trait of %s instance must be %s, but a value of %s was specified.\" \\\n            % (self.name, class_of(obj), validator.info(), repr_type(element))\n        raise TraitError(e)\n\n    def validate(self, obj, value):\n        if isinstance(value, self._cast_types):\n            value = self.klass(value)\n        value = super(Container, self).validate(obj, value)\n        if value is None:\n            return value\n\n        value = self.validate_elements(obj, value)\n\n        return value\n\n    def validate_elements(self, obj, value):\n        validated = []\n        if self._trait is None or isinstance(self._trait, Any):\n            return value\n        for v in value:\n            try:\n                v = self._trait._validate(obj, v)\n            except TraitError:\n                self.element_error(obj, v, self._trait)\n            else:\n                validated.append(v)\n        return self.klass(validated)\n\n    def class_init(self, cls, name):\n        if isinstance(self._trait, TraitType):\n            self._trait.class_init(cls, None)\n        super(Container, self).class_init(cls, name)\n\n    def instance_init(self, obj):\n        if isinstance(self._trait, TraitType):\n            self._trait.instance_init(obj)\n        super(Container, self).instance_init(obj)\n\n\nclass List(Container):\n    \"\"\"An instance of a Python list.\"\"\"\n    klass = list\n    _cast_types = (tuple,)\n\n    def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxsize, **kwargs):\n        \"\"\"Create a List trait type from a list, set, or tuple.\n\n        The default value is created by doing ``list(default_value)``,\n        which creates a copy of the ``default_value``.\n\n        ``trait`` can be specified, which restricts the type of elements\n        in the container to that TraitType.\n\n        If only one arg is given and it is not a Trait, it is taken as\n        ``default_value``:\n\n        ``c = List([1, 2, 3])``\n\n        Parameters\n        ----------\n\n        trait : TraitType [ optional ]\n            the type for restricting the contents of the Container.\n            If unspecified, types are not checked.\n\n        default_value : SequenceType [ optional ]\n            The default value for the Trait.  Must be list/tuple/set, and\n            will be cast to the container type.\n\n        minlen : Int [ default 0 ]\n            The minimum length of the input list\n\n        maxlen : Int [ default sys.maxsize ]\n            The maximum length of the input list\n        \"\"\"\n        self._minlen = minlen\n        self._maxlen = maxlen\n        super(List, self).__init__(trait=trait, default_value=default_value,\n                                   **kwargs)\n\n    def length_error(self, obj, value):\n        e = \"The '%s' trait of %s instance must be of length %i <= L <= %i, but a value of %s was specified.\" \\\n            % (self.name, class_of(obj), self._minlen, self._maxlen, value)\n        raise TraitError(e)\n\n    def validate_elements(self, obj, value):\n        length = len(value)\n        if length < self._minlen or length > self._maxlen:\n            self.length_error(obj, value)\n\n        return super(List, self).validate_elements(obj, value)\n\n    def validate(self, obj, value):\n        value = super(List, self).validate(obj, value)\n        value = self.validate_elements(obj, value)\n        return value\n\n\nclass Set(List):\n    \"\"\"An instance of a Python set.\"\"\"\n    klass = set\n    _cast_types = (tuple, list)\n\n    # Redefine __init__ just to make the docstring more accurate.\n    def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxsize,\n                 **kwargs):\n        \"\"\"Create a Set trait type from a list, set, or tuple.\n\n        The default value is created by doing ``set(default_value)``,\n        which creates a copy of the ``default_value``.\n\n        ``trait`` can be specified, which restricts the type of elements\n        in the container to that TraitType.\n\n        If only one arg is given and it is not a Trait, it is taken as\n        ``default_value``:\n\n        ``c = Set({1, 2, 3})``\n\n        Parameters\n        ----------\n\n        trait : TraitType [ optional ]\n            the type for restricting the contents of the Container.\n            If unspecified, types are not checked.\n\n        default_value : SequenceType [ optional ]\n            The default value for the Trait.  Must be list/tuple/set, and\n            will be cast to the container type.\n\n        minlen : Int [ default 0 ]\n            The minimum length of the input list\n\n        maxlen : Int [ default sys.maxsize ]\n            The maximum length of the input list\n        \"\"\"\n        super(Set, self).__init__(trait, default_value, minlen, maxlen, **kwargs)\n\n\nclass Tuple(Container):\n    \"\"\"An instance of a Python tuple.\"\"\"\n    klass = tuple\n    _cast_types = (list,)\n\n    def __init__(self, *traits, **kwargs):\n        \"\"\"Create a tuple from a list, set, or tuple.\n\n        Create a fixed-type tuple with Traits:\n\n        ``t = Tuple(Int(), Str(), CStr())``\n\n        would be length 3, with Int,Str,CStr for each element.\n\n        If only one arg is given and it is not a Trait, it is taken as\n        default_value:\n\n        ``t = Tuple((1, 2, 3))``\n\n        Otherwise, ``default_value`` *must* be specified by keyword.\n\n        Parameters\n        ----------\n\n        `*traits` : TraitTypes [ optional ]\n            the types for restricting the contents of the Tuple.  If unspecified,\n            types are not checked. If specified, then each positional argument\n            corresponds to an element of the tuple.  Tuples defined with traits\n            are of fixed length.\n\n        default_value : SequenceType [ optional ]\n            The default value for the Tuple.  Must be list/tuple/set, and\n            will be cast to a tuple. If ``traits`` are specified,\n            ``default_value`` must conform to the shape and type they specify.\n        \"\"\"\n        default_value = kwargs.pop('default_value', Undefined)\n        # allow Tuple((values,)):\n        if len(traits) == 1 and default_value is Undefined and not is_trait(traits[0]):\n            default_value = traits[0]\n            traits = ()\n\n        if default_value is Undefined:\n            args = ()\n        elif isinstance(default_value, self._valid_defaults):\n            args = (default_value,)\n        else:\n            raise TypeError('default value of %s was %s' %(self.__class__.__name__, default_value))\n\n        self._traits = []\n        for trait in traits:\n            if isinstance(trait, type):\n                warn(\"Traits should be given as instances, not types (for example, `Int()`, not `Int`)\"\n                     \" Passing types is deprecated in traitlets 4.1.\",\n                     DeprecationWarning, stacklevel=2)\n            t = trait() if isinstance(trait, type) else trait\n            self._traits.append(t)\n\n        if self._traits and default_value is None:\n            # don't allow default to be an empty container if length is specified\n            args = None\n        super(Container,self).__init__(klass=self.klass, args=args, **kwargs)\n\n    def validate_elements(self, obj, value):\n        if not self._traits:\n            # nothing to validate\n            return value\n        if len(value) != len(self._traits):\n            e = \"The '%s' trait of %s instance requires %i elements, but a value of %s was specified.\" \\\n                % (self.name, class_of(obj), len(self._traits), repr_type(value))\n            raise TraitError(e)\n\n        validated = []\n        for t, v in zip(self._traits, value):\n            try:\n                v = t._validate(obj, v)\n            except TraitError:\n                self.element_error(obj, v, t)\n            else:\n                validated.append(v)\n        return tuple(validated)\n\n    def class_init(self, cls, name):\n        for trait in self._traits:\n            if isinstance(trait, TraitType):\n                trait.class_init(cls, None)\n        super(Container, self).class_init(cls, name)\n\n    def instance_init(self, obj):\n        for trait in self._traits:\n            if isinstance(trait, TraitType):\n                trait.instance_init(obj)\n        super(Container, self).instance_init(obj)\n\n\nclass Dict(Instance):\n    \"\"\"An instance of a Python dict.\"\"\"\n    _trait = None\n\n    def __init__(self, trait=None, traits=None, default_value=Undefined,\n                 **kwargs):\n        \"\"\"Create a dict trait type from a Python dict.\n\n        The default value is created by doing ``dict(default_value)``,\n        which creates a copy of the ``default_value``.\n\n        Parameters\n        ----------\n\n        trait : TraitType [ optional ]\n            The specified trait type to check and use to restrict contents of\n            the Container. If unspecified, trait types are not checked.\n\n        traits : Dictionary of trait types [ optional ]\n            A Python dictionary containing the types that are valid for\n            restricting the content of the Dict Container for certain keys.\n\n        default_value : SequenceType [ optional ]\n            The default value for the Dict.  Must be dict, tuple, or None, and\n            will be cast to a dict if not None. If `trait` is specified, the\n            `default_value` must conform to the constraints it specifies.\n        \"\"\"\n        # Handling positional arguments\n        if default_value is Undefined and trait is not None:\n            if not is_trait(trait):\n                default_value = trait\n                trait = None\n\n        # Handling default value\n        if default_value is Undefined:\n            default_value = {}\n        if default_value is None:\n            args = None\n        elif isinstance(default_value, dict):\n            args = (default_value,)\n        elif isinstance(default_value, SequenceTypes):\n            args = (default_value,)\n        else:\n            raise TypeError('default value of Dict was %s' % default_value)\n\n        # Case where a type of TraitType is provided rather than an instance\n        if is_trait(trait):\n            if isinstance(trait, type):\n                warn(\"Traits should be given as instances, not types (for example, `Int()`, not `Int`)\"\n                     \" Passing types is deprecated in traitlets 4.1.\",\n                     DeprecationWarning, stacklevel=2)\n            self._trait = trait() if isinstance(trait, type) else trait\n        elif trait is not None:\n            raise TypeError(\"`trait` must be a Trait or None, got %s\" % repr_type(trait))\n\n        self._traits = traits\n\n        super(Dict, self).__init__(klass=dict, args=args, **kwargs)\n\n    def element_error(self, obj, element, validator):\n        e = \"Element of the '%s' trait of %s instance must be %s, but a value of %s was specified.\" \\\n            % (self.name, class_of(obj), validator.info(), repr_type(element))\n        raise TraitError(e)\n\n    def validate(self, obj, value):\n        value = super(Dict, self).validate(obj, value)\n        if value is None:\n            return value\n        value = self.validate_elements(obj, value)\n        return value\n\n    def validate_elements(self, obj, value):\n        use_dict = bool(self._traits)\n        default_to = (self._trait or Any())\n        if not use_dict and isinstance(default_to, Any):\n            return value\n\n        validated = {}\n        for key in value:\n            if use_dict and key in self._traits:\n                validate_with = self._traits[key]\n            else:\n                validate_with = default_to\n            try:\n                v = value[key]\n                if not isinstance(validate_with, Any):\n                    v = validate_with._validate(obj, v)\n            except TraitError:\n                self.element_error(obj, v, validate_with)\n            else:\n                validated[key] = v\n\n        return self.klass(validated)\n\n    def class_init(self, cls, name):\n        if isinstance(self._trait, TraitType):\n            self._trait.class_init(cls, None)\n        if self._traits is not None:\n            for trait in self._traits.values():\n                trait.class_init(cls, None)\n        super(Dict, self).class_init(cls, name)\n\n    def instance_init(self, obj):\n        if isinstance(self._trait, TraitType):\n            self._trait.instance_init(obj)\n        if self._traits is not None:\n            for trait in self._traits.values():\n                trait.instance_init(obj)\n        super(Dict, self).instance_init(obj)\n\n\nclass TCPAddress(TraitType):\n    \"\"\"A trait for an (ip, port) tuple.\n\n    This allows for both IPv4 IP addresses as well as hostnames.\n    \"\"\"\n\n    default_value = ('127.0.0.1', 0)\n    info_text = 'an (ip, port) tuple'\n\n    def validate(self, obj, value):\n        if isinstance(value, tuple):\n            if len(value) == 2:\n                if isinstance(value[0], six.string_types) and isinstance(value[1], int):\n                    port = value[1]\n                    if port >= 0 and port <= 65535:\n                        return value\n        self.error(obj, value)\n\nclass CRegExp(TraitType):\n    \"\"\"A casting compiled regular expression trait.\n\n    Accepts both strings and compiled regular expressions. The resulting\n    attribute will be a compiled regular expression.\"\"\"\n\n    info_text = 'a regular expression'\n\n    def validate(self, obj, value):\n        try:\n            return re.compile(value)\n        except:\n            self.error(obj, value)\n\n\nclass UseEnum(TraitType):\n    \"\"\"Use a Enum class as model for the data type description.\n    Note that if no default-value is provided, the first enum-value is used\n    as default-value.\n\n    .. sourcecode:: python\n\n        # -- SINCE: Python 3.4 (or install backport: pip install enum34)\n        import enum\n        from traitlets import HasTraits, UseEnum\n\n        class Color(enum.Enum):\n            red = 1         # -- IMPLICIT: default_value\n            blue = 2\n            green = 3\n\n        class MyEntity(HasTraits):\n            color = UseEnum(Color, default_value=Color.blue)\n\n        entity = MyEntity(color=Color.red)\n        entity.color = Color.green    # USE: Enum-value (preferred)\n        entity.color = \"green\"        # USE: name (as string)\n        entity.color = \"Color.green\"  # USE: scoped-name (as string)\n        entity.color = 3              # USE: number (as int)\n        assert entity.color is Color.green\n    \"\"\"\n    default_value = None\n    info_text = \"Trait type adapter to a Enum class\"\n\n    def __init__(self, enum_class, default_value=None, **kwargs):\n        assert issubclass(enum_class, enum.Enum), \\\n                          \"REQUIRE: enum.Enum, but was: %r\" % enum_class\n        allow_none = kwargs.get(\"allow_none\", False)\n        if default_value is None and not allow_none:\n            default_value = list(enum_class.__members__.values())[0]\n        super(UseEnum, self).__init__(default_value=default_value, **kwargs)\n        self.enum_class = enum_class\n        self.name_prefix = enum_class.__name__ + \".\"\n\n    def select_by_number(self, value, default=Undefined):\n        \"\"\"Selects enum-value by using its number-constant.\"\"\"\n        assert isinstance(value, int)\n        enum_members = self.enum_class.__members__\n        for enum_item in enum_members.values():\n            if enum_item.value == value:\n                return enum_item\n        # -- NOT FOUND:\n        return default\n\n    def select_by_name(self, value, default=Undefined):\n        \"\"\"Selects enum-value by using its name or scoped-name.\"\"\"\n        assert isinstance(value, six.string_types)\n        if value.startswith(self.name_prefix):\n            # -- SUPPORT SCOPED-NAMES, like: \"Color.red\" => \"red\"\n            value = value.replace(self.name_prefix, \"\", 1)\n        return self.enum_class.__members__.get(value, default)\n\n    def validate(self, obj, value):\n        if isinstance(value, self.enum_class):\n            return value\n        elif isinstance(value, int):\n            # -- CONVERT: number => enum_value (item)\n            value2 = self.select_by_number(value)\n            if value2 is not Undefined:\n                return value2\n        elif isinstance(value, six.string_types):\n            # -- CONVERT: name or scoped_name (as string) => enum_value (item)\n            value2 = self.select_by_name(value)\n            if value2 is not Undefined:\n                return value2\n        elif value is None:\n            if self.allow_none:\n                return None\n            else:\n                return self.default_value\n        self.error(obj, value)\n\n    def info(self):\n        \"\"\"Returns a description of this Enum trait (in case of errors).\"\"\"\n        result = \"Any of: %s\" % \", \".join(self.enum_class.__members__.keys())\n        if self.allow_none:\n            return result + \" or None\"\n        return result\n"
  },
  {
    "path": "lib/client/traitlets/utils/__init__.py",
    "content": ""
  },
  {
    "path": "lib/client/traitlets/utils/bunch.py",
    "content": "\"\"\"Yet another implementation of bunch\n\nattribute-access of items on a dict.\n\"\"\"\n\n# Copyright (c) Jupyter Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nclass Bunch(dict):\n    \"\"\"A dict with attribute-access\"\"\"\n    def __getattr__(self, key):\n        try:\n            return self.__getitem__(key)\n        except KeyError:\n            raise AttributeError(key)\n    \n    def __setattr__(self, key, value):\n        self.__setitem__(key, value)\n    \n    def __dir__(self):\n        # py2-compat: can't use super because dict doesn't have __dir__\n        names = dir({})\n        names.extend(self.keys())\n        return names\n\n"
  },
  {
    "path": "lib/client/traitlets/utils/getargspec.py",
    "content": "# -*- coding: utf-8 -*-\n\"\"\"\n    getargspec excerpted from:\n    \n    sphinx.util.inspect\n    ~~~~~~~~~~~~~~~~~~~\n    Helpers for inspecting Python modules.\n    :copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.\n    :license: BSD, see LICENSE for details.\n\"\"\"\n\nimport inspect\nfrom six import PY3\n\n# Unmodified from sphinx below this line\n\nif PY3:\n    from functools import partial\n\n    def getargspec(func):\n        \"\"\"Like inspect.getargspec but supports functools.partial as well.\"\"\"\n        if inspect.ismethod(func):\n            func = func.__func__\n        if type(func) is partial:\n            orig_func = func.func\n            argspec = getargspec(orig_func)\n            args = list(argspec[0])\n            defaults = list(argspec[3] or ())\n            kwoargs = list(argspec[4])\n            kwodefs = dict(argspec[5] or {})\n            if func.args:\n                args = args[len(func.args):]\n            for arg in func.keywords or ():\n                try:\n                    i = args.index(arg) - len(args)\n                    del args[i]\n                    try:\n                        del defaults[i]\n                    except IndexError:\n                        pass\n                except ValueError:   # must be a kwonly arg\n                    i = kwoargs.index(arg)\n                    del kwoargs[i]\n                    del kwodefs[arg]\n            return inspect.FullArgSpec(args, argspec[1], argspec[2],\n                                       tuple(defaults), kwoargs,\n                                       kwodefs, argspec[6])\n        while hasattr(func, '__wrapped__'):\n            func = func.__wrapped__\n        if not inspect.isfunction(func):\n            raise TypeError('%r is not a Python function' % func)\n        return inspect.getfullargspec(func)\n\nelse:  # 2.6, 2.7\n    from functools import partial\n\n    def getargspec(func):\n        \"\"\"Like inspect.getargspec but supports functools.partial as well.\"\"\"\n        if inspect.ismethod(func):\n            func = func.__func__\n        parts = 0, ()\n        if type(func) is partial:\n            keywords = func.keywords\n            if keywords is None:\n                keywords = {}\n            parts = len(func.args), keywords.keys()\n            func = func.func\n        if not inspect.isfunction(func):\n            raise TypeError('%r is not a Python function' % func)\n        args, varargs, varkw = inspect.getargs(func.__code__)\n        func_defaults = func.__defaults__\n        if func_defaults is None:\n            func_defaults = []\n        else:\n            func_defaults = list(func_defaults)\n        if parts[0]:\n            args = args[parts[0]:]\n        if parts[1]:\n            for arg in parts[1]:\n                i = args.index(arg) - len(args)\n                del args[i]\n                try:\n                    del func_defaults[i]\n                except IndexError:\n                    pass\n        return inspect.ArgSpec(args, varargs, varkw, func_defaults)\n"
  },
  {
    "path": "lib/client/traitlets/utils/importstring.py",
    "content": "# encoding: utf-8\n\"\"\"\nA simple utility to import something by its string name.\n\"\"\"\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nfrom ipython_genutils.py3compat import cast_bytes_py2\nfrom six import string_types\n\ndef import_item(name):\n    \"\"\"Import and return ``bar`` given the string ``foo.bar``.\n\n    Calling ``bar = import_item(\"foo.bar\")`` is the functional equivalent of\n    executing the code ``from foo import bar``.\n\n    Parameters\n    ----------\n    name : string\n      The fully qualified name of the module/package being imported.\n\n    Returns\n    -------\n    mod : module object\n       The module that was imported.\n    \"\"\"\n    if not isinstance(name, string_types):\n        raise TypeError(\"import_item accepts strings, not '%s'.\" % type(name))\n    name = cast_bytes_py2(name)\n    parts = name.rsplit('.', 1)\n    if len(parts) == 2:\n        # called with 'foo.bar....'\n        package, obj = parts\n        module = __import__(package, fromlist=[obj])\n        try:\n            pak = getattr(module, obj)\n        except AttributeError:\n            raise ImportError('No module named %s' % obj)\n        return pak\n    else:\n        # called with un-dotted string\n        return __import__(parts[0])\n"
  },
  {
    "path": "lib/client/traitlets/utils/sentinel.py",
    "content": "\"\"\"Sentinel class for constants with useful reprs\"\"\"\n\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n\nclass Sentinel(object):\n\n    def __init__(self, name, module, docstring=None):\n        self.name = name\n        self.module = module\n        if docstring:\n            self.__doc__ = docstring\n\n\n    def __repr__(self):\n        return str(self.module)+'.'+self.name\n\n"
  },
  {
    "path": "lib/client/traitlets/utils/tests/__init__.py",
    "content": ""
  },
  {
    "path": "lib/client/traitlets/utils/tests/test_bunch.py",
    "content": "from ..bunch import Bunch\n\ndef test_bunch():\n    b = Bunch(x=5, y=10)\n    assert 'y' in b\n    assert 'x' in b\n    assert b.x == 5\n    b['a'] = 'hi'\n    assert b.a == 'hi'\n\ndef test_bunch_dir():\n    b = Bunch(x=5, y=10)\n    assert 'x' in dir(b)\n    assert 'keys' in dir(b)\n"
  },
  {
    "path": "lib/client/traitlets/utils/tests/test_importstring.py",
    "content": "# encoding: utf-8\n# Copyright (c) IPython Development Team.\n# Distributed under the terms of the Modified BSD License.\n#\n# Adapted from enthought.traits, Copyright (c) Enthought, Inc.,\n# also under the terms of the Modified BSD License.\n\"\"\"Tests for traitlets.utils.importstring.\"\"\"\n\nimport os\nfrom unittest import TestCase\n\nfrom ..importstring import import_item\n\n\nclass TestImportItem(TestCase):\n\n    def test_import_unicode(self):\n        self.assertIs(os, import_item(u'os'))\n        self.assertIs(os.path, import_item(u'os.path'))\n        self.assertIs(os.path.join, import_item(u'os.path.join'))\n\n    def test_bad_input(self):\n        class NotAString(object):\n            pass\n        msg = (\n            \"import_item accepts strings, \"\n            \"not '%s'.\" % NotAString\n        )\n        with self.assertRaisesRegexp(TypeError, msg):\n            import_item(NotAString())\n"
  },
  {
    "path": "lib/client/update_decorator.sh",
    "content": "#!/bin/bash\n# This script updates decorator to another version. Version is either the git tag\n# or the commit has of the respective release\n#\n# Usage:\n#       ./update_traitlets.sh 4.0.0\n#\ncur_path=`pwd`\nred='\\033[0;31m'\nnoc='\\033[0m'\n\nif [[ $1 == \"\" ]]; then\n    echo -e \"${red}ERROR\"\n    echo -e \"${noc}No version spefified.\"\n    echo \"\"\n    echo \"Exiting...\"\n    exit 1;\nfi\n\n\nrm -rf /tmp/decorator\ngit clone https://github.com/micheles/decorator /tmp/decorator\n\ncd /tmp/decorator\ngit checkout $1\ncd $cur_path\n\ngit_status=`git status -- decorator | tail -n 1`\ngit_clean=\"nothing to commit, working tree clean\"\n\nif [[ $git_status == $git_clean ]]; then\n    rm -rf decorator/\n    mv /tmp/decorator/src/decorator.py .\n    echo $1 > decorator_version\nelse\n    echo \"\"\n    echo -e \"${red}ERROR\"\n    echo \"There are uncommitted changes or untracked files in './decorator.py'.\"\n    echo \"\"\n    echo -e \"${noc}See 'git status -- decorator.py' for more details.\"\nfi\n\nrm -rf /tmp/decorator\n\n"
  },
  {
    "path": "lib/client/update_ipython_genutils.sh",
    "content": "#!/bin/bash\n# This script updates ipython_genutils to another version. Version is either the git tag\n# or the commit has of the respective release\n#\n# Usage:\n#       ./update_ipython_genutils.sh 4.0.0\n#\ncur_path=`pwd`\nred='\\033[0;31m'\nnoc='\\033[0m'\n\nif [[ $1 == \"\" ]]; then\n    echo -e \"${red}ERROR\"\n    echo -e \"${noc}No version spefified.\"\n    echo \"\"\n    echo \"Exiting...\"\n    exit 1;\nfi\n\n\nrm -rf /tmp/ipython_genutils\ngit clone https://github.com/ipython/ipython_genutils /tmp/ipython_genutils\n\ncd /tmp/ipython_genutils\ngit checkout $1\ncd $cur_path\n\ngit_status=`git status -- ipython_genutils | tail -n 1`\ngit_clean=\"nothing to commit, working tree clean\"\n\nif [[ $git_status == $git_clean ]]; then\n    rm -rf ipython_genutils/\n    mv /tmp/ipython_genutils/ipython_genutils .\n\n    rm -rf ipython_genutils/testing\n    rm -rf ipython_genutils/tests\nelse\n    echo \"\"\n    echo -e \"${red}ERROR\"\n    echo \"There are uncommitted changes or untracked files in './ipython_genutils/'.\"\n    echo \"\"\n    echo -e \"${noc}See 'git status -- ipython_genutils' for more details.\"\nfi\n\nrm -rf /tmp/ipython_genutils\n\n"
  },
  {
    "path": "lib/client/update_jupyter_client.sh",
    "content": "#!/bin/bash\n# This script updates jupyter_client to another version. Version is either the git tag\n# or the commit has of the respective release\n#\n# Usage:\n#       ./update_jupyter_client.sh 4.0.0\n#\ncur_path=`pwd`\nred='\\033[0;31m'\nnoc='\\033[0m'\n\nif [[ $1 == \"\" ]]; then\n    echo -e \"${red}ERROR\"\n    echo -e \"${noc}No version spefified.\"\n    echo \"\"\n    echo \"Exiting...\"\n    exit 1;\nfi\n\n\nrm -rf /tmp/jupyter_client\ngit clone https://github.com/jupyter/jupyter_client /tmp/jupyter_client\n\ncd /tmp/jupyter_client\ngit checkout $1\ncd $cur_path\n\ngit_status=`git status -- jupyter_client | tail -n 1`\ngit_clean=\"nothing to commit, working tree clean\"\n\nif [[ $git_status == $git_clean ]]; then\n    rm -rf jupyter_client/\n    mv /tmp/jupyter_client/jupyter_client .\n\n    rm -rf jupyter_client/tests\nelse\n    echo \"\"\n    echo -e \"${red}ERROR\"\n    echo \"There are uncommitted changes or untracked files in './jupyter_client/'.\"\n    echo \"\"\n    echo -e \"${noc}See 'git status -- jupyter_client' for more details.\"\nfi\n\nrm -rf /tmp/jupyter_client\n\n"
  },
  {
    "path": "lib/client/update_jupyter_core.sh",
    "content": "#!/bin/bash\n# This script updates jupyter_core to another version. Version is either the git tag\n# or the commit has of the respective release\n#\n# Usage:\n#       ./update_jupyter_core.sh 4.0.0\n#\ncur_path=`pwd`\nred='\\033[0;31m'\nnoc='\\033[0m'\n\nif [[ $1 == \"\" ]]; then\n    echo -e \"${red}ERROR\"\n    echo -e \"${noc}No version spefified.\"\n    echo \"\"\n    echo \"Exiting...\"\n    exit 1;\nfi\n\n\nrm -rf /tmp/jupyter_core\ngit clone https://github.com/jupyter/jupyter_core /tmp/jupyter_core\n\ncd /tmp/jupyter_core\ngit checkout $1\ncd $cur_path\n\ngit_status=`git status -- jupyter_core | tail -n 1`\ngit_clean=\"nothing to commit, working tree clean\"\n\nif [[ $git_status == $git_clean ]]; then\n    rm -rf jupyter_core/\n    mv /tmp/jupyter_core/jupyter_core .\n\n    rm -rf jupyter_core/tests\nelse\n    echo \"\"\n    echo -e \"${red}ERROR\"\n    echo \"There are uncommitted changes or untracked files in './jupyter_core/'.\"\n    echo \"\"\n    echo -e \"${noc}See 'git status -- jupyter_core' for more details.\"\nfi\n\nrm -rf /tmp/jupyter_core\n\n"
  },
  {
    "path": "lib/client/update_traitlets.sh",
    "content": "#!/bin/bash\n# This script updates traitlets to another version. Version is either the git tag\n# or the commit has of the respective release\n#\n# Usage:\n#       ./update_traitlets.sh 4.0.0\n#\ncur_path=`pwd`\nred='\\033[0;31m'\nnoc='\\033[0m'\n\nif [[ $1 == \"\" ]]; then\n    echo -e \"${red}ERROR\"\n    echo -e \"${noc}No version spefified.\"\n    echo \"\"\n    echo \"Exiting...\"\n    exit 1;\nfi\n\n\nrm -rf /tmp/traitlets\ngit clone https://github.com/ipython/traitlets /tmp/traitlets\n\ncd /tmp/traitlets\ngit checkout $1\ncd $cur_path\n\ngit_status=`git status -- traitlets | tail -n 1`\ngit_clean=\"nothing to commit, working tree clean\"\n\nif [[ $git_status == $git_clean ]]; then\n    rm -rf traitlets/\n    mv /tmp/traitlets/traitlets .\n\n    rm -rf traitlets/tests\n    rm -rf traitlets/config/tests\nelse\n    echo \"\"\n    echo -e \"${red}ERROR\"\n    echo \"There are uncommitted changes or untracked files in './traitlets/'.\"\n    echo \"\"\n    echo -e \"${noc}See 'git status -- traitlets' for more details.\"\nfi\n\nrm -rf /tmp/traitlets\n\n"
  },
  {
    "path": "lib/kernel.py",
    "content": "\"\"\"Definition of KernelConnection class.\n\nKernelConnection class provides interaction with Jupyter kernels.\n\nCopyright (c) 2017-2018, NEGORO Tetsuya (https://github.com/ngr-t)\n\"\"\"\nimport re\nfrom collections import defaultdict\nfrom datetime import datetime\nfrom queue import Empty, Queue\nfrom threading import Event, RLock, Thread\n\nimport sublime\n\nfrom .utils import get_cell, get_png_dimensions, show_password_input\n\nJUPYTER_PROTOCOL_VERSION = \"5.0\"\n\nREPLY_STATUS_OK = \"ok\"\nREPLY_STATUS_ERROR = \"error\"\nREPLY_STATUS_ABORT = \"abort\"\n\nMSG_TYPE_EXECUTE_INPUT = \"execute_input\"\nMSG_TYPE_EXECUTE_REQUEST = \"execute_request\"\nMSG_TYPE_EXECUTE_RESULT = \"execute_result\"\nMSG_TYPE_EXECUTE_REPLY = \"execute_reply\"\nMSG_TYPE_COMPLETE_REQUEST = \"complete_request\"\nMSG_TYPE_COMPLETE_REPLY = \"complete_reply\"\nMSG_TYPE_DISPLAY_DATA = \"display_data\"\nMSG_TYPE_INSPECT_REQUEST = \"inspect_request\"\nMSG_TYPE_INSPECT_REPLY = \"inspect_reply\"\nMSG_TYPE_INPUT_REQUEST = \"input_request\"\nMSG_TYPE_INPUT_REPLY = \"input_reply\"\nMSG_TYPE_ERROR = \"error\"\nMSG_TYPE_STREAM = \"stream\"\nMSG_TYPE_STATUS = \"status\"\n\nHELIUM_FIGURE_PHANTOMS = \"helium_figure_phantoms\"\nMAX_PHANTOMS = 65536\n\n# Used as key of status bar.\nKERNEL_STATUS_KEY = \"helium_kernel_status\"\n\nHELIUM_OBJECT_INSPECT_PANEL = \"helium_object_inspect\"\n\nANSI_ESCAPE_PATTERN = re.compile(r\"\\x1b[^m]*m\")\n\nOUTPUT_VIEW_SEPARATOR = \"-\" * 80\n\nTEXT_PHANTOM = \"\"\"<body id=\"helium-result\">\n  <style>\n    .stdout {{ color: color(var(--foreground) alpha(0.7)) }}\n    .error {{ color: var(--redish) }}\n    .other {{ color: var(--yellowish) }}\n    .closebutton {{ text-decoration: none }}\n  </style>\n  <a class=closebutton href=hide>×</a>\n  {content}\n</body>\"\"\"\n\nIMAGE_PHANTOM = \"\"\"<body id=\"helium-image-result\" style=\"background-color:none\">\n  <style>\n    .image {{ background-color: none }}\n    .closebutton {{ text-decoration: none }}\n  </style>\n  <a class=closebutton href=hide>×</a>\n  <br>\n  <img class=\"image\" alt=\"Out\" style=\"width: {width}; height: {height}\" src=\"data:image/png;base64,{data}\" />\n</body>\"\"\"\n\nSTREAM_PHANTOM = \"<div class={name}>{content}</div>\"\n\n\ndef fix_whitespace_for_phantom(text: str):\n    \"\"\"Transform output for proper display.\n\n    This is important to display pandas DataFrames, for instance.\n    \"\"\"\n    text = text.replace(\" \", r\"&nbsp;\")\n    text = \"<br>\".join(text.splitlines())\n    return text\n\n\ndef extract_content(messages, msg_type):\n    \"\"\"Extract content from messages received from a kernel.\"\"\"\n    return [\n        message[\"content\"]\n        for message in messages\n        if message[\"header\"][\"msg_type\"] == msg_type\n    ]\n\n\ndef remove_ansi_escape(text: str):\n    return ANSI_ESCAPE_PATTERN.sub(\"\", text)\n\n\ndef get_msg_type(message):\n    return message[\"header\"][\"msg_type\"]\n\n\ndef extract_data(result):\n    \"\"\"Extract plain text data.\"\"\"\n    try:\n        return result[\"data\"]\n    except KeyError:\n        return \"\"\n\n\nclass KernelConnection(object):\n    \"\"\"Interact with a Jupyter kernel.\"\"\"\n\n    class MessageReceiver(Thread):  # noqa\n        def __init__(self, kernel):\n            \"\"\"Initialize AsyncCommunicator class.\"\"\"\n            super().__init__()\n            self._kernel = kernel\n            self.exit = Event()\n\n        def shutdown(self):\n            self.exit.set()\n\n    class ShellMessageReceiver(MessageReceiver):\n        \"\"\"Communicator that runs asynchroniously.\"\"\"\n\n        def run(self):\n            \"\"\"Run main routine.\"\"\"\n            # TODO: implement logging\n            # TODO: remove view and regions from id2region\n            while not self.exit.is_set():\n                try:\n                    msg = self._kernel.client.get_shell_msg(timeout=1)\n                    self._kernel.shell_msg_queues_lock.acquire()\n                    try:\n                        queue = self._kernel.shell_msg_queues[\n                            msg[\"parent_header\"][\"msg_id\"]\n                        ]\n                    finally:\n                        self._kernel.shell_msg_queues_lock.release()\n                    queue.put(msg)\n                except Empty:\n                    pass\n                except Exception as ex:\n                    self._kernel._logger.exception(ex)\n\n    class IOPubMessageReceiver(MessageReceiver):\n        \"\"\"Receive and process IOPub messages.\"\"\"\n\n        def run(self):\n            \"\"\"Run main routine.\"\"\"\n            # TODO: log, handle other message types.\n\n            while not self.exit.is_set():\n                try:\n                    msg = self._kernel.client.get_iopub_msg(timeout=1)\n                    self._kernel._logger.info(msg)\n                    content = msg.get(\"content\", {})\n                    execution_count = content.get(\"execution_count\", None)\n                    msg_type = msg[\"msg_type\"]\n                    view, region = self._kernel.id2region.get(\n                        msg[\"parent_header\"].get(\"msg_id\", None), (None, None)\n                    )\n\n                    if msg_type == MSG_TYPE_STATUS:\n                        self._kernel._execution_state = content[\"execution_state\"]\n                    elif msg_type == MSG_TYPE_EXECUTE_INPUT:\n                        # if code is executed deleted all phantoms in this region\n                        self._kernel._clear_phantoms_in_region(region, view)\n\n                        self._kernel._write_text_to_view(\"\\n\\n\")\n                        if sublime.load_settings(\"Helium.sublime-settings\").get(\n                            \"output_code\"\n                        ):\n                            self._kernel._output_input_code(\n                                content[\"code\"], content[\"execution_count\"]\n                            )\n                    elif msg_type == MSG_TYPE_ERROR:\n                        self._kernel._logger.info(\"Handling error\")\n                        self._kernel._handle_error(\n                            content[\"ename\"],\n                            content[\"evalue\"],\n                            content[\"traceback\"],\n                            region,\n                            view,\n                        )\n                    elif msg_type == MSG_TYPE_DISPLAY_DATA:\n                        self._kernel._write_mime_data_to_view(\n                            content[\"data\"], region, view\n                        )\n                    elif msg_type == MSG_TYPE_EXECUTE_RESULT:\n                        self._kernel._write_mime_data_to_view(\n                            content[\"data\"], region, view\n                        )\n                    elif msg_type == MSG_TYPE_STREAM:\n                        self._kernel._handle_stream(\n                            content[\"name\"],\n                            content[\"text\"],\n                            region,\n                            view,\n                        )\n\n                except Empty:\n                    pass\n                except Exception as ex:\n                    self._kernel._logger.exception(ex)\n\n    class StdInMessageReceiver(MessageReceiver):\n        \"\"\"Receive and process IOPub messages.\"\"\"\n\n        def _handle_input_request(self, prompt, password):\n            def interrupt():\n                self._kernel.interrupt_kernel(self.kernel_id)\n\n            if password:\n                show_password_input(prompt, self._kernel.input, interrupt)\n            else:\n                (\n                    sublime.active_window().show_input_panel(\n                        prompt, \"\", self._kernel.client.input, lambda x: None, interrupt\n                    )\n                )\n\n        def run(self):\n            \"\"\"Run main routine.\"\"\"\n            # TODO: log, handle other message types.\n            while not self.exit.is_set():\n                try:\n                    msg = self._kernel.client.get_stdin_msg(timeout=1)\n                    msg_type = msg[\"msg_type\"]\n                    content = msg[\"content\"]\n                    if msg_type == MSG_TYPE_INPUT_REQUEST:\n                        self._handle_input_request(\n                            content[\"prompt\"], content[\"password\"]\n                        )\n                except Empty:\n                    pass\n                except Exception as ex:\n                    self._kernel._logger.exception(ex)\n\n    def _init_receivers(self):\n        # Set the attributes refered by receivers before they start.\n        self._shell_msg_receiver = self.ShellMessageReceiver(self)\n        self._shell_msg_receiver.start()\n        self._iopub_msg_receiver = self.IOPubMessageReceiver(self)\n        self._iopub_msg_receiver.start()\n        self._stdin_msg_receiver = self.StdInMessageReceiver(self)\n        self._stdin_msg_receiver.start()\n\n    def __init__(\n        self,\n        kernel_id,\n        kernel_manager,\n        parent,\n        connection_name=None,\n        logger=None,\n    ):\n        \"\"\"Initialize KernelConnection class.\n\n        parameters\n        ---------\n        kernel_id str: kernel ID\n        parent parent kernel manager\n        \"\"\"\n        self._logger = logger\n        self.shell_msg_queues = defaultdict(Queue)\n        self._kernel_id = kernel_id\n        self.parent = parent\n        self.kernel_manager = kernel_manager\n        self.client = self.kernel_manager.client()\n        self.client.start_channels()\n        self.shell_msg_queues_lock = RLock()\n        self.id2region = {}\n        self._connection_name = connection_name\n        self._execution_state = \"unknown\"\n        self._init_receivers()\n        self.phantoms = {}\n\n    def __del__(self):  # noqa\n        self._shell_msg_receiver.shutdown()\n        self._iopub_msg_receiver.shutdown()\n        self._stdin_msg_receiver.shutdown()\n\n    @property\n    def lang(self):\n        \"\"\"Language of kernel.\"\"\"\n        return self.kernel_manager.kernel_name\n\n    @property\n    def kernel_id(self):\n        \"\"\"ID of kernel.\"\"\"\n        return self._kernel_id\n\n    def shutdown_kernel(self):\n        self.kernel_manager.shutdown_kernel()\n\n    def restart_kernel(self):\n        self.kernel_manager.restart_kernel()\n\n    def interrupt_kernel(self):\n        self.kernel_manager.interrupt_kernel()\n\n    def get_connection_name(self):\n        return self._connection_name\n\n    def set_connection_name(self, new_name):\n        # We also have to change the view name now.\n        view = self.get_view()\n        self._connection_name = new_name\n        view.set_name(self.view_name)\n\n    def del_connection_name(self):\n        self._connection_name = None\n\n    connection_name = property(\n        get_connection_name,\n        set_connection_name,\n        del_connection_name,\n        \"Name of kernel connection shown in a view title.\",\n    )\n\n    @property\n    def view_name(self):\n        \"\"\"Return name of output view.\"\"\"\n        return \"*Helium Output* {repr}\".format(repr=self.repr)\n\n    @property\n    def repr(self):\n        \"\"\"Return string representation of the connection.\"\"\"\n        if self.connection_name:\n            return \"{connection_name} ([{lang}] {kernel_id})\".format(\n                connection_name=self.connection_name,\n                lang=self.lang,\n                kernel_id=self.kernel_id,\n            )\n        else:\n            return \"[{lang}] {kernel_id}\".format(\n                lang=self.lang, kernel_id=self.kernel_id\n            )\n\n    @property\n    def execution_state(self):\n        return self._execution_state\n\n    @property\n    def _show_inline_output(self):\n        return sublime.load_settings(\"Helium.sublime-settings\").get(\"inline_output\")\n\n    def activate_view(self):\n        \"\"\"Activate view to show the output of kernel.\"\"\"\n        view = self.get_view()\n        current_view = sublime.active_window().active_view()\n        sublime.active_window().focus_view(view)\n        view.set_scratch(True)  # avoids prompting to save\n        view.settings().set(\"word_wrap\", \"false\")\n        sublime.active_window().focus_view(current_view)\n\n    def _output_input_code(self, code, execution_count):\n        line = \"In[{execution_count}]: {code}\".format(\n            execution_count=execution_count, code=code\n        )\n        self._write_text_to_view(line)\n\n    def _handle_error(\n        self,\n        ename,\n        evalue,\n        traceback,\n        region: sublime.Region = None,\n        view: sublime.View = None,\n    ) -> None:\n        try:\n            lines = \"\"\"\\nError: {ename}, {evalue}.\n            \\nTraceback:\\n{traceback}\"\"\".format(\n                ename=ename,\n                evalue=evalue,\n                traceback=\"\\n\".join(traceback),\n            )\n            lines = remove_ansi_escape(lines)\n            self._write_text_to_view(lines)\n            if region is not None:\n                phantom_html = STREAM_PHANTOM.format(\n                    name=\"error\", content=fix_whitespace_for_phantom(lines)\n                )\n                self._write_inline_html_phantom(phantom_html, region, view)\n        except AttributeError:\n            # Just there is no error.\n            pass\n\n    def _handle_stream(\n        self, name, text, region: sublime.Region = None, view: sublime.View = None\n    ) -> None:\n        # Currently don't consider real time catching of streams.\n        try:\n            lines = \"\\n({name}):\\n{text}\".format(name=name, text=text)\n            phantom_html = STREAM_PHANTOM.format(\n                name=name, content=fix_whitespace_for_phantom(text)\n            )\n            self._write_text_to_view(lines)\n            if phantom_html and (region is not None):\n                self._write_inline_html_phantom(phantom_html, region, view)\n        except AttributeError:\n            # Just there is no error.\n            pass\n\n    def _write_out_execution_count(self, execution_count) -> None:\n        self._write_text_to_view(\"\\nOut[{}]: \\n\".format(execution_count))\n\n    def _write_text_to_view(self, text: str) -> None:\n        if self._show_inline_output:\n            return\n        self.activate_view()\n        view = self.get_view()\n        view.set_read_only(False)\n        view.run_command(\"append\", {\"characters\": text})\n        view.set_read_only(True)\n        view.show(view.size())\n\n    def _write_phantom(self, content: str):\n        if self._show_inline_output:\n            return\n        self.activate_view()\n        file_size = self.get_view().size()\n        region = sublime.Region(file_size, file_size)\n\n        self.get_view().add_phantom(\n            HELIUM_FIGURE_PHANTOMS, region, content, sublime.LAYOUT_BLOCK\n        )\n        self._logger.info(\"Created phantom {}\".format(content))\n\n    def _write_inline_html_phantom(\n        self, content: str, region: sublime.Region, view: sublime.View\n    ):\n        if self._show_inline_output:\n            id = HELIUM_FIGURE_PHANTOMS + datetime.now().isoformat()\n\n            html = TEXT_PHANTOM.format(content=content)\n            self._add_phantom(view, id, region, html)\n\n    def _write_inline_image_phantom(\n        self, data: str, region: sublime.Region, view: sublime.View\n    ):\n        if self._show_inline_output:\n            id = HELIUM_FIGURE_PHANTOMS + datetime.now().isoformat()\n            img_size = sublime.load_settings(\"Helium.sublime-settings\").get(\n                \"image_size\", \"optimal\"\n            )\n\n            width = view.viewport_extent()[0] - 2\n            dimensions = get_png_dimensions(data)\n\n            if img_size == \"original\" or (\n                img_size == \"optimal\" and (dimensions[0] < width)\n            ):\n                html = IMAGE_PHANTOM.format(\n                    data=data, width=dimensions[0], height=dimensions[1]\n                )\n            else:\n                scale_factor = width / dimensions[0]\n                height = dimensions[1] * scale_factor\n\n                html = IMAGE_PHANTOM.format(data=data, width=width, height=height)\n\n            self._add_phantom(view, id, region, html)\n\n    def _add_phantom(\n        self, view: sublime.View, id: str, region: sublime.Region, html: str\n    ):\n        int_id = view.add_phantom(\n            id,\n            region,\n            html,\n            sublime.LAYOUT_BLOCK,\n            on_navigate=lambda href, id=id, view=view: self._erase_phantom(\n                id, view=view\n            ),\n        )\n        self.phantoms[id] = int_id\n\n        if int_id > MAX_PHANTOMS:\n            sublime.message_dialog(\n                \"Please close and reopen your current tab. \"\n                + \"Otherwise the 'Clear All Cells' command might not work as intended.\"\n            )\n        self._logger.info(\"Created inline phantom image\")\n\n    def _clear_phantoms_in_region(self, region: sublime.Region, view: sublime.View):\n        _, cell = get_cell(view, region, logger=\"\")\n        remove = [\n            pid\n            for pid, int_id in self.phantoms.items()\n            if cell.contains(view.query_phantom(int_id)[0])\n        ]\n\n        for pid in remove:\n            self._erase_phantom(pid, view=view)\n\n    def _erase_phantom(self, pid: str, *, view: sublime.View):\n        if pid in self.phantoms:\n            _ = self.phantoms.pop(pid)\n            view.erase_phantoms(pid)\n\n    def _write_mime_data_to_view(\n        self, mime_data: dict, region: sublime.Region, view: sublime.View\n    ) -> None:\n        # Now we use basically text/plain for text type.\n        # Jupyter kernels often emits html whom minihtml cannot render.\n\n        if \"text/plain\" in mime_data:\n            content = mime_data[\"text/plain\"]\n            lines = \"\\n(display data): {content}\".format(content=content)\n            self._write_text_to_view(lines)\n            self._write_inline_html_phantom(\n                fix_whitespace_for_phantom(content), region, view\n            )\n        elif \"text/html\" in mime_data:\n            self._logger.info(\n                \"Caught 'text/html' output without plain text. \"\n                \"Try to show with phantom.\"\n            )\n            content = mime_data[\"text/html\"]\n            self._write_phantom(content)\n            self._write_inline_html_phantom(content, region, view)\n\n        if \"image/png\" in mime_data:\n            data = mime_data[\"image/png\"].strip()\n\n            img_size = sublime.load_settings(\"Helium.sublime-settings\").get(\n                \"image_size\", \"optimal\"\n            )\n\n            self._logger.info(self.get_view().viewport_extent())\n            width = self.get_view().viewport_extent()[0] - 2\n            dimensions = get_png_dimensions(data)\n\n            if img_size == \"original\" or (\n                img_size == \"optimal\" and (dimensions[0] < width)\n            ):\n                width, height = dimensions\n            else:\n                scale_factor = width / dimensions[0]\n                height = dimensions[1] * scale_factor\n\n            content = (\n                '<body style=\"background-color: none\">'\n                '<img alt=\"Out\" style=\"width: {width}; height: {height}\" src=\"data:image/png;base64,{data}\" />'\n                + \"</body>\"\n            ).format(data=data, width=width, height=height, bgcolor=\"white\")\n\n            self._write_phantom(content)\n            self._write_inline_image_phantom(data, region, view)\n\n    def _handle_inspect_reply(self, reply: dict):\n        window = sublime.active_window()\n        if window.find_output_panel(HELIUM_OBJECT_INSPECT_PANEL) is not None:\n            window.destroy_output_panel(HELIUM_OBJECT_INSPECT_PANEL)\n        view = window.create_output_panel(HELIUM_OBJECT_INSPECT_PANEL)\n        try:\n            self._logger.debug(reply)\n            text = remove_ansi_escape(reply[\"text/plain\"])\n            view.run_command(\"append\", {\"characters\": text})\n            window.run_command(\n                \"show_panel\", {\"panel\": \"output.\" + HELIUM_OBJECT_INSPECT_PANEL}\n            )\n\n        except KeyError as ex:\n            self._logger.exception(ex)\n\n    def get_view(self):\n        \"\"\"Get view corresponds to the KernelConnection.\"\"\"\n        view = None\n        view_name = self.view_name\n        window = sublime.active_window()\n        views = window.views()\n        for view_candidate in views:\n            if view_candidate.name() == view_name:\n                return view_candidate\n        if not view:\n            active_group = window.active_group()\n            view = window.new_file()\n            view.set_name(view_name)\n            view.settings().set(\"syntax\", \"Packages/Helium/Helium.sublime-syntax\")\n            num_group = window.num_groups()\n            if num_group != 1:\n                if active_group + 1 < num_group:\n                    new_group = active_group + 1\n                else:\n                    new_group = active_group - 1\n                window.set_view_index(\n                    view, new_group, len(window.sheets_in_group(new_group))\n                )\n            return view\n\n    def execute_code(self, code, phantom_region, view):\n        \"\"\"Run code with Jupyter kernel.\"\"\"\n        msg_id = self.client.execute(code)\n        self.id2region[msg_id] = (\n            view,\n            sublime.Region(phantom_region.end() - 1, phantom_region.end() - 1),\n        )\n        info_message = \"Kernel executed code ```{code}```.\".format(code=code)\n        self._logger.info(info_message)\n\n    def is_alive(self):\n        \"\"\"Return True if kernel is alive.\"\"\"\n        return self.client.hb_channel.is_beating()\n\n    def get_complete(self, code, cursor_pos, timeout=None):\n        \"\"\"Generate complete request.\"\"\"\n        if self.execution_state != \"idle\":\n            return []\n        msg_id = self.client.complete(code, cursor_pos)\n        self.shell_msg_queues_lock.acquire()\n        try:\n            queue = self.shell_msg_queues[msg_id]\n        finally:\n            self.shell_msg_queues_lock.release()\n\n        try:\n            recv_msg = queue.get(timeout=timeout)\n            recv_content = recv_msg[\"content\"]\n            self._logger.info(recv_content)\n            if \"_jupyter_types_experimental\" in recv_content.get(\"metadata\", {}):\n                # If the reply has typing metadata, use it.\n                # This metadata for typing is obviously experimental\n                # and not documented yet.\n                return [\n                    (\n                        match[\"text\"]\n                        + \"\\t\"\n                        + (\n                            \"<no type info>\" if match[\"type\"] is None else match[\"type\"]\n                        ),\n                        match[\"text\"],\n                    )\n                    for match in recv_content[\"metadata\"][\"_jupyter_types_experimental\"]\n                ]\n            else:\n                # Just say the completion is came from this plugin, otherwise.\n                return [\n                    (match + \"\\tHelium\", match) for match in recv_content[\"matches\"]\n                ]\n        except Empty:\n            self._logger.info(\"Completion timeout.\")\n        except Exception as ex:\n            self._logger.exception(ex)\n        finally:\n            self.shell_msg_queues_lock.acquire()\n            try:\n                self.shell_msg_queues.pop(msg_id, None)\n            finally:\n                self.shell_msg_queues_lock.release()\n\n        return []\n\n    def get_inspection(self, code, cursor_pos, detail_level=0, timeout=None):\n        \"\"\"Get object inspection by sending a `inspect_request` message to kernel.\"\"\"\n        msg_id = self.client.inspect(code, cursor_pos, detail_level)\n        self.shell_msg_queues_lock.acquire()\n        try:\n            queue = self.shell_msg_queues[msg_id]\n        finally:\n            self.shell_msg_queues_lock.release()\n\n        try:\n            recv_msg = queue.get(timeout=timeout)\n            self._handle_inspect_reply(recv_msg[\"content\"][\"data\"])\n        except Empty:\n            self._logger.info(\"Object inspection timeout.\")\n\n        finally:\n            self.shell_msg_queues_lock.acquire()\n            try:\n                self.shell_msg_queues.pop(msg_id, None)\n            finally:\n                self.shell_msg_queues_lock.release()\n"
  },
  {
    "path": "lib/utils.py",
    "content": "import bisect\nimport re\nimport sys\nfrom base64 import b64decode\nfrom functools import wraps\n\nimport sublime\nfrom sublime_plugin import TextCommand\n\n\nclass add_path(object):\n    \"\"\"Temporarily insert a path into sys.path.\"\"\"\n\n    def __init__(self, path):\n        self.path = path\n\n    def __enter__(self):  # noqa\n        sys.path.insert(0, self.path)\n\n    def __exit__(self, exc_type, exc_value, traceback):  # noqa\n        sys.path.remove(self.path)\n\n\ndef chain_callbacks(f):\n    \"\"\"Decorate to mimic the promise pattern via an yield expression.\n\n    Decorator function to make a wrapper which executes functions\n    yielded by the given generator in order.\n    \"\"\"\n\n    @wraps(f)\n    def wrapper(*args, **kwargs):\n        chain = f(*args, **kwargs)\n        try:\n            next_f = next(chain)\n        except StopIteration:\n            return\n\n        def cb(*args, **kwargs):\n            nonlocal next_f\n            try:\n                if len(args) + len(kwargs) != 0:\n                    next_f = chain.send(*args, **kwargs)\n                else:\n                    next_f = next(chain)\n                next_f(cb)\n            except StopIteration:\n                return\n\n        next_f(cb)\n\n    return wrapper\n\n\nPASSWORD_INPUT_PATTERN = re.compile(r\"^(\\**)([^*]+)(\\**)\")\n\n\nclass MaskInputPanelText(TextCommand):\n    \"\"\"Command to hide all the charatcters of view by '*'.\"\"\"\n\n    def run(self, edit):\n        s = self.view.size()\n        region = sublime.Region(0, s)\n        self.view.replace(edit, region, s * \"*\")\n\n\ndef show_password_input(prompt, on_done, on_cancel):\n    hidden_input = \"\"\n    view = None\n\n    def get_hidden_input(user_input):\n        nonlocal hidden_input\n        on_done(hidden_input)\n\n    def hide_input(user_input):\n        nonlocal view\n        nonlocal hidden_input\n\n        matches = PASSWORD_INPUT_PATTERN.match(user_input)\n        if matches:\n            # When there are characters other than \"*\"\n            pre, new, post = matches.group(1, 2, 3)\n            hidden_input = (\n                hidden_input[: len(pre)]\n                + new\n                + hidden_input[len(hidden_input) - len(post) : len(hidden_input)]\n            )\n            view.run_command(\"mask_input_panel_text\")\n        else:\n            try:\n                pos = view.sel()[0].begin()\n                hidden_input = hidden_input[:pos] + hidden_input[pos : len(user_input)]\n            except AttributeError:\n                # `view` is not assigned at first time this function is called.\n                pass\n\n    view = sublime.active_window().show_input_panel(\n        prompt, \"\", get_hidden_input, hide_input, on_cancel\n    )\n\n\ndef get_png_dimensions(base64):\n    \"\"\"\n    Extrac the dimension properties of the IHDR information encoded in base 64.\n    \"\"\"\n\n    wh = b64decode(base64[20:32])\n    iwidth = int.from_bytes(wh[1:5], byteorder=\"big\")\n    iheight = int.from_bytes(wh[5:], byteorder=\"big\")\n    return (iwidth, iheight)\n\n\ndef get_cell(\n    view: sublime.View, region: sublime.Region, *, logger: str\n) -> (str, sublime.Region):\n    \"\"\"Get the code cell under the cursor.\n\n    Cells are separated by markers.\n    Those are defined in `cell_delimiter_pattern` in the config file.\n\n    If `s` is a selected region, the code cell is it.\n    \"\"\"\n    if not region.empty():\n        return (view.substr(region), region)\n    cell_delimiter_pattern = sublime.load_settings(\"Helium.sublime-settings\").get(\n        \"cell_delimiter_pattern\"\n    )\n    separators = view.find_all(cell_delimiter_pattern)\n    separators.append(sublime.Region(view.size() + 2, view.size() + 2))\n    r = sublime.Region(region.begin() + 1, region.begin() + 1)\n    start_point = separators[bisect.bisect(separators, r) - 1].end() + 1\n    end_point = separators[bisect.bisect(separators, r)].begin() - 1\n    cell_region = sublime.Region(start_point, end_point)\n    return (view.substr(cell_region), cell_region)\n"
  },
  {
    "path": "messages/0.3.1.txt",
    "content": "Update in 0.3.1\n---------------\n\nFixed some problems (thanks @randy3k for feedback!)\n\n  - Handle \"text/markdown\" MIME type in `display_data` messages. Some kernel (such as IRkernel) uses this to show object repr instead of `execute_result`.\n  - Add `username` and `session` item in message headers. Some kernel (such as IJulia) require them.\n"
  },
  {
    "path": "messages/0.3.2.txt",
    "content": "Update in 0.3.2\n---------------\n\n  - Use wss for https connections. This enables Hermes to connect Jupyterhub server using token. See https://github.com/ngr-t/SublimeHermes/issues/1 for details. (Thanks to @randy3k)"
  },
  {
    "path": "messages/0.3.3.txt",
    "content": "Update in 0.3.3\n---------------\n\n  - Fixed issue #3. Now `text/plain` type data are primarily used when `display_data` are written to the view.\n  - Fixed issue #5. `text/html` type data are shown with in phantoms unless there `text/plain` or `text/markdown` type exist in output data."
  },
  {
    "path": "messages/0.3.4.txt",
    "content": "Update in 0.3.4\n---------------\n\n  - Add request parameter on creating WebSocket connection to avoid \"No session ID specified\" warning dumped to the server log (#9).\n  - Show progress bar while the kernel is busy(#12).\n  - Disable \"Hermes: Execute Block\" command if the kernel is dead (#13).\n\nNow we plan to rename and refactor the commands as argued in #4 (working branch is #14).\nIf you have any openion about it, feel free to express it in the issue."
  },
  {
    "path": "messages/0.3.5.txt",
    "content": "Update in 0.3.5\n---------------\n\n  - Scroll to the end of the result buffer on code block execution(#15).\n  - Added `Hermes: Settings` command, which opens the side-by-side edit setting window.\n\nNow we plan to rename and refactor the commands as argued in #4 (working branch is #14).\nIf you have any openion about it, feel free to express it in the issue."
  },
  {
    "path": "messages/0.3.6.txt",
    "content": "Update in 0.3.6\n---------------\n\n  - Fixed code block detection when there are code block(s) selected.\n  - Better error handlings around communicating via Jupyter APIs (related to #19).\n\nNow we plan to rename and refactor the commands as argued in #4 (working branch is #14).\nIf you have any openion about it, feel free to express it in the issue."
  },
  {
    "path": "messages/0.4.0.txt",
    "content": "Update in 0.4.0\n---------------\n\n  - `Hermes: Set URL` command is renamed to `Hermes: Connect Server`.\n  - `Hermes: List Kernels` command is added. You can do several actions on kernels running in Jupyter process with this command.\n  - You become to be able to name the connections to the kernels, when you want.\n  - Execute, object inspection, interrupt, shutdown, and restart commands are now only shown when the active view is connected to a kernel.\n"
  },
  {
    "path": "messages/0.4.1.txt",
    "content": "Update in 0.4.1\n---------------\n\nFixed the bug failing to connect a kernel created by Hermes."
  },
  {
    "path": "messages/0.4.2.txt",
    "content": "Update in 0.4.2\n---------------\n\nFixed the bug that the editor hangs up when view is connected to a dead kernel. "
  },
  {
    "path": "messages/0.4.3.txt",
    "content": "Update in 0.4.3\n---------------\n\nFix to reuse an established WebSocket connection to Jupyter kernel. This should solve some performance issues."
  },
  {
    "path": "messages/0.5.0.txt",
    "content": "Update in 0.5.0\n---------------\n\nThis is update with big changes. Please read this release note.\nI had tackled with the known serious unstability issues, and large modification was required to solve it. Consequently it requires changes about the way to Jupyter kernel.\nThe way to make connection with Jupyter kernels is changed as below.\n\n\n### 1. The most basic way, start a kernelspec installed locally, as a subprocess of ST3 (the process stops when Sublime stops)\n\n  1. Run `Hermes: connect kernel` command.\n  2. Choose `New kernel`.\n  3. Choose the kernelspec you want to run.\n\n\n### 2. Connect to the kernel already runnning and connected to Hermes\n\n  1. Run `Hermes: connect kernel` command.\n  2. Choose the kernel you want to connect.\n\n### 3. Connect to a kernel already running under some other Jupyter app (such as Notebook)\n\n  1. Get connection info of the kernel. The way to get connection info differ among kernels, see the doc of each kernel (in ipython kernel, you can get it by `%connect_info` magic.)\n  2. Run `Hermes: connect kernel` command.\n  3. Choose `New kernel`.\n  4. Choose `(Enter connection info)`.\n  5. Enter the connection info (Hermes accepts a path or connection info itself).\n\n### 4. Connect to a kernel already running under some other Jupyter app, in a SSH server\n\n  1. Configure SSH servers in the setting file (opened by `Hermes: Settings` command.)\n  2. Get connection info of the kernel. The way to get connection info differ among kernels, see the doc of each kernel (in ipython kernel, you can get it by `%connect_info` magic.)\n  3. Run `Hermes: connect kernel` command.\n  4. Choose `New kernel`.\n  5. Choose `(Connect remote kernel via SSH)`.\n  6. Choose the server, then enter the connection info.\n\n\nI'm afraid that this change might break the workflow of some users, but I think it's more convenient for many people who works with locally running Jupyter. I ask you for your kind understanding about the changes.\n\n\n## New features\n\nThanks to @SamiPirbay, there are also new cool features, which are inline phantom mode and cell evaluation support.\n\n\n### Inline phantoms\n\nYou can get evaluation result as inline phantoms in the place where you executed code like Light Table or Hydrogen.\nIt's enabled by setting the `inline_output` option `True`. Each phantom has a small x mark to close it.\n\n\n### Cell evaluation support\n\nRegions surrounded by `# %%` or `# <codecell>` (you can configure it in `cell_delimiter_pattern` option item) are considered as \"code cells\".\n\nYou can execute a region by `Hermes: Execute cell` or `Hermes: Execute Cell and Move` command.\nEach cell has a clickable \"Run Cell\" phantom that appears next to the cell markers to run the cell.\n"
  },
  {
    "path": "messages/0.5.1.txt",
    "content": "Update in 0.5.1\n---------------\n\nFixed that text data in display_data were not shown as inline output. This has caused problem such as no execution results shown when we use IRkernel (#46).\n"
  },
  {
    "path": "messages/0.6.0.txt",
    "content": "Update in 0.6.0\n---------------\n\nThis release adds many quality of life features and fixes some bugs:\n\n- control the size of inline plots\n- transparent background for images\n- move the cursor after executing cell is the new default\n- selects the correct cell for execution\n- bugfixes\n\nAltogether, Helium should feel much smoother to use.\n\nIf you have any issues, please report them on [github/issues](https://github.com/sschuhmann/Helium/issues)\n"
  },
  {
    "path": "messages/0.6.1.txt",
    "content": "Update in 0.6.1\n---------------\n\n- added package control message\n"
  },
  {
    "path": "messages/0.6.2.txt",
    "content": "Update 0.6.2\n------------\n\n- fixed a bug where ST4 uses python 3.8 instead of python 3.3. Thanks to walterm128 for the fix.\n"
  },
  {
    "path": "messages/0.6.3.txt",
    "content": "Update 0.6.2\n------------\n\n- updated internal packages\n"
  },
  {
    "path": "messages.json",
    "content": "{\n    \"install\": \"README.md\",\n    \"0.3.1\": \"messages/0.3.1.txt\",\n    \"0.3.2\": \"messages/0.3.2.txt\",\n    \"0.3.3\": \"messages/0.3.3.txt\",\n    \"0.3.4\": \"messages/0.3.4.txt\",\n    \"0.3.5\": \"messages/0.3.5.txt\",\n    \"0.3.6\": \"messages/0.3.6.txt\",\n    \"0.4.0\": \"messages/0.4.0.txt\",\n    \"0.4.1\": \"messages/0.4.1.txt\",\n    \"0.4.2\": \"messages/0.4.2.txt\",\n    \"0.4.3\": \"messages/0.4.3.txt\",\n    \"0.5.0\": \"messages/0.5.0.txt\",\n    \"0.5.1\": \"messages/0.5.1.txt\",\n    \"0.6.0\": \"messages/0.6.0.txt\",\n    \"0.6.1\": \"messages/0.6.1.txt\",\n    \"0.6.2\": \"messages/0.6.2.txt\"\n}\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[tool.poetry]\nname = \"Helium\"\nversion = \"0.6.0\"\ndescription = \"Let Sublime Text 3 talk with Jupyter.\"\nauthors = [\"Ben Felder <ben@felder.io>\"]\nrepository = \"https://github.com/pykong/Helium\"\nreadme = \"README.md\"\nkeywords = [\"sublime-text-3\", \"jupyter\"]\nlicense = \"GPL-2.0-only\"\nexclude = []\n\n[tool.poetry.urls]\n\"Bug Tracker\" = \"https://github.com/pykong/Helium/issues\"\n\n[tool.poetry.dependencies]\npython = \"^3.8\"\nflake8-eradicate = \"^0.2.4\"\npre-commit = \"^2.0.1\"\n\n[tool.poetry.dev-dependencies]\nblack = {version = \"^24.3\", allow-prereleases = true}\nflake8 = \"^3.7.9\"\nflake8-blind-except = \"^0.1.1\"\nflake8-comprehensions = \"^3.2.2\"\nflake8-docstrings = \"^1.5.0\"\nisort = \"^4.3.21\"\nmypy = \"^0.761\"\n\n[tool.isort]\nline_length = 88\ncombine_star = true\nknown_third_party = []\nskip_glob = [\"lib/client\"]\n\n[tool.black]\nline-length = 88\ntarget_version = [\"py33\"]\nexclude = \"lib/client\"\n\n[build-system]\nrequires = [\"poetry>=0.12\"]\nbuild-backend = \"poetry.masonry.api\"\n\n[flake8]\nignore = \",E203,D100,D101,D102,D103,D104,D105,D106,D107,D203,W503,\"\nexclude = \",.git, .venv, lib/client,\"\nmax-line-length = 88\n"
  },
  {
    "path": "tests/_helpers.py",
    "content": "import sublime\n\nfrom unittest import TestCase\n\n\nclass ViewTestCase(TestCase):\n    \"\"\"Providing basic functionality for testing against views.\n\n    Taken from:\n    https://github.com/randy3k/AlignTab/blob/master/tests/test_basic.py\n    https://github.com/randy3k/AutoWrap/blob/master/tests/test_python.py\n    \"\"\"\n\n    def setUp(self):\n        # make sure we have a window to work with\n        s = sublime.load_settings(\"Preferences.sublime-settings\")\n        s.set(\"close_windows_when_empty\", False)\n        self.view = sublime.active_window().new_file()\n\n    def tearDown(self):\n        if self.view:\n            self.view.set_scratch(True)\n            self.view.window().run_command(\"close_file\")\n\n    def set_text(self, string):\n        self.view.run_command(\"insert\", {\"characters\": string})\n\n    def clear_view(self):\n        self.view.run_command(\"select_all\")\n        self.view.run_command(\"right_delete\")\n"
  },
  {
    "path": "tests/test_cell_handling.py",
    "content": "import sublime\n\nfrom _helpers import ViewTestCase\n\nvalid_delimiters = (\n    # %% pattern\n    \"#%%\",\n    \"# %%\",\n    # `in` pattern\n    \"# in[5]:\",\n    \"# in[]:\",\n    \"# in:\",\n    \"#in:\"\n)\n\ninvalid_delimiters = (\n    \"#\",\n    \"#%\",\n    \"#%?\",\n    \"%\",\n    \"% 123\",\n    \"no way\",\n    \"# normal comment\",\n    \"#xin:\",\n    \"#        in:\",\n    \"# in\",\n    \"in:\",\n    \"# In[5]:\",\n    \"# In[]:\",\n    \"# In:\"\n)\n\n\nclass TestDelimiter(ViewTestCase):\n\n    def find_all_delimiters(self):\n        s = sublime.load_settings(\"Helium.sublime-settings\")\n        pattern = s.get(\"cell_delimiter_pattern\")\n        return self.view.find_all(pattern)\n\n    def check_content_against_match_count(self, content, expected_count):\n        self.clear_view()\n        self.set_text(content)\n        matches = self.find_all_delimiters()\n        assert len(matches) == expected_count\n\n    def test_pattern_against_delimiteres_valid(self):\n        \"\"\"Succeed if all of the valid delimiters match.\"\"\"\n        for d in valid_delimiters:\n            # TODO: Use subTest once on ST4\n            self.check_content_against_match_count(d, 1)\n\n    def test_pattern_against_delimiteres_invalid(self):\n        \"\"\"Succeed if none of the invalid delimiters match.\"\"\"\n        for d in invalid_delimiters:\n            # TODO: Use subTest once on ST4\n            self.check_content_against_match_count(d, 0)\n\n    def test_delimiter_match_count_against_pattern_one(self):\n        \"\"\"Succeed if match count from view.find_all equal its expectation.\"\"\"\n        for i in range(10):\n            # TODO: Use subTest once on ST4\n            self.check_content_against_match_count(\"# %% \\n\" * i, i)\n\n    def test_delimiter_match_count_against_pattern_two(self):\n        \"\"\"Succeed if match count from view.find_all equal its expectation.\"\"\"\n        for i in range(10):\n            # TODO: Use subTest once on ST4\n            self.check_content_against_match_count(\"# in: \\n\" * i, i)\n\n    def test_delimiter_match_count_against_pattern_mixed(self):\n        \"\"\"Succeed if match count from view.find_all equal its expectation.\"\"\"\n        for i in range(10):\n            # TODO: Use subTest once on ST4\n            self.check_content_against_match_count(\"# %% \\n# in: \\n\" * i, i * 2)\n"
  },
  {
    "path": "tests/test_tests_running.py",
    "content": "import unittest\n\n\nclass TestThatTestsAreRunning(unittest.TestCase):\n    def test_that_never_fails(self):\n        \"\"\"Check that tests are indeed being run.\"\"\"\n        self.assertTrue(True)\n"
  }
]