Skip to content
This repository was archived by the owner on Apr 18, 2026. It is now read-only.

SECURITY.md - #753

Open
Apidwalin wants to merge 4 commits into
google:masterfrom
Apidwalin:master
Open

SECURITY.md#753
Apidwalin wants to merge 4 commits into
google:masterfrom
Apidwalin:master

Conversation

@Apidwalin

@Apidwalin Apidwalin commented Jul 23, 2021

Copy link
Copy Markdown

From c4ca027 Mon Sep 17 00:00:00 2001
From: apidwalin 84679338+Apidwalin@users.noreply.github.com
Date: Fri, 23 Jul 2021 09:16:58 +0700
Subject: [PATCH 1/4] Create codeql-analysis.yml


.github/workflows/codeql-analysis.yml | 71 +++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 .github/workflows/codeql-analysis.yml

diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000..09200e8
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,71 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the language matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL"
+
+on:

  • push:
  • branches: [ master ]
  • pull_request:
  • The branches below must be a subset of the branches above

  • branches: [ master ]
  • schedule:
    • cron: '22 8 * * 0'

+jobs:

  • analyze:
  • name: Analyze
  • runs-on: ubuntu-latest
  • permissions:
  •  actions: read
    
  •  contents: read
    
  •  security-events: write
    
  • strategy:
  •  fail-fast: false
    
  •  matrix:
    
  •    language: [ 'javascript' ]
    
  •    # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
    
  •    # Learn more:
    
  •    # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
    
  • steps:
    • name: Checkout repository
  •  uses: actions/checkout@v2
    
  • Initializes the CodeQL tools for scanning.

    • name: Initialize CodeQL
  •  uses: github/codeql-action/init@v1
    
  •  with:
    
  •    languages: ${{ matrix.language }}
    
  •    # If you wish to specify custom queries, you can do so here or in a config file.
    
  •    # By default, queries listed here will override any specified in a config file.
    
  •    # Prefix the list here with "+" to use these queries and those in the config file.
    
  •    # queries: ./path/to/local/query, your-org/your-repo/queries@main
    
  • Autobuild attempts to build any compiled languages (C/C++, C#, or Java).

  • If this step fails, then you should remove it and run the build manually (see below)

    • name: Autobuild
  •  uses: github/codeql-action/autobuild@v1
    
  • ℹ️ Command-line programs to run using the OS shell.

  • 📚 https://git.io/JvXDl

  • ✏️ If the Autobuild fails above, remove it and uncomment the following three lines

  • and modify them (or add more) to build your code if your project

  • uses a compiled language

  • #- run: |
  • make bootstrap

  • make release

    • name: Perform CodeQL Analysis
  •  uses: github/codeql-action/analyze@v1
    

From 83a461c Mon Sep 17 00:00:00 2001
From: apidwalin 84679338+Apidwalin@users.noreply.github.com
Date: Fri, 23 Jul 2021 09:19:40 +0700
Subject: [PATCH 2/4] SECURITY.md

Security Policy

Supported Versions

Use this section to tell people about which versions of your project are
currently being supported with security updates.

Version Supported
5.1.x
5.0.x
4.0.x
< 4.0 ��

Reporting a Vulnerability

Use this section to tell people how to report a vulnerability.

Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.

SECURITY.md | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 SECURITY.md

diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..034e848
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,21 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version | Supported |
+| ------- | ------------------ |
+| 5.1.x | ✅ |
+| 5.0.x | ❌ |
+| 4.0.x | ✅ |
+| < 4.0 | ❌ |
+
+## Reporting a Vulnerability
+
+Use this section to tell people how to report a vulnerability.
+
+Tell them where to go, how often they can expect to get an update on a
+reported vulnerability, what to expect if the vulnerability is accepted or
+declined, etc.

From b52b6dc Mon Sep 17 00:00:00 2001
From: apidwalin 84679338+Apidwalin@users.noreply.github.com
Date: Fri, 23 Jul 2021 11:13:28 +0700
Subject: [PATCH 3/4] Create blank.yml


.github/workflows/blank.yml | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 .github/workflows/blank.yml

diff --git a/.github/workflows/blank.yml b/.github/workflows/blank.yml
new file mode 100644
index 0000000..f937a06
--- /dev/null
+++ b/.github/workflows/blank.yml
@@ -0,0 +1,36 @@
+# This is a basic workflow to help you get started with Actions
+
+name: CI
+
+# Controls when the workflow will run
+on:

  • Triggers the workflow on push or pull request events but only for the master branch

  • push:
  • branches: [ master ]
  • pull_request:
  • branches: [ master ]
  • Allows you to run this workflow manually from the Actions tab

  • workflow_dispatch:

+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:

  • This workflow contains a single job called "build"

  • build:
  • The type of runner that the job will run on

  • runs-on: ubuntu-latest
  • Steps represent a sequence of tasks that will be executed as part of the job

  • steps:
  •  # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    
  •  - uses: actions/checkout@v2
    
  •  # Runs a single command using the runners shell
    
  •  - name: Run a one-line script
    
  •    run: echo Hello, world!
    
  •  # Runs a set of commands using the runners shell
    
  •  - name: Run a multi-line script
    
  •    run: |
    
  •      echo Add other actions to build,
    
  •      echo test, and deploy your project.
    

From 2130ca7 Mon Sep 17 00:00:00 2001
From: apidwalin 84679338+Apidwalin@users.noreply.github.com
Date: Fri, 23 Jul 2021 11:17:57 +0700
Subject: [PATCH 4/4] Add files via upload


.DS_Store | Bin 0 -> 6148 bytes
app_authKey.py | 177 +++
key_api.txt | 3 +
models.py | 3107 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 3287 insertions(+)
create mode 100644 .DS_Store
create mode 100644 app_authKey.py
create mode 100644 key_api.txt
create mode 100644 models.py

diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..a8976cb5df6626a8825a8a2092e19def77bbb6de
GIT binary patch
literal 6148
zcmeHKI|>3p3{6x-u(7n9D|mxJ^aNhOA7~civ3oe%cJ@7L6Fr(u#p!?-b^NMmVL!$
zBO
GzZYLrm5gEV@<z}I6c5dFXPG%Gc#pjQY%iO``glCFs^2G!+n1f3WhJLC0sCJ zmI_b-DnJFO02TP8fc0M3U>L|q1*iZOcq(AuhXOaOiA|t?IuLvW0QQh}!f#FV6g<S
zCN_b{z%;19plXg78g%4K*44x&FzBK=d}uydb3##nI_@uCE?NT_sQ?vtRiGQ&k@f#M
z{KNeJO5%<RP=UWvKzp;rY>HRP-r9OO>$L^Ggj>xWZicl}5WF1&y&Yp??Re}(QCDn@
X^P1QMIvshZ1Nk#xy3nY=uN8Oz`K%R

literal 0
HcmV?d00001

diff --git a/app_authKey.py b/app_authKey.py
new file mode 100644
index 0000000..3d415c1
--- /dev/null
+++ b/app_authKey.py
@@ -0,0 +1,177 @@
+from flask import Flask, request, render_template, jsonify
+from io import BytesIO
+from captchaModel.model import load_model, inference
+# from waitress import serve
+import numpy as np
+import base64
+from PIL import Image
+from waitress import serve
+from paste.translogger import TransLogger
+import time
+import math
+
+sess, dectection_graph = load_model()
+app = Flask(name)
+
+# app.config['SECRET_KEY'] = 'secret key here'
+# app.config['HOST'] = '0.0.0.0'
+# app.config['DEBUG'] = True
+# app.config["CACHE_TYPE"] = "null"
+
+# change to "redis" and restart to cache again
+
+# some time later
+# cache.init_app(app)
+
+
+# @app.route('/')
+# def home():
+# return "Hello World"
+
+# def shutdown_server():
+# func = request.environ.get('werkzeug.server.shutdown')
+# if func is None:
+# raise RuntimeError('Not running with the Werkzeug Server')
+# func()
+
+# @app.route('/shutdown', methods=['POST'])
+# def shutdown():
+# shutdown_server()
+# return 'Server shutting down...'
+
+
+@app.route('/api/predict/', methods=['GET', 'POST','DELETE', 'PATCH'])
+def api_predict():

  • print(request.is_json)

  • image_base64 = request.form['image']

  • image = base64.b64decode(image_base64)

  • image = Image.open(BytesIO(image))

  • if image.mode != "RGB":

  • image.convert("RGB")

  • image_arr = np.array(image, dtype=np.uint8)

  • # print(image_arr)

  • start_date = time.time()

  • res = inference(sess, dectection_graph, image_arr)

  • end_date = time.time()

  • result_date = start_date - end_date

  • # print(res)

  • return jsonify(answer=res, status=True, captcha=res, time=format(math.floor(result_date)).replace("-","") + "s")

  • return {

  • "captcha": res,

  • "time": format(math.floor(result_date)).replace("-","") + "s"}

  • return jsonify(answer=res, status=True)

  • apiKeys = []
  • with open('key_api.txt', 'r') as listApiKeys:
  •    apiKeys = [listApiKey.rstrip() for listApiKey in listApiKeys.readlines()]
    
  • print(apiKey)

  • apiKey = 'Pong11299'

  • if request.is_json:
  •    data_json = request.get_json()
    
  •    if data_json['api_key'] in apiKeys:
    
  •        print('found')
    
  •        try:
    
  •            if data_json:
    
  •                image_base64 = data_json['image']
    
  •                image = base64.b64decode(image_base64)
    
  •                image = Image.open(BytesIO(image))
    
  •                if image.mode != "RGB":
    
  •                    image.convert("RGB")
    
  •                image_arr = np.array(image, dtype=np.uint8)
    
  •                # print(image_arr)
    
  •                res = inference(sess, dectection_graph, image_arr)
    
  •                return jsonify(answer=res, status=True)
    
  •        except Exception as e:
    
  •            return jsonify(answer="", status=False)
    
  •    else:
    
  •        return jsonify(answer="NoApiKey", status=False, text='Please Enter API KEY') 
    
  • else:
  •    image_base64 = request.form['image']
    
  •    image = base64.b64decode(image_base64)
    
  •    image = Image.open(BytesIO(image))
    
  •    if image.mode != "RGB":
    
  •        image.convert("RGB")
    
  •    image_arr = np.array(image, dtype=np.uint8)
    
  •    # print(image_arr)
    
  •    start_date = time.time()
    
  •    res = inference(sess, dectection_graph, image_arr)
    
  •    end_date = time.time()
    
  •    result_date = start_date - end_date
    
  •    # print(res)
    
  •    return {
    
  •                "captcha": res, 
    
  •                "time": format(math.floor(result_date)).replace("-","") + "s"}
    
  •        # base64 = request.form['base64']
    
  •        # start_date = time.time()
    
  •        # captcha = Captcha_detection(base64)
    
  •        # end_date = time.time()
    
  •        # result_date = start_date - end_date
    
  •        # return {
    
  •        #     "captcha": captcha, 
    
  •        #     "time": format(math.floor(result_date)).replace("-","") + "s"
    

+@app.route('/' , methods=['GET', 'POST','DELETE', 'PATCH'])
+def home():

  • base64few = str(request.form['base64'])
  • image = base64.b64decode(base64few)
  • image = Image.open(BytesIO(image))
  • if image.mode != "RGB":
  •    image.convert("RGB")
    
  • image_arr = np.array(image, dtype=np.uint8)
  • start_date = time.time()
  • #captcha = Captcha_detection(base64)
  • res = inference(sess, dectection_graph, image_arr)
  • end_date = time.time()
  • result_date = start_date - end_date
  • #print('I have money {:,.2f} baht'.format(result_date))
  • return {
  •    "captcha": res, 
    
  •    "time": '{:,.2f}s'.format(result_date).replace("-","")
    
  • }

+@app.route('/api/images/', methods=['POST'])
+def api_images():

  • if request.is_json:
  •    try:
    
  •        data_json = request.get_json()
    
  •        if data_json:
    
  •            image_base64 = data_json['image']
    
  •            image = base64.b64decode(image_base64)
    
  •            image = Image.open(BytesIO(image))
    
  •            if image.mode != "RGB":
    
  •                image.convert("RGB")
    
  •            image_arr = np.array(image, dtype=np.uint8)
    
  •            # print(image_arr)
    
  •            res = inference(sess, dectection_graph, image_arr)
    
  •            return jsonify(answer=res, status=True)
    
  •    except Exception as e:
    
  •        return jsonify(answer="", status=False)
    
  • return jsonify(answer="", status=False)

+@app.route('/api/imgArr/', methods=['POST'])
+def api_imgArr():

  • print(request.get_json())

+if name == "main":

  • app.run(debug=True)

  • app.debug = False
  • app.config["CACHE_TYPE"] = "null"

  • app.run(host = '0.0.0.0',port=8080)
  • serve(TransLogger(app, setup_console_handler=False), threads=20, host = '0.0.0.0',port=5000)

  • serve(TransLogger(app, setup_console_handler=False), threads=40, host = '0.0.0.0',port=5000)

diff --git a/key_api.txt b/key_api.txt
new file mode 100644
index 0000000..227d6a4
--- /dev/null
+++ b/key_api.txt
@@ -0,0 +1,3 @@
+Pong11299
+Apidwalin
+bas2563
diff --git a/models.py b/models.py
new file mode 100644
index 0000000..20da8b9
--- /dev/null
+++ b/models.py
@@ -0,0 +1,3107 @@
+_instance = None
+
+ast_transformers = List([], help=

  • """
  • A list of ast.NodeTransformer subclass instances, which will be applied
  • to user input before code is run.
  • """
    +).tag(config=True)

+autocall = Enum((0,1,2), default_value=0, help=

  • """
  • Make IPython automatically call any callable object even if you didn't
  • type explicit parentheses. For example, 'str 43' becomes 'str(43)'
  • automatically. The value can be '0' to disable the feature, '1' for
  • 'smart' autocall, where it is not applied if there are no more
  • arguments on the line, and '2' for 'full' autocall, where all callable
  • objects are automatically called (even if no arguments are present).
  • """
    +).tag(config=True)
    +# TODO: remove all autoindent logic and put into frontends.
    +# We can't do this yet because even runlines uses the autoindent.
    +autoindent = Bool(True, help=
  • """
  • Autoindent IPython code entered interactively.
  • """
    +).tag(config=True)

+automagic = Bool(True, help=

  • """
  • Enable magic commands to be called without the leading %.
  • """
    +).tag(config=True)

+banner1 = Unicode(default_banner,

  • help="""The part of the banner to be printed before the profile"""
    +).tag(config=True)
    +banner2 = Unicode('',
  • help="""The part of the banner to be printed after the profile"""
    +).tag(config=True)

+cache_size = Integer(1000, help=

  • """
  • Set the size of the output cache. The default is 1000, you can
  • change it permanently in your config file. Setting it to 0 completely
  • disables the caching system, and the minimum value accepted is 3 (if
  • you provide a value less than 3, it is reset to 0 and a warning is
  • issued). This limit is defined because otherwise you'll spend more
  • time re-flushing a too small cache than working
  • """
    +).tag(config=True)
    +color_info = Bool(True, help=
  • """
  • Use colors for displaying information about objects. Because this
  • information is passed through a pager (like 'less'), and some pagers
  • get confused with color codes, this capability can be turned off.
  • """
    +).tag(config=True)
    +colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
  •                     default_value='Neutral',
    
  • help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
    +).tag(config=True)
    +debug = Bool(False).tag(config=True)
    +disable_failing_post_execute = Bool(False,
  • help="Don't call post-execute functions that have failed in the past."
    +).tag(config=True)
    +display_formatter = Instance(DisplayFormatter, allow_none=True)
    +displayhook_class = Type(DisplayHook)
    +display_pub_class = Type(DisplayPublisher)

+sphinxify_docstring = Bool(False, help=

  • """
  • Enables rich html representation of docstrings. (This requires the
  • docrepr module).
  • """).tag(config=True)

+@observe("sphinxify_docstring")
+def _sphinxify_docstring_changed(self, change):

  • if change['new']:
  •    warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
    

+enable_html_pager = Bool(False, help=

  • """
  • (Provisional API) enables html representation in mime bundles sent
  • to pagers.
  • """).tag(config=True)

+@observe("enable_html_pager")
+def _enable_html_pager_changed(self, change):

  • if change['new']:
  •    warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
    

+data_pub_class = None
+
+exit_now = Bool(False)
+exiter = Instance(ExitAutocall)
+@default('exiter')
+def _exiter_default(self):

  • return ExitAutocall(self)
    +# Monotonically increasing execution counter
    +execution_count = Integer(1)
    +filename = Unicode("")
    +ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in init

+# Input splitter, to transform input line by line and detect when a block
+# is ready to be executed.
+input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',

  •                      (), {'line_input_checker': True})
    

+# This InputSplitter instance is used to transform completed cells before
+# running them. It allows cell magics to contain blank lines.
+input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',

  •                                 (), {'line_input_checker': False})
    

+logstart = Bool(False, help=

  • """
  • Start logging to the default log file in overwrite mode.
  • Use logappend to specify a log file to append logs to.
  • """
    +).tag(config=True)
    +logfile = Unicode('', help=
  • """
  • The name of the logfile to use.
  • """
    +).tag(config=True)
    +logappend = Unicode('', help=
  • """
  • Start logging to the given file in append mode.
  • Use logfile to specify a log file to overwrite logs to.
  • """
    +).tag(config=True)
    +object_info_string_level = Enum((0,1,2), default_value=0,
    +).tag(config=True)
    +pdb = Bool(False, help=
  • """
  • Automatically call the pdb debugger after every exception.
  • """
    +).tag(config=True)
    +display_page = Bool(False,
  • help="""If True, anything that would be passed to the pager
  • will be displayed as regular output instead."""
    +).tag(config=True)

+# deprecated prompt traits:
+
+prompt_in1 = Unicode('In [\#]: ',

  • help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
    +).tag(config=True)
    +prompt_in2 = Unicode(' .\D.: ',
  • help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
    +).tag(config=True)
    +prompt_out = Unicode('Out[\#]: ',
  • help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
    +).tag(config=True)
    +prompts_pad_left = Bool(True,
  • help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
    +).tag(config=True)

+@observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left')
+def _prompt_trait_changed(self, change):

  • name = change['name']
  • warn("InteractiveShell.{name} is deprecated since IPython 4.0"
  •     " and ignored since 5.0, set TerminalInteractiveShell.prompts"
    
  •     " object directly.".format(name=name))
    
  • protect against weird cases where self.config may not exist:

+show_rewritten_input = Bool(True,

  • help="Show rewritten input, e.g. for autocall."
    +).tag(config=True)

+quiet = Bool(False).tag(config=True)
+
+history_length = Integer(10000,

  • help='Total length of command history'
    +).tag(config=True)

+history_load_length = Integer(1000, help=

  • """
  • The number of saved history entries to be loaded
  • into the history buffer at startup.
  • """
    +).tag(config=True)

+ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],

  •                          default_value='last_expr',
    
  •                          help="""
    
  • 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
  • which nodes should be run interactively (displaying output from expressions).
  • """
    +).tag(config=True)

+# TODO: this part of prompt management should be moved to the frontends.
+# Use custom TraitTypes that convert '0'->'' and '\n'->'\n'
+separate_in = SeparateUnicode('\n').tag(config=True)
+separate_out = SeparateUnicode('').tag(config=True)
+separate_out2 = SeparateUnicode('').tag(config=True)
+wildcards_case_sensitive = Bool(True).tag(config=True)
+xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),

  •                    default_value='Context',
    
  •                    help="Switch modes for the IPython exception handlers."
    
  •                    ).tag(config=True)
    

+# Subcomponents of InteractiveShell
+alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
+prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
+builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
+display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
+extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
+payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
+history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
+magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
+
+profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
+@Property
+def profile(self):

  • if self.profile_dir is not None:
  •    name = os.path.basename(self.profile_dir.location)
    
  •    return name.replace('profile_','')
    

+# Private interface
+_post_execute = Dict()
+
+# Tracks any GUI loop loaded for pylab
+pylab_gui_select = None
+
+last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
+
+last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
+
+def init(self, ipython_dir=None, profile_dir=None,

  •         user_module=None, user_ns=None,
    
  •         custom_exceptions=((), None), **kwargs):
    
  • This is where traits with a config_key argument are updated

  • from the values on config.

  • super(InteractiveShell, self).init(**kwargs)
  • if 'PromptManager' in self.config:
  •    warn('As of IPython 5.0 `PromptManager` config will have no effect'
    
  •         ' and has been replaced by TerminalInteractiveShell.prompts_class')
    
  • self.configurables = [self]
  • These are relatively independent and stateless

  • self.init_ipython_dir(ipython_dir)
  • self.init_profile_dir(profile_dir)
  • self.init_instance_attrs()
  • self.init_environment()
  • Check if we're in a virtualenv, and set up sys.path.

  • self.init_virtualenv()
  • Create namespaces (user_ns, user_global_ns, etc.)

  • self.init_create_namespaces(user_module, user_ns)
  • This has to be done after init_create_namespaces because it uses

  • something in self.user_ns, but before init_sys_modules, which

  • is the first thing to modify sys.

  • TODO: When we override sys.stdout and sys.stderr before this class

  • is created, we are saving the overridden ones here. Not sure if this

  • is what we want to do.

  • self.save_sys_module_state()
  • self.init_sys_modules()
  • While we're trying to have each part of the code directly access what

  • it needs without keeping redundant references to objects, we have too

  • much legacy code that expects ip.db to exist.

  • self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
  • self.init_history()
  • self.init_encoding()
  • self.init_prefilter()
  • self.init_syntax_highlighting()
  • self.init_hooks()
  • self.init_events()
  • self.init_pushd_popd_magic()
  • self.init_user_ns()
  • self.init_logger()
  • self.init_builtins()
  • The following was in post_config_initialization

  • self.init_inspector()
  • self.raw_input_original = input
  • self.init_completer()
  • TODO: init_io() needs to happen before init_traceback handlers

  • because the traceback handlers hardcode the stdout/stderr streams.

  • This logic in in debugger.Pdb and should eventually be changed.

  • self.init_io()
  • self.init_traceback_handlers(custom_exceptions)
  • self.init_prompts()
  • self.init_display_formatter()
  • self.init_display_pub()
  • self.init_data_pub()
  • self.init_displayhook()
  • self.init_magics()
  • self.init_alias()
  • self.init_logstart()
  • self.init_pdb()
  • self.init_extension_manager()
  • self.init_payload()
  • self.init_deprecation_warnings()
  • self.hooks.late_startup_hook()
  • self.events.trigger('shell_initialized', self)
  • atexit.register(self.atexit_operations)

+def get_ipython(self):

  • """Return the currently running IPython instance."""
  • return self

+#-------------------------------------------------------------------------
+# Trait changed handlers
+#-------------------------------------------------------------------------
+@observe('ipython_dir')
+def _ipython_dir_changed(self, change):

  • ensure_dir_exists(change['new'])

+def set_autoindent(self,value=None):

  • """Set the autoindent flag.
  • If called with no arguments, it acts as a toggle."""
  • if value is None:
  •    self.autoindent = not self.autoindent
    
  • else:
  •    self.autoindent = value
    

+#-------------------------------------------------------------------------
+# init_* methods called by init
+#-------------------------------------------------------------------------
+
+def init_ipython_dir(self, ipython_dir):

  • if ipython_dir is not None:
  •    self.ipython_dir = ipython_dir
    
  •    return
    
  • self.ipython_dir = get_ipython_dir()

+def init_profile_dir(self, profile_dir):

  • if profile_dir is not None:
  •    self.profile_dir = profile_dir
    
  •    return
    
  • self.profile_dir =\
  •    ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
    

+def init_instance_attrs(self):

  • self.more = False
  • command compiler

  • self.compile = CachingCompiler()
  • Make an empty namespace, which extension writers can rely on both

  • existing and NEVER being used by ipython itself. This gives them a

  • convenient location for storing additional information and state

  • their extensions may require, without fear of collisions with other

  • ipython names that may develop later.

  • self.meta = Struct()
  • Temporary files used for various purposes. Deleted at exit.

  • self.tempfiles = []
  • self.tempdirs = []
  • keep track of where we started running (mainly for crash post-mortem)

  • This is not being used anywhere currently.

  • self.starting_dir = os.getcwd()
  • Indentation management

  • self.indent_current_nsp = 0
  • Dict to track post-execution functions that have been registered

  • self._post_execute = {}

+def init_environment(self):

  • """Any changes we need to make to the user's environment."""
  • pass

+def init_encoding(self):

  • Get system encoding at startup time. Certain terminals (like Emacs

  • under Win32 have it set to None, and we need to have a known valid

  • encoding to use in the raw_input() method

  • try:
  •    self.stdin_encoding = sys.stdin.encoding or 'ascii'
    
  • except AttributeError:
  •    self.stdin_encoding = 'ascii'
    

+@observe('colors')
+def init_syntax_highlighting(self, changes=None):

  • Python source parser/formatter for syntax highlighting

  • pyformat = PyColorize.Parser(style=self.colors, parent=self).format
  • self.pycolorize = lambda src: pyformat(src,'str')

+def refresh_style(self):

  • No-op here, used in subclass

  • pass

+def init_pushd_popd_magic(self):

  • for pushd/popd management

  • self.home_dir = get_home_dir()
  • self.dir_stack = []

+def init_logger(self):

  • self.logger = Logger(self.home_dir, logfname='ipython_log.py',
  •                     logmode='rotate')
    

+def init_logstart(self):

  • """Initialize logging in case it was requested at the command line.
  • """
  • if self.logappend:
  •    self.magic('logstart %s append' % self.logappend)
    
  • elif self.logfile:
  •    self.magic('logstart %s' % self.logfile)
    
  • elif self.logstart:
  •    self.magic('logstart')
    

+def init_deprecation_warnings(self):

  • """
  • register default filter for deprecation warning.
  • This will allow deprecation warning of function used interactively to show
  • warning to users, and still hide deprecation warning from libraries import.
  • """
  • warnings.filterwarnings("default", category=DeprecationWarning, module=self.user_ns.get("name"))

+def init_builtins(self):

  • A single, static flag that we set to True. Its presence indicates

  • that an IPython shell has been created, and we make no attempts at

  • removing on exit or representing the existence of more than one

  • IPython at a time.

  • builtin_mod.dict['IPYTHON'] = True
  • builtin_mod.dict['display'] = display
  • self.builtin_trap = BuiltinTrap(shell=self)

+@observe('colors')
+def init_inspector(self, changes=None):

  • Object inspector

  • self.inspector = oinspect.Inspector(oinspect.InspectColors,
  •                                    PyColorize.ANSICodeColors,
    
  •                                    self.colors,
    
  •                                    self.object_info_string_level)
    

+def init_io(self):

  • This will just use sys.stdout and sys.stderr. If you want to

  • override sys.stdout and sys.stderr themselves, you need to do that

  • before instantiating this class, because io holds onto

  • references to the underlying streams.

  • io.std* are deprecated, but don't show our own deprecation warnings

  • during initialization of the deprecated API.

  • with warnings.catch_warnings():
  •    warnings.simplefilter('ignore', DeprecationWarning)
    
  •    io.stdout = io.IOStream(sys.stdout)
    
  •    io.stderr = io.IOStream(sys.stderr)
    

+def init_prompts(self):

  • Set system prompts, so that scripts can decide if they are running

  • interactively.

  • sys.ps1 = 'In : '
  • sys.ps2 = '...: '
  • sys.ps3 = 'Out: '

+def init_display_formatter(self):

  • self.display_formatter = DisplayFormatter(parent=self)
  • self.configurables.append(self.display_formatter)

+def init_display_pub(self):

  • self.display_pub = self.display_pub_class(parent=self)
  • self.configurables.append(self.display_pub)

+def init_data_pub(self):

  • if not self.data_pub_class:
  •    self.data_pub = None
    
  •    return
    
  • self.data_pub = self.data_pub_class(parent=self)
  • self.configurables.append(self.data_pub)

+def init_displayhook(self):

  • Initialize displayhook, set in/out prompts and printing system

  • self.displayhook = self.displayhook_class(
  •    parent=self,
    
  •    shell=self,
    
  •    cache_size=self.cache_size,
    
  • )
  • self.configurables.append(self.displayhook)
  • This is a context manager that installs/revmoes the displayhook at

  • the appropriate time.

  • self.display_trap = DisplayTrap(hook=self.displayhook)

+def init_virtualenv(self):

  • """Add a virtualenv to sys.path so the user can import modules from it.
  • This isn't perfect: it doesn't use the Python interpreter with which the
  • virtualenv was built, and it ignores the --no-site-packages option. A
  • warning will appear suggesting the user installs IPython in the
  • virtualenv, but for many cases, it probably works well enough.
  • Adapted from code snippets online.
  • http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
  • """
  • if 'VIRTUAL_ENV' not in os.environ:
  •    # Not in a virtualenv
    
  •    return
    
  • p = os.path.normcase(sys.executable)
  • p_venv = os.path.normcase(os.environ['VIRTUAL_ENV'])
  • executable path should end like /bin/python or \scripts\python.exe

  • p_exe_up2 = os.path.dirname(os.path.dirname(p))
  • if p_exe_up2 and os.path.samefile(p_exe_up2, p_venv):
  •    # Our exe is inside the virtualenv, don't need to do anything.
    
  •    return
    
  • fallback venv detection:

  • stdlib venv may symlink sys.executable, so we can't use realpath.

  • but others can symlink to the venv Python, so we can't just use sys.executable.

  • So we just check every item in the symlink tree (generally <= 3)

  • paths = [p]
  • while os.path.islink(p):
  •    p = os.path.normcase(os.path.join(os.path.dirname(p), os.readlink(p)))
    
  •    paths.append(p)
    
  • In Cygwin paths like "c:..." and '\cygdrive\c...' are possible

  • if p_venv.startswith('\cygdrive'):
  •    p_venv = p_venv[11:]
    
  • elif len(p_venv) >= 2 and p_venv[1] == ':':
  •    p_venv = p_venv[2:]
    
  • if any(p_venv in p for p in paths):
  •    # Running properly in the virtualenv, don't need to do anything
    
  •    return
    
  • warn("Attempting to work in a virtualenv. If you encounter problems, please "
  •     "install IPython inside the virtualenv.")
    
  • if sys.platform == "win32":
  •    virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages') 
    
  • else:
  •    virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
    
  •               'python%d.%d' % sys.version_info[:2], 'site-packages')
    
  • import site
  • sys.path.insert(0, virtual_env)
  • site.addsitedir(virtual_env)

+#-------------------------------------------------------------------------
+# Things related to injections into the sys module
+#-------------------------------------------------------------------------
+
+def save_sys_module_state(self):

  • """Save the state of hooks in the sys module.
  • This has to be called after self.user_module is created.
  • """
  • self._orig_sys_module_state = {'stdin': sys.stdin,
  •                               'stdout': sys.stdout,
    
  •                               'stderr': sys.stderr,
    
  •                               'excepthook': sys.excepthook}
    
  • self._orig_sys_modules_main_name = self.user_module.name
  • self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.name)

+def restore_sys_module_state(self):

  • """Restore the state of the sys module."""
  • try:
  •    for k, v in self._orig_sys_module_state.items():
    
  •        setattr(sys, k, v)
    
  • except AttributeError:
  •    pass
    
  • Reset what what done in self.init_sys_modules

  • if self._orig_sys_modules_main_mod is not None:
  •    sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
    

+#-------------------------------------------------------------------------
+# Things related to the banner
+#-------------------------------------------------------------------------
+
+@Property
+def banner(self):

  • banner = self.banner1
  • if self.profile and self.profile != 'default':
  •    banner += '\nIPython profile: %s\n' % self.profile
    
  • if self.banner2:
  •    banner += '\n' + self.banner2
    
  • return banner

+def show_banner(self, banner=None):

  • if banner is None:
  •    banner = self.banner
    
  • sys.stdout.write(banner)

+#-------------------------------------------------------------------------
+# Things related to hooks
+#-------------------------------------------------------------------------
+
+def init_hooks(self):

  • hooks holds pointers used for user-side customizations

  • self.hooks = Struct()
  • self.strdispatchers = {}
  • Set all default hooks, defined in the IPython.hooks module.

  • hooks = IPython.core.hooks
  • for hook_name in hooks.all:
  •    # default hooks have priority 100, i.e. low; user hooks should have
    
  •    # 0-100 priority
    
  •    self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
    
  • if self.display_page:
  •    self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
    

+def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,

  •         _warn_deprecated=True):
    
  • """set_hook(name,hook) -> sets an internal IPython hook.
  • IPython exposes some of its internal API as user-modifiable hooks. By
  • adding your function to one of these hooks, you can modify IPython's
  • behavior to call at runtime your own routines."""
  • At some point in the future, this should validate the hook before it

  • accepts it. Probably at least check that the hook takes the number

  • of args it's supposed to.

  • f = types.MethodType(hook,self)
  • check if the hook is for strdispatcher first

  • if str_key is not None:
  •    sdp = self.strdispatchers.get(name, StrDispatch())
    
  •    sdp.add_s(str_key, f, priority )
    
  •    self.strdispatchers[name] = sdp
    
  •    return
    
  • if re_key is not None:
  •    sdp = self.strdispatchers.get(name, StrDispatch())
    
  •    sdp.add_re(re.compile(re_key), f, priority )
    
  •    self.strdispatchers[name] = sdp
    
  •    return
    
  • dp = getattr(self.hooks, name, None)
  • if name not in IPython.core.hooks.all:
  •    print("Warning! Hook '%s' is not one of %s" % \
    
  •          (name, IPython.core.hooks.__all__ ))
    
  • if _warn_deprecated and (name in IPython.core.hooks.deprecated):
  •    alternative = IPython.core.hooks.deprecated[name]
    
  •    warn("Hook {} is deprecated. Use {} instead.".format(name, alternative), stacklevel=2)
    
  • if not dp:
  •    dp = IPython.core.hooks.CommandChainDispatcher()
    
  • try:
  •    dp.add(f,priority)
    
  • except AttributeError:
  •    # it was not commandchain, plain old func - replace
    
  •    dp = f
    
  • setattr(self.hooks,name, dp)

+#-------------------------------------------------------------------------
+# Things related to events
+#-------------------------------------------------------------------------
+
+def init_events(self):

  • self.events = EventManager(self, available_events)
  • self.events.register("pre_execute", self._clear_warning_registry)

+def register_post_execute(self, func):

  • """DEPRECATED: Use ip.events.register('post_run_cell', func)
  • Register a function for calling after code execution.
  • """
  • warn("ip.register_post_execute is deprecated, use "
  •     "ip.events.register('post_run_cell', func) instead.", stacklevel=2)
    
  • self.events.register('post_run_cell', func)

+def _clear_warning_registry(self):

  • clear the warning registry, so that different code blocks with

  • overlapping line number ranges don't cause spurious suppression of

  • warnings (see gh-6611 for details)

  • if "warningregistry" in self.user_global_ns:
  •    del self.user_global_ns["__warningregistry__"]
    

+#-------------------------------------------------------------------------
+# Things related to the "main" module
+#-------------------------------------------------------------------------
+
+def new_main_mod(self, filename, modname):

  • """Return a new 'main' module object for user code execution.
  • filename should be the path of the script which will be run in the
  • module. Requests with the same filename will get the same module, with
  • its namespace cleared.
  • modname should be the module name - normally either 'main' or
  • the basename of the file without the extension.
  • When scripts are executed via %run, we must keep a reference to their
  • main module around so that Python doesn't
  • clear it, rendering references to module globals useless.
  • This method keeps said reference in a private dict, keyed by the
  • absolute path of the script. This way, for multiple executions of the
  • same script we only keep one copy of the namespace (the last one),
  • thus preventing memory leaks from old references while allowing the
  • objects from the last execution to be accessible.
  • """
  • filename = os.path.abspath(filename)
  • try:
  •    main_mod = self._main_mod_cache[filename]
    
  • except KeyError:
  •    main_mod = self._main_mod_cache[filename] = types.ModuleType(
    
  •                modname,
    
  •                doc="Module created for script run in IPython")
    
  • else:
  •    main_mod.__dict__.clear()
    
  •    main_mod.__name__ = modname
    
  • main_mod.file = filename
  • It seems pydoc (and perhaps others) needs any module instance to

  • implement a nonzero method

  • main_mod.nonzero = lambda : True
  • return main_mod

+def clear_main_mod_cache(self):

  • """Clear the cache of main modules.
  • Mainly for use by utilities like %reset.
  • Examples

  • In [15]: import IPython
  • In [16]: m = _ip.new_main_mod(IPython.file, 'IPython')
  • In [17]: len(_ip._main_mod_cache) > 0
  • Out[17]: True
  • In [18]: _ip.clear_main_mod_cache()
  • In [19]: len(_ip._main_mod_cache) == 0
  • Out[19]: True
  • """
  • self._main_mod_cache.clear()

+#-------------------------------------------------------------------------
+# Things related to debugging
+#-------------------------------------------------------------------------
+
+def init_pdb(self):

  • Set calling of pdb on exceptions

  • self.call_pdb is a property

  • self.call_pdb = self.pdb

+def _get_call_pdb(self):

  • return self._call_pdb

+def _set_call_pdb(self,val):
+

  • if val not in (0,1,False,True):
  •    raise ValueError('new call_pdb value must be boolean')
    
  • store value in instance

  • self._call_pdb = val
  • notify the actual exception handlers

  • self.InteractiveTB.call_pdb = val

+call_pdb = property(_get_call_pdb,_set_call_pdb,None,

  •                'Control auto-activation of pdb at exceptions')
    

+def debugger(self,force=False):

  • """Call the pdb debugger.
  • Keywords:
  •  - force(False): by default, this routine checks the instance call_pdb
    
  •    flag and does not actually invoke the debugger if the flag is false.
    
  •    The 'force' option forces the debugger to activate even if the flag
    
  •    is false.
    
  • """
  • if not (force or self.call_pdb):
  •    return
    
  • if not hasattr(sys,'last_traceback'):
  •    error('No traceback has been produced, nothing to debug.')
    
  •    return
    
  • self.InteractiveTB.debugger(force=True)

+#-------------------------------------------------------------------------
+# Things related to IPython's various namespaces
+#-------------------------------------------------------------------------
+default_user_namespaces = True
+
+def init_create_namespaces(self, user_module=None, user_ns=None):

  • Create the namespace where the user will operate. user_ns is

  • normally the only one used, and it is passed to the exec calls as

  • the locals argument. But we do carry a user_global_ns namespace

  • given as the exec 'globals' argument, This is useful in embedding

  • situations where the ipython shell opens in a context where the

  • distinction between locals and globals is meaningful. For

  • non-embedded contexts, it is just the same object as the user_ns dict.

  • FIXME. For some strange reason, builtins is showing up at user

  • level as a dict instead of a module. This is a manual fix, but I

  • should really track down where the problem is coming from. Alex

  • Schmolck reported this problem first.

  • A useful post by Alex Martelli on this topic:

  • Re: inconsistent value from builtins

  • Von: Alex Martelli aleaxit@yahoo.com

  • Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends

  • Gruppen: comp.lang.python

  • Michael Hohn hohn@hooknose.lbl.gov wrote:

  • > >>> print type(builtin_check.get_global_binding('builtins'))

  • > <type 'dict'>

  • > >>> print type(builtins)

  • > <type 'module'>

  • > Is this difference in return value intentional?

  • Well, it's documented that 'builtins' can be either a dictionary

  • or a module, and it's been that way for a long time. Whether it's

  • intentional (or sensible), I don't know. In any case, the idea is

  • that if you need to access the built-in namespace directly, you

  • should start with "import builtin" (note, no 's') which will

  • definitely give you a module. Yeah, it's somewhat confusing:-(.

  • These routines return a properly built module and dict as needed by

  • the rest of the code, and can also be used by extension writers to

  • generate properly initialized namespaces.

  • if (user_ns is not None) or (user_module is not None):
  •    self.default_user_namespaces = False
    
  • self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
  • A record of hidden variables we have added to the user namespace, so

  • we can list later only variables defined in actual interactive use.

  • self.user_ns_hidden = {}
  • Now that FakeModule produces a real module, we've run into a nasty

  • problem: after script execution (via %run), the module where the user

  • code ran is deleted. Now that this object is a true module (needed

  • so doctest and other tools work correctly), the Python module

  • teardown mechanism runs over it, and sets to None every variable

  • present in that module. Top-level references to objects from the

  • script survive, because the user_ns is updated with them. However,

  • calling functions defined in the script that use other things from

  • the script will fail, because the function's closure had references

  • to the original objects, which are now all None. So we must protect

  • these modules from deletion by keeping a cache.

  • To avoid keeping stale modules around (we only need the one from the

  • last run), we use a dict keyed with the full path to the script, so

  • only the last version of the module is held in the cache. Note,

  • however, that we must cache the module namespace contents (their

  • dict). Because if we try to cache the actual modules, old ones

  • (uncached) could be destroyed while still holding references (such as

  • those held by GUI objects that tend to be long-lived)>

  • The %reset command will flush this cache. See the cache_main_mod()

  • and clear_main_mod_cache() methods for details on use.

  • This is the cache used for 'main' namespaces

  • self._main_mod_cache = {}
  • A table holding all the namespaces IPython deals with, so that

  • introspection facilities can search easily.

  • self.ns_table = {'user_global':self.user_module.dict,
  •                 'user_local':self.user_ns,
    
  •                 'builtin':builtin_mod.__dict__
    
  •                 }
    

+@Property
+def user_global_ns(self):

  • return self.user_module.dict

+def prepare_user_module(self, user_module=None, user_ns=None):

  • """Prepare the module and namespace in which user code will be run.
  • When IPython is started normally, both parameters are None: a new module
  • is created automatically, and its dict used as the namespace.
  • If only user_module is provided, its dict is used as the namespace.
  • If only user_ns is provided, a dummy module is created, and user_ns
  • becomes the global namespace. If both are provided (as they may be
  • when embedding), user_ns is the local namespace, and user_module
  • provides the global namespace.
  • Parameters

  • user_module : module, optional
  •    The current user module in which IPython is being run. If None,
    
  •    a clean module will be created.
    
  • user_ns : dict, optional
  •    A namespace in which to run interactive commands.
    
  • Returns

  • A tuple of user_module and user_ns, each properly initialised.
  • """
  • if user_module is None and user_ns is not None:
  •    user_ns.setdefault("__name__", "__main__")
    
  •    user_module = DummyMod()
    
  •    user_module.__dict__ = user_ns
    
  • if user_module is None:
  •    user_module = types.ModuleType("__main__",
    
  •        doc="Automatically created module for IPython interactive environment")
    
  • We must ensure that builtin (without the final 's') is always

  • available and pointing to the builtin module. For more details:

  • http://mail.python.org/pipermail/python-dev/2001-April/014068.html

  • user_module.dict.setdefault('builtin', builtin_mod)
  • user_module.dict.setdefault('builtins', builtin_mod)
  • if user_ns is None:
  •    user_ns = user_module.__dict__
    
  • return user_module, user_ns

+def init_sys_modules(self):

  • We need to insert into sys.modules something that looks like a

  • module but which accesses the IPython namespace, for shelve and

  • pickle to work interactively. Normally they rely on getting

  • everything out of main, but for embedding purposes each IPython

  • instance has its own private namespace, so we can't go shoving

  • everything into main.

  • note, however, that we should only do this for non-embedded

  • ipythons, which really mimic the main.dict with their own

  • namespace. Embedded instances, on the other hand, should not do

  • this because they need to manage the user local/global namespaces

  • only, but they live within a 'normal' main (meaning, they

  • shouldn't overtake the execution environment of the script they're

  • embedded in).

  • This is overridden in the InteractiveShellEmbed subclass to a no-op.

  • main_name = self.user_module.name
  • sys.modules[main_name] = self.user_module

+def init_user_ns(self):

  • """Initialize all user-visible namespaces to their minimum defaults.
  • Certain history lists are also initialized here, as they effectively
  • act as user namespaces.
  • Notes

  • All data structures here are only filled in, they are NOT reset by this
  • method. If they were not empty before, data will simply be added to
  • them.
  • """
  • This function works in two parts: first we put a few things in

  • user_ns, and we sync that contents into user_ns_hidden so that these

  • initial variables aren't shown by %who. After the sync, we add the

  • rest of what we do want the user to see with %who even on a new

  • session (probably nothing, so they really only see their own stuff)

  • The user dict must always have a builtin reference to the

  • Python standard builtin namespace, which must be imported.

  • This is so that certain operations in prompt evaluation can be

  • reliably executed with builtins. Note that we can NOT use

  • builtins (note the 's'), because that can either be a dict or a

  • module, and can even mutate at runtime, depending on the context

  • (Python makes no guarantees on it). In contrast, builtin is

  • always a module object, though it must be explicitly imported.

  • For more details:

  • http://mail.python.org/pipermail/python-dev/2001-April/014068.html

  • ns = {}
  • make global variables for user access to the histories

  • ns['_ih'] = self.history_manager.input_hist_parsed
  • ns['_oh'] = self.history_manager.output_hist
  • ns['_dh'] = self.history_manager.dir_hist
  • user aliases to input and output histories. These shouldn't show up

  • in %who, as they can have very large reprs.

  • ns['In'] = self.history_manager.input_hist_parsed
  • ns['Out'] = self.history_manager.output_hist
  • Store myself as the public api!!!

  • ns['get_ipython'] = self.get_ipython
  • ns['exit'] = self.exiter
  • ns['quit'] = self.exiter
  • Sync what we've added so far to user_ns_hidden so these aren't seen

  • by %who

  • self.user_ns_hidden.update(ns)
  • Anything put into ns now would show up in %who. Think twice before

  • putting anything here, as we really want %who to show the user their

  • stuff, not our variables.

  • Finally, update the real user's namespace

  • self.user_ns.update(ns)

+@Property
+def all_ns_refs(self):

  • """Get a list of references to all the namespace dictionaries in which
  • IPython might store a user-created object.
  • Note that this does not include the displayhook, which also caches
  • objects from the output."""
  • return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
  •       [m.__dict__ for m in self._main_mod_cache.values()]
    

+def reset(self, new_session=True):

  • """Clear all internal namespaces, and attempt to release references to
  • user objects.
  • If new_session is True, a new history session will be opened.
  • """
  • Clear histories

  • self.history_manager.reset(new_session)
  • Reset counter used to index all histories

  • if new_session:
  •    self.execution_count = 1
    
  • Reset last execution result

  • self.last_execution_succeeded = True
  • self.last_execution_result = None
  • Flush cached output items

  • if self.displayhook.do_full_cache:
  •    self.displayhook.flush()
    
  • The main execution namespaces must be cleared very carefully,

  • skipping the deletion of the builtin-related keys, because doing so

  • would cause errors in many object's del methods.

  • if self.user_ns is not self.user_global_ns:
  •    self.user_ns.clear()
    
  • ns = self.user_global_ns
  • drop_keys = set(ns.keys())
  • drop_keys.discard('builtin')
  • drop_keys.discard('builtins')
  • drop_keys.discard('name')
  • for k in drop_keys:
  •    del ns[k]
    
  • self.user_ns_hidden.clear()
  • Restore the user namespaces to minimal usability

  • self.init_user_ns()
  • Restore the default and user aliases

  • self.alias_manager.clear_aliases()
  • self.alias_manager.init_aliases()
  • Flush the private list of module references kept for script

  • execution protection

  • self.clear_main_mod_cache()

+def del_var(self, varname, by_name=False):

  • """Delete a variable from the various namespaces, so that, as
  • far as possible, we're not keeping any hidden references to it.
  • Parameters

  • varname : str
  •    The name of the variable to delete.
    
  • by_name : bool
  •    If True, delete variables with the given name in each
    
  •    namespace. If False (default), find the variable in the user
    
  •    namespace, and delete references to it.
    
  • """
  • if varname in ('builtin', 'builtins'):
  •    raise ValueError("Refusing to delete %s" % varname)
    
  • ns_refs = self.all_ns_refs
  • if by_name: # Delete by name
  •    for ns in ns_refs:
    
  •        try:
    
  •            del ns[varname]
    
  •        except KeyError:
    
  •            pass
    
  • else: # Delete by object
  •    try:
    
  •        obj = self.user_ns[varname]
    
  •    except KeyError:
    
  •        raise NameError("name '%s' is not defined" % varname)
    
  •    # Also check in output history
    
  •    ns_refs.append(self.history_manager.output_hist)
    
  •    for ns in ns_refs:
    
  •        to_delete = [n for n, o in ns.items() if o is obj]
    
  •        for name in to_delete:
    
  •            del ns[name]
    
  •    # Ensure it is removed from the last execution result
    
  •    if self.last_execution_result.result is obj:
    
  •        self.last_execution_result = None
    
  •    # displayhook keeps extra references, but not in a dictionary
    
  •    for name in ('_', '__', '___'):
    
  •        if getattr(self.displayhook, name) is obj:
    
  •            setattr(self.displayhook, name, None)
    

+def reset_selective(self, regex=None):

  • """Clear selective variables from internal namespaces based on a
  • specified regular expression.
  • Parameters

  • regex : string or compiled pattern, optional
  •    A regular expression pattern that will be used in searching
    
  •    variable names in the users namespaces.
    
  • """
  • if regex is not None:
  •    try:
    
  •        m = re.compile(regex)
    
  •    except TypeError:
    
  •        raise TypeError('regex must be a string or compiled pattern')
    
  •    # Search for keys in each namespace that match the given regex
    
  •    # If a match is found, delete the key/value pair.
    
  •    for ns in self.all_ns_refs:
    
  •        for var in ns:
    
  •            if m.search(var):
    
  •                del ns[var]
    

+def push(self, variables, interactive=True):

  • """Inject a group of variables into the IPython user namespace.
  • Parameters

  • variables : dict, str or list/tuple of str
  •    The variables to inject into the user's namespace.  If a dict, a
    
  •    simple update is done.  If a str, the string is assumed to have
    
  •    variable names separated by spaces.  A list/tuple of str can also
    
  •    be used to give the variable names.  If just the variable names are
    
  •    give (list/tuple/str) then the variable values looked up in the
    
  •    callers frame.
    
  • interactive : bool
  •    If True (default), the variables will be listed with the ``who``
    
  •    magic.
    
  • """
  • vdict = None
  • We need a dict of name/value pairs to do namespace updates.

  • if isinstance(variables, dict):
  •    vdict = variables
    
  • elif isinstance(variables, (str, list, tuple)):
  •    if isinstance(variables, str):
    
  •        vlist = variables.split()
    
  •    else:
    
  •        vlist = variables
    
  •    vdict = {}
    
  •    cf = sys._getframe(1)
    
  •    for name in vlist:
    
  •        try:
    
  •            vdict[name] = eval(name, cf.f_globals, cf.f_locals)
    
  •        except:
    
  •            print('Could not get variable %s from %s' %
    
  •                   (name,cf.f_code.co_name))
    
  • else:
  •    raise ValueError('variables must be a dict/str/list/tuple')
    
  • Propagate variables to user namespace

  • self.user_ns.update(vdict)
  • And configure interactive visibility

  • user_ns_hidden = self.user_ns_hidden
  • if interactive:
  •    for name in vdict:
    
  •        user_ns_hidden.pop(name, None)
    
  • else:
  •    user_ns_hidden.update(vdict)
    

+def drop_by_id(self, variables):

  • """Remove a dict of variables from the user namespace, if they are the
  • same as the values in the dictionary.
  • This is intended for use by extensions: variables that they've added can
  • be taken back out if they are unloaded, without removing any that the
  • user has overwritten.
  • Parameters

  • variables : dict
  •  A dictionary mapping object names (as strings) to the objects.
    
  • """
  • for name, obj in variables.items():
  •    if name in self.user_ns and self.user_ns[name] is obj:
    
  •        del self.user_ns[name]
    
  •        self.user_ns_hidden.pop(name, None)
    

+#-------------------------------------------------------------------------
+# Things related to object introspection
+#-------------------------------------------------------------------------
+
+def _ofind(self, oname, namespaces=None):

  • """Find an object in the available namespaces.
  • self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
  • Has special code to detect magic functions.
  • """
  • oname = oname.strip()
  • if not oname.startswith(ESC_MAGIC) and \
  •        not oname.startswith(ESC_MAGIC2) and \
    
  •        not all(a.isidentifier() for a in oname.split(".")):
    
  •    return {'found': False}
    
  • if namespaces is None:
  •    # Namespaces to search in:
    
  •    # Put them in a list. The order is important so that we
    
  •    # find things in the same order that Python finds them.
    
  •    namespaces = [ ('Interactive', self.user_ns),
    
  •                   ('Interactive (global)', self.user_global_ns),
    
  •                   ('Python builtin', builtin_mod.__dict__),
    
  •                   ]
    
  • ismagic = False
  • isalias = False
  • found = False
  • ospace = None
  • parent = None
  • obj = None
  • Look for the given name by splitting it in parts. If the head is

  • found, then we look for all the remaining parts as members, and only

  • declare success if we can find them all.

  • oname_parts = oname.split('.')
  • oname_head, oname_rest = oname_parts[0],oname_parts[1:]
  • for nsname,ns in namespaces:
  •    try:
    
  •        obj = ns[oname_head]
    
  •    except KeyError:
    
  •        continue
    
  •    else:
    
  •        for idx, part in enumerate(oname_rest):
    
  •            try:
    
  •                parent = obj
    
  •                # The last part is looked up in a special way to avoid
    
  •                # descriptor invocation as it may raise or have side
    
  •                # effects.
    
  •                if idx == len(oname_rest) - 1:
    
  •                    obj = self._getattr_property(obj, part)
    
  •                else:
    
  •                    obj = getattr(obj, part)
    
  •            except:
    
  •                # Blanket except b/c some badly implemented objects
    
  •                # allow __getattr__ to raise exceptions other than
    
  •                # AttributeError, which then crashes IPython.
    
  •                break
    
  •        else:
    
  •            # If we finish the for loop (no break), we got all members
    
  •            found = True
    
  •            ospace = nsname
    
  •            break  # namespace loop
    
  • Try to see if it's magic

  • if not found:
  •    obj = None
    
  •    if oname.startswith(ESC_MAGIC2):
    
  •        oname = oname.lstrip(ESC_MAGIC2)
    
  •        obj = self.find_cell_magic(oname)
    
  •    elif oname.startswith(ESC_MAGIC):
    
  •        oname = oname.lstrip(ESC_MAGIC)
    
  •        obj = self.find_line_magic(oname)
    
  •    else:
    
  •        # search without prefix, so run? will find %run?
    
  •        obj = self.find_line_magic(oname)
    
  •        if obj is None:
    
  •            obj = self.find_cell_magic(oname)
    
  •    if obj is not None:
    
  •        found = True
    
  •        ospace = 'IPython internal'
    
  •        ismagic = True
    
  •        isalias = isinstance(obj, Alias)
    
  • Last try: special-case some literals like '', [], {}, etc:

  • if not found and oname_head in ["''",'""','[]','{}','()']:
  •    obj = eval(oname_head)
    
  •    found = True
    
  •    ospace = 'Interactive'
    
  • return {
  •        'obj':obj,
    
  •        'found':found,
    
  •        'parent':parent,
    
  •        'ismagic':ismagic,
    
  •        'isalias':isalias,
    
  •        'namespace':ospace
    
  •       }
    

+@staticmethod
+def _getattr_property(obj, attrname):

  • """Property-aware getattr to use in object finding.
  • If attrname represents a property, return it unevaluated (in case it has
  • side effects or raises an error.
  • """
  • if not isinstance(obj, type):
  •    try:
    
  •        # `getattr(type(obj), attrname)` is not guaranteed to return
    
  •        # `obj`, but does so for property:
    
  •        #
    
  •        # property.__get__(self, None, cls) -> self
    
  •        #
    
  •        # The universal alternative is to traverse the mro manually
    
  •        # searching for attrname in class dicts.
    
  •        attr = getattr(type(obj), attrname)
    
  •    except AttributeError:
    
  •        pass
    
  •    else:
    
  •        # This relies on the fact that data descriptors (with both
    
  •        # __get__ & __set__ magic methods) take precedence over
    
  •        # instance-level attributes:
    
  •        #
    
  •        #    class A(object):
    
  •        #        @property
    
  •        #        def foobar(self): return 123
    
  •        #    a = A()
    
  •        #    a.__dict__['foobar'] = 345
    
  •        #    a.foobar  # == 123
    
  •        #
    
  •        # So, a property may be returned right away.
    
  •        if isinstance(attr, property):
    
  •            return attr
    
  • Nothing helped, fall back.

  • return getattr(obj, attrname)

+def _object_find(self, oname, namespaces=None):

  • """Find an object and return a struct with info about it."""
  • return Struct(self._ofind(oname, namespaces))

+def _inspect(self, meth, oname, namespaces=None, **kw):

  • """Generic interface to the inspector system.
  • This function is meant to be called by pdef, pdoc & friends.
  • """
  • info = self._object_find(oname, namespaces)
  • docformat = sphinxify if self.sphinxify_docstring else None
  • if info.found:
  •    pmethod = getattr(self.inspector, meth)
    
  •    # TODO: only apply format_screen to the plain/text repr of the mime
    
  •    # bundle.
    
  •    formatter = format_screen if info.ismagic else docformat
    
  •    if meth == 'pdoc':
    
  •        pmethod(info.obj, oname, formatter)
    
  •    elif meth == 'pinfo':
    
  •        pmethod(info.obj, oname, formatter, info, 
    
  •                enable_html_pager=self.enable_html_pager, **kw)
    
  •    else:
    
  •        pmethod(info.obj, oname)
    
  • else:
  •    print('Object `%s` not found.' % oname)
    
  •    return 'not found'  # so callers can take other action
    

+def object_inspect(self, oname, detail_level=0):

  • """Get object info about oname"""
  • with self.builtin_trap:
  •    info = self._object_find(oname)
    
  •    if info.found:
    
  •        return self.inspector.info(info.obj, oname, info=info,
    
  •                    detail_level=detail_level
    
  •        )
    
  •    else:
    
  •        return oinspect.object_info(name=oname, found=False)
    

+def object_inspect_text(self, oname, detail_level=0):

  • """Get object info as formatted text"""
  • return self.object_inspect_mime(oname, detail_level)['text/plain']

+def object_inspect_mime(self, oname, detail_level=0):

  • """Get object info as a mimebundle of formatted representations.
  • A mimebundle is a dictionary, keyed by mime-type.
  • It must always have the key 'text/plain'.
  • """
  • with self.builtin_trap:
  •    info = self._object_find(oname)
    
  •    if info.found:
    
  •        return self.inspector._get_info(info.obj, oname, info=info,
    
  •                    detail_level=detail_level
    
  •        )
    
  •    else:
    
  •        raise KeyError(oname)
    

+#-------------------------------------------------------------------------
+# Things related to history management
+#-------------------------------------------------------------------------
+
+def init_history(self):

  • """Sets up the command history, and starts regular autosaves."""
  • self.history_manager = HistoryManager(shell=self, parent=self)
  • self.configurables.append(self.history_manager)

+#-------------------------------------------------------------------------
+# Things related to exception handling and tracebacks (not debugging)
+#-------------------------------------------------------------------------
+
+debugger_cls = Pdb
+
+def init_traceback_handlers(self, custom_exceptions):

  • Syntax error handler.

  • self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
  • The interactive one is initialized with an offset, meaning we always

  • want to remove the topmost item in the traceback, which is our own

  • internal code. Valid modes: ['Plain','Context','Verbose']

  • self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
  •                                             color_scheme='NoColor',
    
  •                                             tb_offset = 1,
    
  •                           check_cache=check_linecache_ipython,
    
  •                           debugger_cls=self.debugger_cls, parent=self)
    
  • The instance will store a pointer to the system-wide exception hook,

  • so that runtime code (such as magics) can access it. This is because

  • during the read-eval loop, it may get temporarily overwritten.

  • self.sys_excepthook = sys.excepthook
  • and add any custom exception handlers the user may have specified

  • self.set_custom_exc(*custom_exceptions)
  • Set the exception mode

  • self.InteractiveTB.set_mode(mode=self.xmode)

+def set_custom_exc(self, exc_tuple, handler):

  • """set_custom_exc(exc_tuple, handler)
  • Set a custom exception handler, which will be called if any of the
  • exceptions in exc_tuple occur in the mainloop (specifically, in the
  • run_code() method).
  • Parameters

  • exc_tuple : tuple of exception classes
  •    A *tuple* of exception classes, for which to call the defined
    
  •    handler.  It is very important that you use a tuple, and NOT A
    
  •    LIST here, because of the way Python's except statement works.  If
    
  •    you only want to trap a single exception, use a singleton tuple::
    
  •        exc_tuple == (MyCustomException,)
    
  • handler : callable
  •    handler must have the following signature::
    
  •        def my_handler(self, etype, value, tb, tb_offset=None):
    
  •            ...
    
  •            return structured_traceback
    
  •    Your handler must return a structured traceback (a list of strings),
    
  •    or None.
    
  •    This will be made into an instance method (via types.MethodType)
    
  •    of IPython itself, and it will be called if any of the exceptions
    
  •    listed in the exc_tuple are caught. If the handler is None, an
    
  •    internal basic one is used, which just prints basic info.
    
  •    To protect IPython from crashes, if your handler ever raises an
    
  •    exception or returns an invalid result, it will be immediately
    
  •    disabled.
    
  • WARNING: by putting in your own exception handler into IPython's main
  • execution loop, you run a very good chance of nasty crashes. This
  • facility should only be used if you really know what you are doing."""
  • if not isinstance(exc_tuple, tuple):
  •    raise TypeError("The custom exceptions must be given as a tuple.")
    
  • def dummy_handler(self, etype, value, tb, tb_offset=None):
  •    print('*** Simple custom exception handler ***')
    
  •    print('Exception type :', etype)
    
  •    print('Exception value:', value)
    
  •    print('Traceback      :', tb)
    
  • def validate_stb(stb):
  •    """validate structured traceback return type
    
  •    return type of CustomTB *should* be a list of strings, but allow
    
  •    single strings or None, which are harmless.
    
  •    This function will *always* return a list of strings,
    
  •    and will raise a TypeError if stb is inappropriate.
    
  •    """
    
  •    msg = "CustomTB must return list of strings, not %r" % stb
    
  •    if stb is None:
    
  •        return []
    
  •    elif isinstance(stb, str):
    
  •        return [stb]
    
  •    elif not isinstance(stb, list):
    
  •        raise TypeError(msg)
    
  •    # it's a list
    
  •    for line in stb:
    
  •        # check every element
    
  •        if not isinstance(line, str):
    
  •            raise TypeError(msg)
    
  •    return stb
    
  • if handler is None:
  •    wrapped = dummy_handler
    
  • else:
  •    def wrapped(self,etype,value,tb,tb_offset=None):
    
  •        """wrap CustomTB handler, to protect IPython from user code
    
  •        This makes it harder (but not impossible) for custom exception
    
  •        handlers to crash IPython.
    
  •        """
    
  •        try:
    
  •            stb = handler(self,etype,value,tb,tb_offset=tb_offset)
    
  •            return validate_stb(stb)
    
  •        except:
    
  •            # clear custom handler immediately
    
  •            self.set_custom_exc((), None)
    
  •            print("Custom TB Handler failed, unregistering", file=sys.stderr)
    
  •            # show the exception in handler first
    
  •            stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
    
  •            print(self.InteractiveTB.stb2text(stb))
    
  •            print("The original exception:")
    
  •            stb = self.InteractiveTB.structured_traceback(
    
  •                                    (etype,value,tb), tb_offset=tb_offset
    
  •            )
    
  •        return stb
    
  • self.CustomTB = types.MethodType(wrapped,self)
  • self.custom_exceptions = exc_tuple

+def excepthook(self, etype, value, tb):

  • """One more defense for GUI apps that call sys.excepthook.
  • GUI frameworks like wxPython trap exceptions and call
  • sys.excepthook themselves. I guess this is a feature that
  • enables them to keep running after exceptions that would
  • otherwise kill their mainloop. This is a bother for IPython
  • which excepts to catch all of the program exceptions with a try:
  • except: statement.
  • Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
  • any app directly invokes sys.excepthook, it will look to the user like
  • IPython crashed. In order to work around this, we can disable the
  • CrashHandler and replace it with this excepthook instead, which prints a
  • regular traceback using our InteractiveTB. In this fashion, apps which
  • call sys.excepthook will generate a regular-looking exception from
  • IPython, and the CrashHandler will only be triggered by real IPython
  • crashes.
  • This hook should be used sparingly, only in places which are not likely
  • to be true IPython errors.
  • """
  • self.showtraceback((etype, value, tb), tb_offset=0)

+def _get_exc_info(self, exc_tuple=None):

  • """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
  • Ensures sys.last_type,value,traceback hold the exc_info we found,
  • from whichever source.
  • raises ValueError if none of these contain any information
  • """
  • if exc_tuple is None:
  •    etype, value, tb = sys.exc_info()
    
  • else:
  •    etype, value, tb = exc_tuple
    
  • if etype is None:
  •    if hasattr(sys, 'last_type'):
    
  •        etype, value, tb = sys.last_type, sys.last_value, \
    
  •                           sys.last_traceback
    
  • if etype is None:
  •    raise ValueError("No exception to find")
    
  • Now store the exception info in sys.last_type etc.

  • WARNING: these variables are somewhat deprecated and not

  • necessarily safe to use in a threaded environment, but tools

  • like pdb depend on their existence, so let's set them. If we

  • find problems in the field, we'll need to revisit their use.

  • sys.last_type = etype
  • sys.last_value = value
  • sys.last_traceback = tb
  • return etype, value, tb

+def show_usage_error(self, exc):

  • """Show a short message for UsageErrors
  • These are special exceptions that shouldn't show a traceback.
  • """
  • print("UsageError: %s" % exc, file=sys.stderr)

+def get_exception_only(self, exc_tuple=None):

  • """
  • Return as a string (ending with a newline) the exception that
  • just occurred, without any traceback.
  • """
  • etype, value, tb = self._get_exc_info(exc_tuple)
  • msg = traceback.format_exception_only(etype, value)
  • return ''.join(msg)

+def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,

  •              exception_only=False, running_compiled_code=False):
    
  • """Display the exception that just occurred.
  • If nothing is known about the exception, this is the method which
  • should be used throughout the code for presenting user tracebacks,
  • rather than directly invoking the InteractiveTB object.
  • A specific showsyntaxerror() also exists, but this method can take
  • care of calling it if needed, so unless you are explicitly catching a
  • SyntaxError exception, don't try to analyze the stack manually and
  • simply call this method."""
  • try:
  •    try:
    
  •        etype, value, tb = self._get_exc_info(exc_tuple)
    
  •    except ValueError:
    
  •        print('No traceback available to show.', file=sys.stderr)
    
  •        return
    
  •    if issubclass(etype, SyntaxError):
    
  •        # Though this won't be called by syntax errors in the input
    
  •        # line, there may be SyntaxError cases with imported code.
    
  •        self.showsyntaxerror(filename, running_compiled_code)
    
  •    elif etype is UsageError:
    
  •        self.show_usage_error(value)
    
  •    else:
    
  •        if exception_only:
    
  •            stb = ['An exception has occurred, use %tb to see '
    
  •                   'the full traceback.\n']
    
  •            stb.extend(self.InteractiveTB.get_exception_only(etype,
    
  •                                                             value))
    
  •        else:
    
  •            try:
    
  •                # Exception classes can customise their traceback - we
    
  •                # use this in IPython.parallel for exceptions occurring
    
  •                # in the engines. This should return a list of strings.
    
  •                stb = value._render_traceback_()
    
  •            except Exception:
    
  •                stb = self.InteractiveTB.structured_traceback(etype,
    
  •                                    value, tb, tb_offset=tb_offset)
    
  •            self._showtraceback(etype, value, stb)
    
  •            if self.call_pdb:
    
  •                # drop into debugger
    
  •                self.debugger(force=True)
    
  •            return
    
  •        # Actually show the traceback
    
  •        self._showtraceback(etype, value, stb)
    
  • except KeyboardInterrupt:
  •    print('\n' + self.get_exception_only(), file=sys.stderr)
    

+def _showtraceback(self, etype, evalue, stb):

  • """Actually show a traceback.
  • Subclasses may override this method to put the traceback on a different
  • place, like a side channel.
  • """
  • print(self.InteractiveTB.stb2text(stb))

+def showsyntaxerror(self, filename=None, running_compiled_code=False):

  • """Display the syntax error that just occurred.
  • This doesn't display a stack trace because there isn't one.
  • If a filename is given, it is stuffed in the exception instead
  • of what was there before (because Python's parser always uses
  • "" when reading from a string).
  • If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
  • longer stack trace will be displayed.
  • """
    
  • etype, value, last_traceback = self._get_exc_info()
  • if filename and issubclass(etype, SyntaxError):
  •    try:
    
  •        value.filename = filename
    
  •    except:
    
  •        # Not the format we expect; leave it alone
    
  •        pass
    
  • If the error occurred when executing compiled code, we should provide full stacktrace.

  • elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
  • stb = self.SyntaxTB.structured_traceback(etype, value, elist)
  • self._showtraceback(etype, value, stb)

+# This is overridden in TerminalInteractiveShell to show a message about
+# the %paste magic.
+def showindentationerror(self):

  • """Called by _run_cell when there's an IndentationError in code entered
  • at the prompt.
  • This is overridden in TerminalInteractiveShell to show a message about
  • the %paste magic."""
  • self.showsyntaxerror()

+#-------------------------------------------------------------------------
+# Things related to readline
+#-------------------------------------------------------------------------
+
+def init_readline(self):

  • """DEPRECATED
  • Moved to terminal subclass, here only to simplify the init logic."""
  • Set a number of methods that depend on readline to be no-op

  • warnings.warn('init_readline is no-op since IPython 5.0 and is Deprecated',
  •        DeprecationWarning, stacklevel=2)
    
  • self.set_custom_completer = no_op

+@skip_doctest
+def set_next_input(self, s, replace=False):

  • """ Sets the 'default' input string for the next command line.
  • Example::
  •    In [1]: _ip.set_next_input("Hello Word")
    
  •    In [2]: Hello Word_  # cursor is here
    
  • """
  • self.rl_next_input = s

+def _indent_current_str(self):

  • """return the current level of indentation as a string"""
  • return self.input_splitter.get_indent_spaces() * ' '

+#-------------------------------------------------------------------------
+# Things related to text completion
+#-------------------------------------------------------------------------
+
+def init_completer(self):

  • """Initialize the completion machinery.
  • This creates completion machinery that can be used by client code,
  • either interactively in-process (typically triggered by the readline
  • library), programmatically (such as in test suites) or out-of-process
  • (typically over the network by remote frontends).
  • """
  • from IPython.core.completer import IPCompleter
  • from IPython.core.completerlib import (module_completer,
  •        magic_run_completer, cd_completer, reset_completer)
    
  • self.Completer = IPCompleter(shell=self,
  •                             namespace=self.user_ns,
    
  •                             global_namespace=self.user_global_ns,
    
  •                             parent=self,
    
  •                             )
    
  • self.configurables.append(self.Completer)
  • Add custom completers to the basic ones built into IPCompleter

  • sdisp = self.strdispatchers.get('complete_command', StrDispatch())
  • self.strdispatchers['complete_command'] = sdisp
  • self.Completer.custom_completers = sdisp
  • self.set_hook('complete_command', module_completer, str_key = 'import')
  • self.set_hook('complete_command', module_completer, str_key = 'from')
  • self.set_hook('complete_command', module_completer, str_key = '%aimport')
  • self.set_hook('complete_command', magic_run_completer, str_key = '%run')
  • self.set_hook('complete_command', cd_completer, str_key = '%cd')
  • self.set_hook('complete_command', reset_completer, str_key = '%reset')

+@skip_doctest
+def complete(self, text, line=None, cursor_pos=None):

  • """Return the completed text and a list of completions.
  • Parameters

  •   text : string
    
  •     A string of text to be completed on.  It can be given as empty and
    
  •     instead a line/position pair are given.  In this case, the
    
  •     completer itself will split the line like readline does.
    
  •   line : string, optional
    
  •     The complete line that text is part of.
    
  •   cursor_pos : int, optional
    
  •     The position of the cursor on the input line.
    
  • Returns

  •  text : string
    
  •    The actual text that was completed.
    
  •  matches : list
    
  •    A sorted list with all possible completions.
    
  • The optional arguments allow the completion to take more context into
  • account, and are part of the low-level completion API.
  • This is a wrapper around the completion mechanism, similar to what
  • readline does at the command line when the TAB key is hit. By
  • exposing it as a method, it can be used by other non-readline
  • environments (such as GUIs) for text completion.
  • Simple usage example:
  • In [1]: x = 'hello'
  • In [2]: _ip.complete('x.l')
  • Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
  • """
  • Inject names into builtin so we can complete on the added names.

  • with self.builtin_trap:
  •    return self.Completer.complete(text, line, cursor_pos)
    

+def set_custom_completer(self, completer, pos=0):

  • """Adds a new custom completer function.
  • The position argument (defaults to 0) is the index in the completers
  • list where you want the completer to be inserted."""
  • newcomp = types.MethodType(completer,self.Completer)
  • self.Completer.matchers.insert(pos,newcomp)

+def set_completer_frame(self, frame=None):

  • """Set the frame of the completer."""
  • if frame:
  •    self.Completer.namespace = frame.f_locals
    
  •    self.Completer.global_namespace = frame.f_globals
    
  • else:
  •    self.Completer.namespace = self.user_ns
    
  •    self.Completer.global_namespace = self.user_global_ns
    

+#-------------------------------------------------------------------------
+# Things related to magics
+#-------------------------------------------------------------------------
+
+def init_magics(self):

  • from IPython.core import magics as m
  • self.magics_manager = magic.MagicsManager(shell=self,
  •                           parent=self,
    
  •                           user_magics=m.UserMagics(self))
    
  • self.configurables.append(self.magics_manager)
  • Expose as public API from the magics manager

  • self.register_magics = self.magics_manager.register
  • self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
  •    m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
    
  •    m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
    
  •    m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
    
  • )
  • Register Magic Aliases

  • mman = self.magics_manager
  • FIXME: magic aliases should be defined by the Magics classes

  • or in MagicsManager, not here

  • mman.register_alias('ed', 'edit')
  • mman.register_alias('hist', 'history')
  • mman.register_alias('rep', 'recall')
  • mman.register_alias('SVG', 'svg', 'cell')
  • mman.register_alias('HTML', 'html', 'cell')
  • mman.register_alias('file', 'writefile', 'cell')
  • FIXME: Move the color initialization to the DisplayHook, which

  • should be split into a prompt manager and displayhook. We probably

  • even need a centralize colors management object.

  • self.run_line_magic('colors', self.colors)

+# Defined here so that it's included in the documentation
+@functools.wraps(magic.MagicsManager.register_function)
+def register_magic_function(self, func, magic_kind='line', magic_name=None):

  • self.magics_manager.register_function(func,
  •                          magic_kind=magic_kind, magic_name=magic_name)
    

+def run_line_magic(self, magic_name, line, _stack_depth=1):

  • """Execute the given line magic.
  • Parameters

  • magic_name : str
  •  Name of the desired magic function, without '%' prefix.
    
  • line : str
  •  The rest of the input line as a single string.
    
  • _stack_depth : int
  •  If run_line_magic() is called from magic() then _stack_depth=2.
    
  •  This is added to ensure backward compatibility for use of 'get_ipython().magic()'
    
  • """
  • fn = self.find_line_magic(magic_name)
  • if fn is None:
  •    cm = self.find_cell_magic(magic_name)
    
  •    etpl = "Line magic function `%%%s` not found%s."
    
  •    extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
    
  •                            'did you mean that instead?)' % magic_name )
    
  •    raise UsageError(etpl % (magic_name, extra))
    
  • else:
  •    # Note: this is the distance in the stack to the user's frame.
    
  •    # This will need to be updated if the internal calling logic gets
    
  •    # refactored, or else we'll be expanding the wrong variables.
    
  •    # Determine stack_depth depending on where run_line_magic() has been called
    
  •    stack_depth = _stack_depth
    
  •    magic_arg_s = self.var_expand(line, stack_depth)
    
  •    # Put magic args in a list so we can call with f(*a) syntax
    
  •    args = [magic_arg_s]
    
  •    kwargs = {}
    
  •    # Grab local namespace if we need it:
    
  •    if getattr(fn, "needs_local_scope", False):
    
  •        kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
    
  •    with self.builtin_trap:
    
  •        result = fn(*args,**kwargs)
    
  •    return result
    

+def run_cell_magic(self, magic_name, line, cell):

  • """Execute the given cell magic.
  • Parameters

  • magic_name : str
  •  Name of the desired magic function, without '%' prefix.
    
  • line : str
  •  The rest of the first input line as a single string.
    
  • cell : str
  •  The body of the cell as a (possibly multiline) string.
    
  • """
  • fn = self.find_cell_magic(magic_name)
  • if fn is None:
  •    lm = self.find_line_magic(magic_name)
    
  •    etpl = "Cell magic `%%{0}` not found{1}."
    
  •    extra = '' if lm is None else (' (But line magic `%{0}` exists, '
    
  •                    'did you mean that instead?)'.format(magic_name))
    
  •    raise UsageError(etpl.format(magic_name, extra))
    
  • elif cell == '':
  •    message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
    
  •    if self.find_line_magic(magic_name) is not None:
    
  •        message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
    
  •    raise UsageError(message)
    
  • else:
  •    # Note: this is the distance in the stack to the user's frame.
    
  •    # This will need to be updated if the internal calling logic gets
    
  •    # refactored, or else we'll be expanding the wrong variables.
    
  •    stack_depth = 2
    
  •    magic_arg_s = self.var_expand(line, stack_depth)
    
  •    with self.builtin_trap:
    
  •        result = fn(magic_arg_s, cell)
    
  •    return result
    

+def find_line_magic(self, magic_name):

  • """Find and return a line magic by name.
  • Returns None if the magic isn't found."""
  • return self.magics_manager.magics['line'].get(magic_name)

+def find_cell_magic(self, magic_name):

  • """Find and return a cell magic by name.
  • Returns None if the magic isn't found."""
  • return self.magics_manager.magics['cell'].get(magic_name)

+def find_magic(self, magic_name, magic_kind='line'):

  • """Find and return a magic of the given type by name.
  • Returns None if the magic isn't found."""
  • return self.magics_manager.magics[magic_kind].get(magic_name)

+def magic(self, arg_s):

  • """DEPRECATED. Use run_line_magic() instead.
  • Call a magic function by name.
  • Input: a string containing the name of the magic function to call and
  • any additional arguments to be passed to the magic.
  • magic('name -opt foo bar') is equivalent to typing at the ipython
  • prompt:
  • In[1]: %name -opt foo bar
  • To call a magic without arguments, simply use magic('name').
  • This provides a proper Python function to call IPython's magics in any
  • valid Python code you can type at the interpreter, including loops and
  • compound statements.
  • """
  • TODO: should we issue a loud deprecation warning here?

  • magic_name, _, magic_arg_s = arg_s.partition(' ')
  • magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
  • return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)

+#-------------------------------------------------------------------------
+# Things related to macros
+#-------------------------------------------------------------------------
+
+def define_macro(self, name, themacro):

  • """Define a new macro
  • Parameters

  • name : str
  •    The name of the macro.
    
  • themacro : str or Macro
  •    The action to do upon invoking the macro.  If a string, a new
    
  •    Macro object is created by passing the string to it.
    
  • """
  • from IPython.core import macro
  • if isinstance(themacro, str):
  •    themacro = macro.Macro(themacro)
    
  • if not isinstance(themacro, macro.Macro):
  •    raise ValueError('A macro must be a string or a Macro instance.')
    
  • self.user_ns[name] = themacro

+#-------------------------------------------------------------------------
+# Things related to the running of system commands
+#-------------------------------------------------------------------------
+
+def system_piped(self, cmd):

  • """Call the given cmd in a subprocess, piping stdout/err
  • Parameters

  • cmd : str
  •  Command to execute (can not end in '&', as background processes are
    
  •  not supported.  Should not be a command that expects input
    
  •  other than simple text.
    
  • """
  • if cmd.rstrip().endswith('&'):
  •    # this is *far* from a rigorous test
    
  •    # We do not support backgrounding processes because we either use
    
  •    # pexpect or pipes to read from.  Users can always just call
    
  •    # os.system() or use ip.system=ip.system_raw
    
  •    # if they really want a background process.
    
  •    raise OSError("Background processes not supported.")
    
  • we explicitly do NOT return the subprocess status code, because

  • a non-None value would trigger :func:sys.displayhook calls.

  • Instead, we store the exit_code in user_ns.

  • self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))

+def system_raw(self, cmd):

  • """Call the given cmd in a subprocess using os.system on Windows or
  • subprocess.call using the system shell on other platforms.
  • Parameters

  • cmd : str
  •  Command to execute.
    
  • """
  • cmd = self.var_expand(cmd, depth=1)
  • protect os.system from UNC paths on Windows, which it can't handle:

  • if sys.platform == 'win32':
  •    from IPython.utils._process_win32 import AvoidUNCPath
    
  •    with AvoidUNCPath() as path:
    
  •        if path is not None:
    
  •            cmd = '"pushd %s &&"%s' % (path, cmd)
    
  •        try:
    
  •            ec = os.system(cmd)
    
  •        except KeyboardInterrupt:
    
  •            print('\n' + self.get_exception_only(), file=sys.stderr)
    
  •            ec = -2
    
  • else:
  •    # For posix the result of the subprocess.call() below is an exit
    
  •    # code, which by convention is zero for success, positive for
    
  •    # program failure.  Exit codes above 128 are reserved for signals,
    
  •    # and the formula for converting a signal to an exit code is usually
    
  •    # signal_number+128.  To more easily differentiate between exit
    
  •    # codes and signals, ipython uses negative numbers.  For instance
    
  •    # since control-c is signal 2 but exit code 130, ipython's
    
  •    # _exit_code variable will read -2.  Note that some shells like
    
  •    # csh and fish don't follow sh/bash conventions for exit codes.
    
  •    executable = os.environ.get('SHELL', None)
    
  •    try:
    
  •        # Use env shell instead of default /bin/sh
    
  •        ec = subprocess.call(cmd, shell=True, executable=executable)
    
  •    except KeyboardInterrupt:
    
  •        # intercept control-C; a long traceback is not useful here
    
  •        print('\n' + self.get_exception_only(), file=sys.stderr)
    
  •        ec = 130
    
  •    if ec > 128:
    
  •        ec = -(ec - 128)
    
  • We explicitly do NOT return the subprocess status code, because

  • a non-None value would trigger :func:sys.displayhook calls.

  • Instead, we store the exit_code in user_ns. Note the semantics

  • of _exit_code: for control-c, _exit_code == -signal.SIGNIT,

  • but raising SystemExit(_exit_code) will give status 254!

  • self.user_ns['_exit_code'] = ec

+# use piped system by default, because it is better behaved
+system = system_piped
+
+def getoutput(self, cmd, split=True, depth=0):

  • """Get output (possibly including stderr) from a subprocess.
  • Parameters

  • cmd : str
  •  Command to execute (can not end in '&', as background processes are
    
  •  not supported.
    
  • split : bool, optional
  •  If True, split the output into an IPython SList.  Otherwise, an
    
  •  IPython LSString is returned.  These are objects similar to normal
    
  •  lists and strings, with a few convenience attributes for easier
    
  •  manipulation of line-based output.  You can use '?' on them for
    
  •  details.
    
  • depth : int, optional
  •  How many frames above the caller are the local variables which should
    
  •  be expanded in the command string? The default (0) assumes that the
    
  •  expansion variables are in the stack frame calling this function.
    
  • """
  • if cmd.rstrip().endswith('&'):
  •    # this is *far* from a rigorous test
    
  •    raise OSError("Background processes not supported.")
    
  • out = getoutput(self.var_expand(cmd, depth=depth+1))
  • if split:
  •    out = SList(out.splitlines())
    
  • else:
  •    out = LSString(out)
    
  • return out

+#-------------------------------------------------------------------------
+# Things related to aliases
+#-------------------------------------------------------------------------
+
+def init_alias(self):

  • self.alias_manager = AliasManager(shell=self, parent=self)
  • self.configurables.append(self.alias_manager)

+#-------------------------------------------------------------------------
+# Things related to extensions
+#-------------------------------------------------------------------------
+
+def init_extension_manager(self):

  • self.extension_manager = ExtensionManager(shell=self, parent=self)
  • self.configurables.append(self.extension_manager)

+#-------------------------------------------------------------------------
+# Things related to payloads
+#-------------------------------------------------------------------------
+
+def init_payload(self):

  • self.payload_manager = PayloadManager(parent=self)
  • self.configurables.append(self.payload_manager)

+#-------------------------------------------------------------------------
+# Things related to the prefilter
+#-------------------------------------------------------------------------
+
+def init_prefilter(self):

  • self.prefilter_manager = PrefilterManager(shell=self, parent=self)
  • self.configurables.append(self.prefilter_manager)
  • Ultimately this will be refactored in the new interpreter code, but

  • for now, we should expose the main prefilter method (there's legacy

  • code out there that may rely on this).

  • self.prefilter = self.prefilter_manager.prefilter_lines

+def auto_rewrite_input(self, cmd):

  • """Print to the screen the rewritten form of the user's command.
  • This shows visual feedback by rewriting input lines that cause
  • automatic calling to kick in, like::
  •  /f x
    
  • into::
  •  ------> f(x)
    
  • after the user's input prompt. This helps the user understand that the
  • input line was transformed automatically by IPython.
  • """
  • if not self.show_rewritten_input:
  •    return
    
  • This is overridden in TerminalInteractiveShell to use fancy prompts

  • print("------> " + cmd)

+#-------------------------------------------------------------------------
+# Things related to extracting values/expressions from kernel and user_ns
+#-------------------------------------------------------------------------
+
+def _user_obj_error(self):

  • """return simple exception dict
  • for use in user_expressions
  • """
  • etype, evalue, tb = self._get_exc_info()
  • stb = self.InteractiveTB.get_exception_only(etype, evalue)
  • exc_info = {
  •    u'status' : 'error',
    
  •    u'traceback' : stb,
    
  •    u'ename' : etype.__name__,
    
  •    u'evalue' : py3compat.safe_unicode(evalue),
    
  • }
  • return exc_info

+def _format_user_obj(self, obj):

  • """format a user object to display dict
  • for use in user_expressions
  • """
  • data, md = self.display_formatter.format(obj)
  • value = {
  •    'status' : 'ok',
    
  •    'data' : data,
    
  •    'metadata' : md,
    
  • }
  • return value

+def user_expressions(self, expressions):

  • """Evaluate a dict of expressions in the user's namespace.
  • Parameters

  • expressions : dict
  •  A dict with string keys and string values.  The expression values
    
  •  should be valid Python expressions, each of which will be evaluated
    
  •  in the user namespace.
    
  • Returns

  • A dict, keyed like the input expressions dict, with the rich mime-typed
  • display_data of each value.
  • """
  • out = {}
  • user_ns = self.user_ns
  • global_ns = self.user_global_ns
  • for key, expr in expressions.items():
  •    try:
    
  •        value = self._format_user_obj(eval(expr, global_ns, user_ns))
    
  •    except:
    
  •        value = self._user_obj_error()
    
  •    out[key] = value
    
  • return out

+#-------------------------------------------------------------------------
+# Things related to the running of code
+#-------------------------------------------------------------------------
+
+def ex(self, cmd):

  • """Execute a normal python statement in user namespace."""
  • with self.builtin_trap:
  •    exec(cmd, self.user_global_ns, self.user_ns)
    

+def ev(self, expr):

  • """Evaluate python expression expr in user namespace.
  • Returns the result of evaluation
  • """
  • with self.builtin_trap:
  •    return eval(expr, self.user_global_ns, self.user_ns)
    

+def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):

  • """A safe version of the builtin execfile().
  • This version will never throw an exception, but instead print
  • helpful error messages to the screen. This only works on pure
  • Python files with the .py extension.
  • Parameters

  • fname : string
  •    The name of the file to be executed.
    
  • where : tuple
  •    One or two namespaces, passed to execfile() as (globals,locals).
    
  •    If only one is given, it is passed as both.
    
  • exit_ignore : bool (False)
  •    If True, then silence SystemExit for non-zero status (it is always
    
  •    silenced for zero status, as it is so common).
    
  • raise_exceptions : bool (False)
  •    If True raise exceptions everywhere. Meant for testing.
    
  • shell_futures : bool (False)
  •    If True, the code will share future statements with the interactive
    
  •    shell. It will both be affected by previous __future__ imports, and
    
  •    any __future__ imports in the code will affect the shell. If False,
    
  •    __future__ imports are not shared in either direction.
    
  • """
  • fname = os.path.abspath(os.path.expanduser(fname))
  • Make sure we can open the file

  • try:
  •    with open(fname):
    
  •        pass
    
  • except:
  •    warn('Could not open file <%s> for safe execution.' % fname)
    
  •    return
    
  • Find things also in current directory. This is needed to mimic the

  • behavior of running a script from the system command line, where

  • Python inserts the script's directory into sys.path

  • dname = os.path.dirname(fname)
  • with prepended_to_syspath(dname), self.builtin_trap:
  •    try:
    
  •        glob, loc = (where + (None, ))[:2]
    
  •        py3compat.execfile(
    
  •            fname, glob, loc,
    
  •            self.compile if shell_futures else None)
    
  •    except SystemExit as status:
    
  •        # If the call was made with 0 or None exit status (sys.exit(0)
    
  •        # or sys.exit() ), don't bother showing a traceback, as both of
    
  •        # these are considered normal by the OS:
    
  •        # > python -c'import sys;sys.exit(0)'; echo $?
    
  •        # 0
    
  •        # > python -c'import sys;sys.exit()'; echo $?
    
  •        # 0
    
  •        # For other exit status, we show the exception unless
    
  •        # explicitly silenced, but only in short form.
    
  •        if status.code:
    
  •            if raise_exceptions:
    
  •                raise
    
  •            if not exit_ignore:
    
  •                self.showtraceback(exception_only=True)
    
  •    except:
    
  •        if raise_exceptions:
    
  •            raise
    
  •        # tb offset is 2 because we wrap execfile
    
  •        self.showtraceback(tb_offset=2)
    

+def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):

  • """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
  • Parameters

  • fname : str
  •    The name of the file to execute.  The filename must have a
    
  •    .ipy or .ipynb extension.
    
  • shell_futures : bool (False)
  •    If True, the code will share future statements with the interactive
    
  •    shell. It will both be affected by previous __future__ imports, and
    
  •    any __future__ imports in the code will affect the shell. If False,
    
  •    __future__ imports are not shared in either direction.
    
  • raise_exceptions : bool (False)
  •    If True raise exceptions everywhere.  Meant for testing.
    
  • """
  • fname = os.path.abspath(os.path.expanduser(fname))
  • Make sure we can open the file

  • try:
  •    with open(fname):
    
  •        pass
    
  • except:
  •    warn('Could not open file <%s> for safe execution.' % fname)
    
  •    return
    
  • Find things also in current directory. This is needed to mimic the

  • behavior of running a script from the system command line, where

  • Python inserts the script's directory into sys.path

  • dname = os.path.dirname(fname)
  • def get_cells():
  •    """generator for sequence of code blocks to run"""
    
  •    if fname.endswith('.ipynb'):
    
  •        from nbformat import read
    
  •        nb = read(fname, as_version=4)
    
  •        if not nb.cells:
    
  •            return
    
  •        for cell in nb.cells:
    
  •            if cell.cell_type == 'code':
    
  •                yield cell.source
    
  •    else:
    
  •        with open(fname) as f:
    
  •            yield f.read()
    
  • with prepended_to_syspath(dname):
  •    try:
    
  •        for cell in get_cells():
    
  •            result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
    
  •            if raise_exceptions:
    
  •                result.raise_error()
    
  •            elif not result.success:
    
  •                break
    
  •    except:
    
  •        if raise_exceptions:
    
  •            raise
    
  •        self.showtraceback()
    
  •        warn('Unknown failure executing file: <%s>' % fname)
    

+def safe_run_module(self, mod_name, where):

  • """A safe version of runpy.run_module().
  • This version will never throw an exception, but instead print
  • helpful error messages to the screen.
  • SystemExit exceptions with status code 0 or None are ignored.
  • Parameters

  • mod_name : string
  •    The name of the module to be executed.
    
  • where : dict
  •    The globals namespace.
    
  • """
  • try:
  •    try:
    
  •        where.update(
    
  •            runpy.run_module(str(mod_name), run_name="__main__",
    
  •                             alter_sys=True)
    
  •                    )
    
  •    except SystemExit as status:
    
  •        if status.code:
    
  •            raise
    
  • except:
  •    self.showtraceback()
    
  •    warn('Unknown failure executing module: <%s>' % mod_name)
    

+def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):

  • """Run a complete IPython cell.
  • Parameters

  • raw_cell : str
  •  The code (including IPython code such as %magic functions) to run.
    
  • store_history : bool
  •  If True, the raw and translated cell will be stored in IPython's
    
  •  history. For user code calling back into IPython's machinery, this
    
  •  should be set to False.
    
  • silent : bool
  •  If True, avoid side-effects, such as implicit displayhooks and
    
  •  and logging.  silent=True forces store_history=False.
    
  • shell_futures : bool
  •  If True, the code will share future statements with the interactive
    
  •  shell. It will both be affected by previous __future__ imports, and
    
  •  any __future__ imports in the code will affect the shell. If False,
    
  •  __future__ imports are not shared in either direction.
    
  • Returns

  • result : :class:ExecutionResult
  • """
  • try:
  •    result = self._run_cell(
    
  •        raw_cell, store_history, silent, shell_futures)
    
  • finally:
  •    self.events.trigger('post_execute')
    
  •    if not silent:
    
  •        self.events.trigger('post_run_cell', result)
    
  • return result

+def _run_cell(self, raw_cell, store_history, silent, shell_futures):

  • """Internal method to run a complete IPython cell.
  • Parameters

  • raw_cell : str
  • store_history : bool
  • silent : bool
  • shell_futures : bool
  • Returns

  • result : :class:ExecutionResult
  • """
  • info = ExecutionInfo(
  •    raw_cell, store_history, silent, shell_futures)
    
  • result = ExecutionResult(info)
  • if (not raw_cell) or raw_cell.isspace():
  •    self.last_execution_succeeded = True
    
  •    self.last_execution_result = result
    
  •    return result
    
  • if silent:
  •    store_history = False
    
  • if store_history:
  •    result.execution_count = self.execution_count
    
  • def error_before_exec(value):
  •    if store_history:
    
  •        self.execution_count += 1
    
  •    result.error_before_exec = value
    
  •    self.last_execution_succeeded = False
    
  •    self.last_execution_result = result
    
  •    return result
    
  • self.events.trigger('pre_execute')
  • if not silent:
  •    self.events.trigger('pre_run_cell', info)
    
  • If any of our input transformation (input_transformer_manager or

  • prefilter_manager) raises an exception, we store it in this variable

  • so that we can display the error after logging the input and storing

  • it in the history.

  • preprocessing_exc_tuple = None
  • try:
  •    # Static input transformations
    
  •    cell = self.input_transformer_manager.transform_cell(raw_cell)
    
  • except SyntaxError:
  •    preprocessing_exc_tuple = sys.exc_info()
    
  •    cell = raw_cell  # cell has to exist so it can be stored/logged
    
  • else:
  •    if len(cell.splitlines()) == 1:
    
  •        # Dynamic transformations - only applied for single line commands
    
  •        with self.builtin_trap:
    
  •            try:
    
  •                # use prefilter_lines to handle trailing newlines
    
  •                # restore trailing newline for ast.parse
    
  •                cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
    
  •            except Exception:
    
  •                # don't allow prefilter errors to crash IPython
    
  •                preprocessing_exc_tuple = sys.exc_info()
    
  • Store raw and processed history

  • if store_history:
  •    self.history_manager.store_inputs(self.execution_count,
    
  •                                      cell, raw_cell)
    
  • if not silent:
  •    self.logger.log(cell, raw_cell)
    
  • Display the exception if input processing failed.

  • if preprocessing_exc_tuple is not None:
  •    self.showtraceback(preprocessing_exc_tuple)
    
  •    if store_history:
    
  •        self.execution_count += 1
    
  •    return error_before_exec(preprocessing_exc_tuple[2])
    
  • Our own compiler remembers the future environment. If we want to

  • run code with a separate future environment, use the default

  • compiler

  • compiler = self.compile if shell_futures else CachingCompiler()
  • with self.builtin_trap:
  •    cell_name = self.compile.cache(cell, self.execution_count)
    
  •    with self.display_trap:
    
  •        # Compile to bytecode
    
  •        try:
    
  •            code_ast = compiler.ast_parse(cell, filename=cell_name)
    
  •        except self.custom_exceptions as e:
    
  •            etype, value, tb = sys.exc_info()
    
  •            self.CustomTB(etype, value, tb)
    
  •            return error_before_exec(e)
    
  •        except IndentationError as e:
    
  •            self.showindentationerror()
    
  •            return error_before_exec(e)
    
  •        except (OverflowError, SyntaxError, ValueError, TypeError,
    
  •                MemoryError) as e:
    
  •            self.showsyntaxerror()
    
  •            return error_before_exec(e)
    
  •        # Apply AST transformations
    
  •        try:
    
  •            code_ast = self.transform_ast(code_ast)
    
  •        except InputRejected as e:
    
  •            self.showtraceback()
    
  •            return error_before_exec(e)
    
  •        # Give the displayhook a reference to our ExecutionResult so it
    
  •        # can fill in the output value.
    
  •        self.displayhook.exec_result = result
    
  •        # Execute the user code
    
  •        interactivity = 'none' if silent else self.ast_node_interactivity
    
  •        has_raised = self.run_ast_nodes(code_ast.body, cell_name,
    
  •           interactivity=interactivity, compiler=compiler, result=result)
    
  •        self.last_execution_succeeded = not has_raised
    
  •        self.last_execution_result = result
    
  •        # Reset this so later displayed values do not modify the
    
  •        # ExecutionResult
    
  •        self.displayhook.exec_result = None
    
  • if store_history:
  •    # Write output to the database. Does nothing unless
    
  •    # history output logging is enabled.
    
  •    self.history_manager.store_output(self.execution_count)
    
  •    # Each cell is a *single* input, regardless of how many lines it has
    
  •    self.execution_count += 1
    
  • return result

+def transform_ast(self, node):

  • """Apply the AST transformations from self.ast_transformers
  • Parameters

  • node : ast.Node
  •  The root node to be transformed. Typically called with the ast.Module
    
  •  produced by parsing user input.
    
  • Returns

  • An ast.Node corresponding to the node it was called with. Note that it
  • may also modify the passed object, so don't rely on references to the
  • original AST.
  • """
  • for transformer in self.ast_transformers:
  •    try:
    
  •        node = transformer.visit(node)
    
  •    except InputRejected:
    
  •        # User-supplied AST transformers can reject an input by raising
    
  •        # an InputRejected.  Short-circuit in this case so that we
    
  •        # don't unregister the transform.
    
  •        raise
    
  •    except Exception:
    
  •        warn("AST transformer %r threw an error. It will be unregistered." % transformer)
    
  •        self.ast_transformers.remove(transformer)
    
  • if self.ast_transformers:
  •    ast.fix_missing_locations(node)
    
  • return node

+def run_ast_nodes(self, nodelist:ListType[AST], cell_name:str, interactivity='last_expr',

  •                compiler=compile, result=None):
    
  • """Run a sequence of AST nodes. The execution mode depends on the
  • interactivity parameter.
  • Parameters

  • nodelist : list
  •  A sequence of AST nodes to run.
    
  • cell_name : str
  •  Will be passed to the compiler as the filename of the cell. Typically
    
  •  the value returned by ip.compile.cache(cell).
    
  • interactivity : str
  •  'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
    
  •  specifying which nodes should be run interactively (displaying output
    
  •  from expressions). 'last_expr' will run the last node interactively
    
  •  only if it is an expression (i.e. expressions in loops or other blocks
    
  •  are not displayed) 'last_expr_or_assign' will run the last expression
    
  •  or the last assignment. Other values for this parameter will raise a
    
  •  ValueError.
    
  • compiler : callable
  •  A function with the same interface as the built-in compile(), to turn
    
  •  the AST nodes into code objects. Default is the built-in compile().
    
  • result : ExecutionResult, optional
  •  An object to store exceptions that occur during execution.
    
  • Returns

  • True if an exception occurred while running code, False if it finished
  • running.
  • """
  • if not nodelist:
  •    return
    
  • if interactivity == 'last_expr_or_assign':
  •    if isinstance(nodelist[-1], _assign_nodes):
    
  •        asg = nodelist[-1]
    
  •        if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
    
  •            target = asg.targets[0]
    
  •        elif isinstance(asg, _single_targets_nodes):
    
  •            target = asg.target
    
  •        else:
    
  •            target = None
    
  •        if isinstance(target, ast.Name):
    
  •            nnode = ast.Expr(ast.Name(target.id, ast.Load()))
    
  •            ast.fix_missing_locations(nnode)
    
  •            nodelist.append(nnode)
    
  •    interactivity = 'last_expr'
    
  • if interactivity == 'last_expr':
  •    if isinstance(nodelist[-1], ast.Expr):
    
  •        interactivity = "last"
    
  •    else:
    
  •        interactivity = "none"
    
  • if interactivity == 'none':
  •    to_run_exec, to_run_interactive = nodelist, []
    
  • elif interactivity == 'last':
  •    to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
    
  • elif interactivity == 'all':
  •    to_run_exec, to_run_interactive = [], nodelist
    
  • else:
  •    raise ValueError("Interactivity was %r" % interactivity)
    
  • try:
  •    for i, node in enumerate(to_run_exec):
    
  •        mod = ast.Module([node])
    
  •        code = compiler(mod, cell_name, "exec")
    
  •        if self.run_code(code, result):
    
  •            return True
    
  •    for i, node in enumerate(to_run_interactive):
    
  •        mod = ast.Interactive([node])
    
  •        code = compiler(mod, cell_name, "single")
    
  •        if self.run_code(code, result):
    
  •            return True
    
  •    # Flush softspace
    
  •    if softspace(sys.stdout, 0):
    
  •        print()
    
  • except:
  •    # It's possible to have exceptions raised here, typically by
    
  •    # compilation of odd code (such as a naked 'return' outside a
    
  •    # function) that did parse but isn't valid. Typically the exception
    
  •    # is a SyntaxError, but it's safest just to catch anything and show
    
  •    # the user a traceback.
    
  •    # We do only one try/except outside the loop to minimize the impact
    
  •    # on runtime, and also because if any node in the node list is
    
  •    # broken, we should stop execution completely.
    
  •    if result:
    
  •        result.error_before_exec = sys.exc_info()[1]
    
  •    self.showtraceback()
    
  •    return True
    
  • return False

+def run_code(self, code_obj, result=None):

  • """Execute a code object.
  • When an exception occurs, self.showtraceback() is called to display a
  • traceback.
  • Parameters

  • code_obj : code object
  •  A compiled code object, to be executed
    
  • result : ExecutionResult, optional
  •  An object to store exceptions that occur during execution.
    
  • Returns

  • False : successful execution.
  • True : an error occurred.
  • """
  • Set our own excepthook in case the user code tries to call it

  • directly, so that the IPython crash handler doesn't get triggered

  • old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
  • we save the original sys.excepthook in the instance, in case config

  • code (such as magics) needs access to it.

  • self.sys_excepthook = old_excepthook
  • outflag = True # happens in more places, so it's easier as default
  • try:
  •    try:
    
  •        self.hooks.pre_run_code_hook()
    
  •        #rprint('Running code', repr(code_obj)) # dbg
    
  •        exec(code_obj, self.user_global_ns, self.user_ns)
    
  •    finally:
    
  •        # Reset our crash handler in place
    
  •        sys.excepthook = old_excepthook
    
  • except SystemExit as e:
  •    if result is not None:
    
  •        result.error_in_exec = e
    
  •    self.showtraceback(exception_only=True)
    
  •    warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
    
  • except self.custom_exceptions:
  •    etype, value, tb = sys.exc_info()
    
  •    if result is not None:
    
  •        result.error_in_exec = value
    
  •    self.CustomTB(etype, value, tb)
    
  • except:
  •    if result is not None:
    
  •        result.error_in_exec = sys.exc_info()[1]
    
  •    self.showtraceback(running_compiled_code=True)
    
  • else:
  •    outflag = False
    
  • return outflag

+# For backwards compatibility
+runcode = run_code
+
+def check_complete(self, code):

  • """Return whether a block of code is ready to execute, or should be continued
  • Parameters

  • source : string
  •  Python input code, which can be multiline.
    
  • Returns

  • status : str
  •  One of 'complete', 'incomplete', or 'invalid' if source is not a
    
  •  prefix of valid code.
    
  • indent : str
  •  When status is 'incomplete', this is some whitespace to insert on
    
  •  the next line of the prompt.
    
  • """
  • status, nspaces = self.input_splitter.check_complete(code)
  • return status, ' ' * (nspaces or 0)

+#-------------------------------------------------------------------------
+# Things related to GUI support and pylab
+#-------------------------------------------------------------------------
+
+active_eventloop = None
+
+def enable_gui(self, gui=None):

  • raise NotImplementedError('Implement enable_gui in a subclass')

+def enable_matplotlib(self, gui=None):

  • """Enable interactive matplotlib and inline figure support.
  • This takes the following steps:
    1. select the appropriate eventloop and matplotlib backend
    1. set up matplotlib for interactive use with that backend
    1. configure formatters for inline figure display
    1. enable the selected gui eventloop
  • Parameters

  • gui : optional, string
  •  If given, dictates the choice of matplotlib GUI backend to use
    
  •  (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
    
  •  'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
    
  •  matplotlib (as dictated by the matplotlib build-time options plus the
    
  •  user's matplotlibrc configuration file).  Note that not all backends
    
  •  make sense in all contexts, for example a terminal ipython can't
    
  •  display figures inline.
    
  • """
  • from IPython.core import pylabtools as pt
  • gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
  • if gui != 'inline':
  •    # If we have our first gui selection, store it
    
  •    if self.pylab_gui_select is None:
    
  •        self.pylab_gui_select = gui
    
  •    # Otherwise if they are different
    
  •    elif gui != self.pylab_gui_select:
    
  •        print('Warning: Cannot change to a different GUI toolkit: %s.'
    
  •                ' Using %s instead.' % (gui, self.pylab_gui_select))
    
  •        gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
    
  • pt.activate_matplotlib(backend)
  • pt.configure_inline_support(self, backend)
  • Now we must activate the gui pylab wants to use, and fix %run to take

  • plot updates into account

  • self.enable_gui(gui)
  • self.magics_manager.registry['ExecutionMagics'].default_runner = \
  •    pt.mpl_runner(self.safe_execfile)
    
  • return gui, backend

+def enable_pylab(self, gui=None, import_all=True, welcome_message=False):

  • """Activate pylab support at runtime.
  • This turns on support for matplotlib, preloads into the interactive
  • namespace all of numpy and pylab, and configures IPython to correctly
  • interact with the GUI event loop. The GUI backend to be used can be
  • optionally selected with the optional gui argument.
  • This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
  • Parameters

  • gui : optional, string
  •  If given, dictates the choice of matplotlib GUI backend to use
    
  •  (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
    
  •  'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
    
  •  matplotlib (as dictated by the matplotlib build-time options plus the
    
  •  user's matplotlibrc configuration file).  Note that not all backends
    
  •  make sense in all contexts, for example a terminal ipython can't
    
  •  display figures inline.
    
  • import_all : optional, bool, default: True
  •  Whether to do `from numpy import *` and `from pylab import *`
    
  •  in addition to module imports.
    
  • welcome_message : deprecated
  •  This argument is ignored, no welcome message will be displayed.
    
  • """
  • from IPython.core.pylabtools import import_pylab
  • gui, backend = self.enable_matplotlib(gui)
  • We want to prevent the loading of pylab to pollute the user's

  • namespace as shown by the %who* magics, so we execute the activation

  • code in an empty namespace, and we update both user_ns and

  • user_ns_hidden with this information.

  • ns = {}
  • import_pylab(ns, import_all)
  • warn about clobbered names

  • ignored = {"builtins"}
  • both = set(ns).intersection(self.user_ns).difference(ignored)
  • clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
  • self.user_ns.update(ns)
  • self.user_ns_hidden.update(ns)
  • return gui, backend, clobbered

+#-------------------------------------------------------------------------
+# Utilities
+#-------------------------------------------------------------------------
+
+def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):

  • """Expand python variables in a string.
  • The depth argument indicates how many frames above the caller should
  • be walked to look for the local namespace where to expand variables.
  • The global namespace for expansion is always the user's interactive
  • namespace.
  • """
  • ns = self.user_ns.copy()
  • try:
  •    frame = sys._getframe(depth+1)
    
  • except ValueError:
  •    # This is thrown if there aren't that many frames on the stack,
    
  •    # e.g. if a script called run_line_magic() directly.
    
  •    pass
    
  • else:
  •    ns.update(frame.f_locals)
    
  • try:
  •    # We have to use .vformat() here, because 'self' is a valid and common
    
  •    # name, and expanding **ns for .format() would make it collide with
    
  •    # the 'self' argument of the method.
    
  •    cmd = formatter.vformat(cmd, args=[], kwargs=ns)
    
  • except Exception:
  •    # if formatter couldn't format, just let it go untransformed
    
  •    pass
    
  • return cmd

+def mktempfile(self, data=None, prefix='ipython_edit_'):

  • """Make a new tempfile and return its filename.
  • This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
  • but it registers the created filename internally so ipython cleans it up
  • at exit time.
  • Optional inputs:
  •  - data(None): if data is given, it gets written out to the temp file
    
  •    immediately, and the file is closed again."""
    
  • dirname = tempfile.mkdtemp(prefix=prefix)
  • self.tempdirs.append(dirname)
  • handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
  • os.close(handle) # On Windows, there can only be one open handle on a file
  • self.tempfiles.append(filename)
  • if data:
  •    tmp_file = open(filename,'w')
    
  •    tmp_file.write(data)
    
  •    tmp_file.close()
    
  • return filename

+@undoc
+def write(self,data):

  • """DEPRECATED: Write a string to the default output"""
  • warn('InteractiveShell.write() is deprecated, use sys.stdout instead',
  •     DeprecationWarning, stacklevel=2)
    
  • sys.stdout.write(data)

+@undoc
+def write_err(self,data):

  • """DEPRECATED: Write a string to the default error output"""
  • warn('InteractiveShell.write_err() is deprecated, use sys.stderr instead',
  •     DeprecationWarning, stacklevel=2)
    
  • sys.stderr.write(data)

+def ask_yes_no(self, prompt, default=None, interrupt=None):

  • if self.quiet:
  •    return True
    
  • return ask_yes_no(prompt,default,interrupt)

+def show_usage(self):

  • """Show a usage message"""
  • page.page(IPython.core.usage.interactive_usage)

+def extract_input_lines(self, range_str, raw=False):

  • """Return as a string a set of input history slices.
  • Parameters

  • range_str : string
  •    The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
    
  •    since this function is for use by magic functions which get their
    
  •    arguments as strings. The number before the / is the session
    
  •    number: ~n goes n back from the current session.
    
  • raw : bool, optional
  •    By default, the processed input is used.  If this is true, the raw
    
  •    input history is used instead.
    
  • Notes

  • Slices can be described with two notations:
    • N:M -> standard python form, means including items N...(M-1).
    • N-M -> include items N..M (closed endpoint).
  • """
  • lines = self.history_manager.get_range_by_str(range_str, raw=raw)
  • return "\n".join(x for _, _, x in lines)

+def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):

  • """Get a code string from history, file, url, or a string or macro.
  • This is mainly used by magic functions.
  • Parameters

  • target : str
  •  A string specifying code to retrieve. This will be tried respectively
    
  •  as: ranges of input history (see %history for syntax), url,
    
  •  corresponding .py file, filename, or an expression evaluating to a
    
  •  string or Macro in the user namespace.
    
  • raw : bool
  •  If true (default), retrieve raw history. Has no effect on the other
    
  •  retrieval mechanisms.
    
  • py_only : bool (default False)
  •  Only try to fetch python code, do not try alternative methods to decode file
    
  •  if unicode fails.
    
  • Returns

  • A string of code.
  • ValueError is raised if nothing is found, and TypeError if it evaluates
  • to an object of another type. In each case, .args[0] is a printable
  • message.
  • """
  • code = self.extract_input_lines(target, raw=raw) # Grab history
  • if code:
  •    return code
    
  • try:
  •    if target.startswith(('http://', 'https://')):
    
  •        return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
    
  • except UnicodeDecodeError:
  •    if not py_only :
    
  •        # Deferred import
    
  •        from urllib.request import urlopen
    
  •        response = urlopen(target)
    
  •        return response.read().decode('latin1')
    
  •    raise ValueError(("'%s' seem to be unreadable.") % target)
    
  • potential_target = [target]
  • try :
  •    potential_target.insert(0,get_py_filename(target))
    
  • except IOError:
  •    pass
    
  • for tgt in potential_target :
  •    if os.path.isfile(tgt):                        # Read file
    
  •        try :
    
  •            return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
    
  •        except UnicodeDecodeError :
    
  •            if not py_only :
    
  •                with io_open(tgt,'r', encoding='latin1') as f :
    
  •                    return f.read()
    
  •            raise ValueError(("'%s' seem to be unreadable.") % target)
    
  •    elif os.path.isdir(os.path.expanduser(tgt)):
    
  •        raise ValueError("'%s' is a directory, not a regular file." % target)
    
  • if search_ns:
  •    # Inspect namespace to load object source
    
  •    object_info = self.object_inspect(target, detail_level=1)
    
  •    if object_info['found'] and object_info['source']:
    
  •        return object_info['source']
    
  • try: # User namespace
  •    codeobj = eval(target, self.user_ns)
    
  • except Exception:
  •    raise ValueError(("'%s' was not found in history, as a file, url, "
    
  •                        "nor in the user namespace.") % target)
    
  • if isinstance(codeobj, str):
  •    return codeobj
    
  • elif isinstance(codeobj, Macro):
  •    return codeobj.value
    
  • raise TypeError("%s is neither a string nor a macro." % target,
  •                codeobj)
    

+#-------------------------------------------------------------------------
+# Things related to IPython exiting
+#-------------------------------------------------------------------------
+def atexit_operations(self):

  • """This will be executed at the time of exit.
  • Cleanup operations and saving of persistent data that is done
  • unconditionally by IPython should be performed here.
  • For things that may depend on startup flags or platform specifics (such
  • as having readline or not), register a separate atexit function in the
  • code that has the appropriate information, rather than trying to
  • clutter
  • """
  • Close the history session (this stores the end time and line count)

  • this must be before the tempfile cleanup, in case of temporary

  • history db

  • self.history_manager.end_session()
  • Cleanup all tempfiles and folders left around

  • for tfile in self.tempfiles:
  •    try:
    
  •        os.unlink(tfile)
    
  •    except OSError:
    
  •        pass
    
  • for tdir in self.tempdirs:
  •    try:
    
  •        os.rmdir(tdir)
    
  •    except OSError:
    
  •        pass
    
  • Clear all user namespaces to release all references cleanly.

  • self.reset(new_session=False)
  • Run user hooks

  • self.hooks.shutdown_hook()

+def cleanup(self):

  • self.restore_sys_module_state()

+# Overridden in terminal subclass to change prompts
+def switch_doctest_mode(self, mode):

  • pass
# Security Policy

## Supported Versions

Use this section to tell people about which versions of your project are
currently being supported with security updates.

| Version | Supported          |
| ------- | ------------------ |
| 5.1.x   | ✅ |
| 5.0.x   | ❌                |
| 4.0.x   | ✅ |
| < 4.0   | ❌                |

## Reporting a Vulnerability

Use this section to tell people how to report a vulnerability.

Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.
@Kinghat7977

Copy link
Copy Markdown

Lets give this a shot

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

3 participants