Uploaded Test files
|
@ -4,7 +4,7 @@
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="jdk" jdkName="Python 3.6" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 (Vehicle Anti-Theft Face Recognition System)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
|
@ -4,7 +4,7 @@ import math
|
||||||
import cv2
|
import cv2
|
||||||
|
|
||||||
|
|
||||||
label = "Feier_Zhang"
|
label = "Batuhan_Basoglu"
|
||||||
num_cap = 20
|
num_cap = 20
|
||||||
|
|
||||||
path = sys.path[0]+'/Facial_images/face_rec/train/'+label
|
path = sys.path[0]+'/Facial_images/face_rec/train/'+label
|
||||||
|
@ -16,7 +16,7 @@ if not folder:
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
|
|
||||||
|
|
||||||
cap = cv2.VideoCapture(1)
|
cap = cv2.VideoCapture(0)
|
||||||
c=0
|
c=0
|
||||||
while(c < num_cap):
|
while(c < num_cap):
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,7 @@ def face_recognition_inference(rec_type):
|
||||||
correct = 0
|
correct = 0
|
||||||
error = 0
|
error = 0
|
||||||
faceDetector = dlib.get_frontal_face_detector()
|
faceDetector = dlib.get_frontal_face_detector()
|
||||||
|
print(sys.path[0])
|
||||||
landmarkDetector = dlib.shape_predictor(sys.path[0]+'/Facial_models/shape_predictor_68_face_landmarks.dat')
|
landmarkDetector = dlib.shape_predictor(sys.path[0]+'/Facial_models/shape_predictor_68_face_landmarks.dat')
|
||||||
|
|
||||||
if (rec_type=='LBPH'):
|
if (rec_type=='LBPH'):
|
||||||
|
@ -179,7 +180,7 @@ def face_recognition_inference(rec_type):
|
||||||
faceRecognizer.read(sys.path[0]+'/Facial_models/face_rec_model.yml')
|
faceRecognizer.read(sys.path[0]+'/Facial_models/face_rec_model.yml')
|
||||||
labelsMap = np.load(sys.path[0]+'/Facial_models/labels_map.pkl', allow_pickle=True)
|
labelsMap = np.load(sys.path[0]+'/Facial_models/labels_map.pkl', allow_pickle=True)
|
||||||
|
|
||||||
cam = cv2.VideoCapture(1)
|
cam = cv2.VideoCapture(0)
|
||||||
|
|
||||||
while(True):
|
while(True):
|
||||||
#imagePath = testFiles[i]
|
#imagePath = testFiles[i]
|
||||||
|
@ -276,4 +277,3 @@ if __name__=="__main__":
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/0.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/1.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/10.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/11.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/12.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/13.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/14.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/15.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/16.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/17.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/18.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/19.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/2.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/3.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/4.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/5.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/6.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/7.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/8.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
Facial_images/face_rec/train/Batuhan_Basoglu/9.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
152
venv/Lib/site-packages/IPython/__init__.py
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
"""
|
||||||
|
IPython: tools for interactive and parallel computing in Python.
|
||||||
|
|
||||||
|
https://ipython.org
|
||||||
|
"""
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2008-2011, IPython Development Team.
|
||||||
|
# Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
|
||||||
|
# Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
|
||||||
|
# Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
|
||||||
|
#
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
#
|
||||||
|
# The full license is in the file COPYING.txt, distributed with this software.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Imports
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Setup everything
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Don't forget to also update setup.py when this changes!
|
||||||
|
if sys.version_info < (3, 6):
|
||||||
|
raise ImportError(
|
||||||
|
"""
|
||||||
|
IPython 7.10+ supports Python 3.6 and above.
|
||||||
|
When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
|
||||||
|
Python 3.3 and 3.4 were supported up to IPython 6.x.
|
||||||
|
Python 3.5 was supported with IPython 7.0 to 7.9.
|
||||||
|
|
||||||
|
See IPython `README.rst` file for more information:
|
||||||
|
|
||||||
|
https://github.com/ipython/ipython/blob/master/README.rst
|
||||||
|
|
||||||
|
""")
|
||||||
|
|
||||||
|
# Make it easy to import extensions - they are always directly on pythonpath.
|
||||||
|
# Therefore, non-IPython modules can be added to extensions directory.
|
||||||
|
# This should probably be in ipapp.py.
|
||||||
|
sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Setup the top level names
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from .core.getipython import get_ipython
|
||||||
|
from .core import release
|
||||||
|
from .core.application import Application
|
||||||
|
from .terminal.embed import embed
|
||||||
|
|
||||||
|
from .core.interactiveshell import InteractiveShell
|
||||||
|
from .testing import test
|
||||||
|
from .utils.sysinfo import sys_info
|
||||||
|
from .utils.frame import extract_module_locals
|
||||||
|
|
||||||
|
# Release data
|
||||||
|
__author__ = '%s <%s>' % (release.author, release.author_email)
|
||||||
|
__license__ = release.license
|
||||||
|
__version__ = release.version
|
||||||
|
version_info = release.version_info
|
||||||
|
|
||||||
|
def embed_kernel(module=None, local_ns=None, **kwargs):
|
||||||
|
"""Embed and start an IPython kernel in a given scope.
|
||||||
|
|
||||||
|
If you don't want the kernel to initialize the namespace
|
||||||
|
from the scope of the surrounding function,
|
||||||
|
and/or you want to load full IPython configuration,
|
||||||
|
you probably want `IPython.start_kernel()` instead.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
module : types.ModuleType, optional
|
||||||
|
The module to load into IPython globals (default: caller)
|
||||||
|
local_ns : dict, optional
|
||||||
|
The namespace to load into IPython user namespace (default: caller)
|
||||||
|
|
||||||
|
kwargs : various, optional
|
||||||
|
Further keyword args are relayed to the IPKernelApp constructor,
|
||||||
|
allowing configuration of the Kernel. Will only have an effect
|
||||||
|
on the first embed_kernel call for a given process.
|
||||||
|
"""
|
||||||
|
|
||||||
|
(caller_module, caller_locals) = extract_module_locals(1)
|
||||||
|
if module is None:
|
||||||
|
module = caller_module
|
||||||
|
if local_ns is None:
|
||||||
|
local_ns = caller_locals
|
||||||
|
|
||||||
|
# Only import .zmq when we really need it
|
||||||
|
from ipykernel.embed import embed_kernel as real_embed_kernel
|
||||||
|
real_embed_kernel(module=module, local_ns=local_ns, **kwargs)
|
||||||
|
|
||||||
|
def start_ipython(argv=None, **kwargs):
|
||||||
|
"""Launch a normal IPython instance (as opposed to embedded)
|
||||||
|
|
||||||
|
`IPython.embed()` puts a shell in a particular calling scope,
|
||||||
|
such as a function or method for debugging purposes,
|
||||||
|
which is often not desirable.
|
||||||
|
|
||||||
|
`start_ipython()` does full, regular IPython initialization,
|
||||||
|
including loading startup files, configuration, etc.
|
||||||
|
much of which is skipped by `embed()`.
|
||||||
|
|
||||||
|
This is a public API method, and will survive implementation changes.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
argv : list or None, optional
|
||||||
|
If unspecified or None, IPython will parse command-line options from sys.argv.
|
||||||
|
To prevent any command-line parsing, pass an empty list: `argv=[]`.
|
||||||
|
user_ns : dict, optional
|
||||||
|
specify this dictionary to initialize the IPython user namespace with particular values.
|
||||||
|
kwargs : various, optional
|
||||||
|
Any other kwargs will be passed to the Application constructor,
|
||||||
|
such as `config`.
|
||||||
|
"""
|
||||||
|
from IPython.terminal.ipapp import launch_new_instance
|
||||||
|
return launch_new_instance(argv=argv, **kwargs)
|
||||||
|
|
||||||
|
def start_kernel(argv=None, **kwargs):
|
||||||
|
"""Launch a normal IPython kernel instance (as opposed to embedded)
|
||||||
|
|
||||||
|
`IPython.embed_kernel()` puts a shell in a particular calling scope,
|
||||||
|
such as a function or method for debugging purposes,
|
||||||
|
which is often not desirable.
|
||||||
|
|
||||||
|
`start_kernel()` does full, regular IPython initialization,
|
||||||
|
including loading startup files, configuration, etc.
|
||||||
|
much of which is skipped by `embed()`.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
|
||||||
|
argv : list or None, optional
|
||||||
|
If unspecified or None, IPython will parse command-line options from sys.argv.
|
||||||
|
To prevent any command-line parsing, pass an empty list: `argv=[]`.
|
||||||
|
user_ns : dict, optional
|
||||||
|
specify this dictionary to initialize the IPython user namespace with particular values.
|
||||||
|
kwargs : various, optional
|
||||||
|
Any other kwargs will be passed to the Application constructor,
|
||||||
|
such as `config`.
|
||||||
|
"""
|
||||||
|
from IPython.kernel.zmq.kernelapp import launch_new_instance
|
||||||
|
return launch_new_instance(argv=argv, **kwargs)
|
14
venv/Lib/site-packages/IPython/__main__.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
"""Terminal-based IPython entry point.
|
||||||
|
"""
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2012, IPython Development Team.
|
||||||
|
#
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
#
|
||||||
|
# The full license is in the file COPYING.txt, distributed with this software.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from IPython import start_ipython
|
||||||
|
|
||||||
|
start_ipython()
|
BIN
venv/Lib/site-packages/IPython/__pycache__/config.cpython-36.pyc
Normal file
BIN
venv/Lib/site-packages/IPython/__pycache__/html.cpython-36.pyc
Normal file
BIN
venv/Lib/site-packages/IPython/__pycache__/paths.cpython-36.pyc
Normal file
BIN
venv/Lib/site-packages/IPython/__pycache__/qt.cpython-36.pyc
Normal file
19
venv/Lib/site-packages/IPython/config.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
"""
|
||||||
|
Shim to maintain backwards compatibility with old IPython.config imports.
|
||||||
|
"""
|
||||||
|
# Copyright (c) IPython Development Team.
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from warnings import warn
|
||||||
|
|
||||||
|
from .utils.shimmodule import ShimModule, ShimWarning
|
||||||
|
|
||||||
|
warn("The `IPython.config` package has been deprecated since IPython 4.0. "
|
||||||
|
"You should import from traitlets.config instead.", ShimWarning)
|
||||||
|
|
||||||
|
|
||||||
|
# Unconditionally insert the shim into sys.modules so that further import calls
|
||||||
|
# trigger the custom attribute access above
|
||||||
|
|
||||||
|
sys.modules['IPython.config'] = ShimModule(src='IPython.config', mirror='traitlets.config')
|
69
venv/Lib/site-packages/IPython/conftest.py
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import types
|
||||||
|
import sys
|
||||||
|
import builtins
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
import pathlib
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from .testing import tools
|
||||||
|
|
||||||
|
|
||||||
|
def get_ipython():
|
||||||
|
from .terminal.interactiveshell import TerminalInteractiveShell
|
||||||
|
if TerminalInteractiveShell._instance:
|
||||||
|
return TerminalInteractiveShell.instance()
|
||||||
|
|
||||||
|
config = tools.default_config()
|
||||||
|
config.TerminalInteractiveShell.simple_prompt = True
|
||||||
|
|
||||||
|
# Create and initialize our test-friendly IPython instance.
|
||||||
|
shell = TerminalInteractiveShell.instance(config=config)
|
||||||
|
return shell
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='session', autouse=True)
|
||||||
|
def work_path():
|
||||||
|
path = pathlib.Path("./tmp-ipython-pytest-profiledir")
|
||||||
|
os.environ["IPYTHONDIR"] = str(path.absolute())
|
||||||
|
if path.exists():
|
||||||
|
raise ValueError('IPython dir temporary path already exists ! Did previous test run exit successfully ?')
|
||||||
|
path.mkdir()
|
||||||
|
yield
|
||||||
|
shutil.rmtree(str(path.resolve()))
|
||||||
|
|
||||||
|
|
||||||
|
def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
|
||||||
|
if isinstance(strng, dict):
|
||||||
|
strng = strng.get("text/plain", "")
|
||||||
|
print(strng)
|
||||||
|
|
||||||
|
|
||||||
|
def xsys(self, cmd):
|
||||||
|
"""Replace the default system call with a capturing one for doctest.
|
||||||
|
"""
|
||||||
|
# We use getoutput, but we need to strip it because pexpect captures
|
||||||
|
# the trailing newline differently from commands.getoutput
|
||||||
|
print(self.getoutput(cmd, split=False, depth=1).rstrip(), end="", file=sys.stdout)
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
# for things to work correctly we would need this as a session fixture;
|
||||||
|
# unfortunately this will fail on some test that get executed as _collection_
|
||||||
|
# time (before the fixture run), in particular parametrized test that contain
|
||||||
|
# yields. so for now execute at import time.
|
||||||
|
#@pytest.fixture(autouse=True, scope='session')
|
||||||
|
def inject():
|
||||||
|
|
||||||
|
builtins.get_ipython = get_ipython
|
||||||
|
builtins._ip = get_ipython()
|
||||||
|
builtins.ip = get_ipython()
|
||||||
|
builtins.ip.system = types.MethodType(xsys, ip)
|
||||||
|
builtins.ip.builtin_trap.activate()
|
||||||
|
from .core import page
|
||||||
|
|
||||||
|
page.pager_page = nopage
|
||||||
|
# yield
|
||||||
|
|
||||||
|
|
||||||
|
inject()
|
12
venv/Lib/site-packages/IPython/consoleapp.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
"""
|
||||||
|
Shim to maintain backwards compatibility with old IPython.consoleapp imports.
|
||||||
|
"""
|
||||||
|
# Copyright (c) IPython Development Team.
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
from warnings import warn
|
||||||
|
|
||||||
|
warn("The `IPython.consoleapp` package has been deprecated since IPython 4.0."
|
||||||
|
"You should import from jupyter_client.consoleapp instead.", stacklevel=2)
|
||||||
|
|
||||||
|
from jupyter_client.consoleapp import *
|
0
venv/Lib/site-packages/IPython/core/__init__.py
Normal file
258
venv/Lib/site-packages/IPython/core/alias.py
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
"""
|
||||||
|
System command aliases.
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
|
||||||
|
* Fernando Perez
|
||||||
|
* Brian Granger
|
||||||
|
"""
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (C) 2008-2011 The IPython Development Team
|
||||||
|
#
|
||||||
|
# Distributed under the terms of the BSD License.
|
||||||
|
#
|
||||||
|
# The full license is in the file COPYING.txt, distributed with this software.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Imports
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from traitlets.config.configurable import Configurable
|
||||||
|
from .error import UsageError
|
||||||
|
|
||||||
|
from traitlets import List, Instance
|
||||||
|
from logging import error
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Utilities
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# This is used as the pattern for calls to split_user_input.
|
||||||
|
shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
|
||||||
|
|
||||||
|
def default_aliases():
|
||||||
|
"""Return list of shell aliases to auto-define.
|
||||||
|
"""
|
||||||
|
# Note: the aliases defined here should be safe to use on a kernel
|
||||||
|
# regardless of what frontend it is attached to. Frontends that use a
|
||||||
|
# kernel in-process can define additional aliases that will only work in
|
||||||
|
# their case. For example, things like 'less' or 'clear' that manipulate
|
||||||
|
# the terminal should NOT be declared here, as they will only work if the
|
||||||
|
# kernel is running inside a true terminal, and not over the network.
|
||||||
|
|
||||||
|
if os.name == 'posix':
|
||||||
|
default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
|
||||||
|
('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
|
||||||
|
('cat', 'cat'),
|
||||||
|
]
|
||||||
|
# Useful set of ls aliases. The GNU and BSD options are a little
|
||||||
|
# different, so we make aliases that provide as similar as possible
|
||||||
|
# behavior in ipython, by passing the right flags for each platform
|
||||||
|
if sys.platform.startswith('linux'):
|
||||||
|
ls_aliases = [('ls', 'ls -F --color'),
|
||||||
|
# long ls
|
||||||
|
('ll', 'ls -F -o --color'),
|
||||||
|
# ls normal files only
|
||||||
|
('lf', 'ls -F -o --color %l | grep ^-'),
|
||||||
|
# ls symbolic links
|
||||||
|
('lk', 'ls -F -o --color %l | grep ^l'),
|
||||||
|
# directories or links to directories,
|
||||||
|
('ldir', 'ls -F -o --color %l | grep /$'),
|
||||||
|
# things which are executable
|
||||||
|
('lx', 'ls -F -o --color %l | grep ^-..x'),
|
||||||
|
]
|
||||||
|
elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
|
||||||
|
# OpenBSD, NetBSD. The ls implementation on these platforms do not support
|
||||||
|
# the -G switch and lack the ability to use colorized output.
|
||||||
|
ls_aliases = [('ls', 'ls -F'),
|
||||||
|
# long ls
|
||||||
|
('ll', 'ls -F -l'),
|
||||||
|
# ls normal files only
|
||||||
|
('lf', 'ls -F -l %l | grep ^-'),
|
||||||
|
# ls symbolic links
|
||||||
|
('lk', 'ls -F -l %l | grep ^l'),
|
||||||
|
# directories or links to directories,
|
||||||
|
('ldir', 'ls -F -l %l | grep /$'),
|
||||||
|
# things which are executable
|
||||||
|
('lx', 'ls -F -l %l | grep ^-..x'),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
# BSD, OSX, etc.
|
||||||
|
ls_aliases = [('ls', 'ls -F -G'),
|
||||||
|
# long ls
|
||||||
|
('ll', 'ls -F -l -G'),
|
||||||
|
# ls normal files only
|
||||||
|
('lf', 'ls -F -l -G %l | grep ^-'),
|
||||||
|
# ls symbolic links
|
||||||
|
('lk', 'ls -F -l -G %l | grep ^l'),
|
||||||
|
# directories or links to directories,
|
||||||
|
('ldir', 'ls -F -G -l %l | grep /$'),
|
||||||
|
# things which are executable
|
||||||
|
('lx', 'ls -F -l -G %l | grep ^-..x'),
|
||||||
|
]
|
||||||
|
default_aliases = default_aliases + ls_aliases
|
||||||
|
elif os.name in ['nt', 'dos']:
|
||||||
|
default_aliases = [('ls', 'dir /on'),
|
||||||
|
('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
|
||||||
|
('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
|
||||||
|
('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
default_aliases = []
|
||||||
|
|
||||||
|
return default_aliases
|
||||||
|
|
||||||
|
|
||||||
|
class AliasError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidAliasError(AliasError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Alias(object):
|
||||||
|
"""Callable object storing the details of one alias.
|
||||||
|
|
||||||
|
Instances are registered as magic functions to allow use of aliases.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Prepare blacklist
|
||||||
|
blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
|
||||||
|
|
||||||
|
def __init__(self, shell, name, cmd):
|
||||||
|
self.shell = shell
|
||||||
|
self.name = name
|
||||||
|
self.cmd = cmd
|
||||||
|
self.__doc__ = "Alias for `!{}`".format(cmd)
|
||||||
|
self.nargs = self.validate()
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
"""Validate the alias, and return the number of arguments."""
|
||||||
|
if self.name in self.blacklist:
|
||||||
|
raise InvalidAliasError("The name %s can't be aliased "
|
||||||
|
"because it is a keyword or builtin." % self.name)
|
||||||
|
try:
|
||||||
|
caller = self.shell.magics_manager.magics['line'][self.name]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if not isinstance(caller, Alias):
|
||||||
|
raise InvalidAliasError("The name %s can't be aliased "
|
||||||
|
"because it is another magic command." % self.name)
|
||||||
|
|
||||||
|
if not (isinstance(self.cmd, str)):
|
||||||
|
raise InvalidAliasError("An alias command must be a string, "
|
||||||
|
"got: %r" % self.cmd)
|
||||||
|
|
||||||
|
nargs = self.cmd.count('%s') - self.cmd.count('%%s')
|
||||||
|
|
||||||
|
if (nargs > 0) and (self.cmd.find('%l') >= 0):
|
||||||
|
raise InvalidAliasError('The %s and %l specifiers are mutually '
|
||||||
|
'exclusive in alias definitions.')
|
||||||
|
|
||||||
|
return nargs
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<alias {} for {!r}>".format(self.name, self.cmd)
|
||||||
|
|
||||||
|
def __call__(self, rest=''):
|
||||||
|
cmd = self.cmd
|
||||||
|
nargs = self.nargs
|
||||||
|
# Expand the %l special to be the user's input line
|
||||||
|
if cmd.find('%l') >= 0:
|
||||||
|
cmd = cmd.replace('%l', rest)
|
||||||
|
rest = ''
|
||||||
|
|
||||||
|
if nargs==0:
|
||||||
|
if cmd.find('%%s') >= 1:
|
||||||
|
cmd = cmd.replace('%%s', '%s')
|
||||||
|
# Simple, argument-less aliases
|
||||||
|
cmd = '%s %s' % (cmd, rest)
|
||||||
|
else:
|
||||||
|
# Handle aliases with positional arguments
|
||||||
|
args = rest.split(None, nargs)
|
||||||
|
if len(args) < nargs:
|
||||||
|
raise UsageError('Alias <%s> requires %s arguments, %s given.' %
|
||||||
|
(self.name, nargs, len(args)))
|
||||||
|
cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
|
||||||
|
|
||||||
|
self.shell.system(cmd)
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Main AliasManager class
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class AliasManager(Configurable):
|
||||||
|
|
||||||
|
default_aliases = List(default_aliases()).tag(config=True)
|
||||||
|
user_aliases = List(default_value=[]).tag(config=True)
|
||||||
|
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
|
||||||
|
|
||||||
|
def __init__(self, shell=None, **kwargs):
|
||||||
|
super(AliasManager, self).__init__(shell=shell, **kwargs)
|
||||||
|
# For convenient access
|
||||||
|
self.linemagics = self.shell.magics_manager.magics['line']
|
||||||
|
self.init_aliases()
|
||||||
|
|
||||||
|
def init_aliases(self):
|
||||||
|
# Load default & user aliases
|
||||||
|
for name, cmd in self.default_aliases + self.user_aliases:
|
||||||
|
if cmd.startswith('ls ') and self.shell.colors == 'NoColor':
|
||||||
|
cmd = cmd.replace(' --color', '')
|
||||||
|
self.soft_define_alias(name, cmd)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def aliases(self):
|
||||||
|
return [(n, func.cmd) for (n, func) in self.linemagics.items()
|
||||||
|
if isinstance(func, Alias)]
|
||||||
|
|
||||||
|
def soft_define_alias(self, name, cmd):
|
||||||
|
"""Define an alias, but don't raise on an AliasError."""
|
||||||
|
try:
|
||||||
|
self.define_alias(name, cmd)
|
||||||
|
except AliasError as e:
|
||||||
|
error("Invalid alias: %s" % e)
|
||||||
|
|
||||||
|
def define_alias(self, name, cmd):
|
||||||
|
"""Define a new alias after validating it.
|
||||||
|
|
||||||
|
This will raise an :exc:`AliasError` if there are validation
|
||||||
|
problems.
|
||||||
|
"""
|
||||||
|
caller = Alias(shell=self.shell, name=name, cmd=cmd)
|
||||||
|
self.shell.magics_manager.register_function(caller, magic_kind='line',
|
||||||
|
magic_name=name)
|
||||||
|
|
||||||
|
def get_alias(self, name):
|
||||||
|
"""Return an alias, or None if no alias by that name exists."""
|
||||||
|
aname = self.linemagics.get(name, None)
|
||||||
|
return aname if isinstance(aname, Alias) else None
|
||||||
|
|
||||||
|
def is_alias(self, name):
|
||||||
|
"""Return whether or not a given name has been defined as an alias"""
|
||||||
|
return self.get_alias(name) is not None
|
||||||
|
|
||||||
|
def undefine_alias(self, name):
|
||||||
|
if self.is_alias(name):
|
||||||
|
del self.linemagics[name]
|
||||||
|
else:
|
||||||
|
raise ValueError('%s is not an alias' % name)
|
||||||
|
|
||||||
|
def clear_aliases(self):
|
||||||
|
for name, cmd in self.aliases:
|
||||||
|
self.undefine_alias(name)
|
||||||
|
|
||||||
|
def retrieve_alias(self, name):
|
||||||
|
"""Retrieve the command to which an alias expands."""
|
||||||
|
caller = self.get_alias(name)
|
||||||
|
if caller:
|
||||||
|
return caller.cmd
|
||||||
|
else:
|
||||||
|
raise ValueError('%s is not an alias' % name)
|
462
venv/Lib/site-packages/IPython/core/application.py
Normal file
|
@ -0,0 +1,462 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
"""
|
||||||
|
An application for IPython.
|
||||||
|
|
||||||
|
All top-level applications should use the classes in this module for
|
||||||
|
handling configuration and creating configurables.
|
||||||
|
|
||||||
|
The job of an :class:`Application` is to create the master configuration
|
||||||
|
object and then create the configurable objects, passing the config to them.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Copyright (c) IPython Development Team.
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
|
import atexit
|
||||||
|
from copy import deepcopy
|
||||||
|
import glob
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from traitlets.config.application import Application, catch_config_error
|
||||||
|
from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
|
||||||
|
from IPython.core import release, crashhandler
|
||||||
|
from IPython.core.profiledir import ProfileDir, ProfileDirError
|
||||||
|
from IPython.paths import get_ipython_dir, get_ipython_package_dir
|
||||||
|
from IPython.utils.path import ensure_dir_exists
|
||||||
|
from traitlets import (
|
||||||
|
List, Unicode, Type, Bool, Set, Instance, Undefined,
|
||||||
|
default, observe,
|
||||||
|
)
|
||||||
|
|
||||||
|
if os.name == 'nt':
|
||||||
|
programdata = os.environ.get('PROGRAMDATA', None)
|
||||||
|
if programdata:
|
||||||
|
SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
|
||||||
|
else: # PROGRAMDATA is not defined by default on XP.
|
||||||
|
SYSTEM_CONFIG_DIRS = []
|
||||||
|
else:
|
||||||
|
SYSTEM_CONFIG_DIRS = [
|
||||||
|
"/usr/local/etc/ipython",
|
||||||
|
"/etc/ipython",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
ENV_CONFIG_DIRS = []
|
||||||
|
_env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
|
||||||
|
if _env_config_dir not in SYSTEM_CONFIG_DIRS:
|
||||||
|
# only add ENV_CONFIG if sys.prefix is not already included
|
||||||
|
ENV_CONFIG_DIRS.append(_env_config_dir)
|
||||||
|
|
||||||
|
|
||||||
|
_envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
|
||||||
|
if _envvar in {None, ''}:
|
||||||
|
IPYTHON_SUPPRESS_CONFIG_ERRORS = None
|
||||||
|
else:
|
||||||
|
if _envvar.lower() in {'1','true'}:
|
||||||
|
IPYTHON_SUPPRESS_CONFIG_ERRORS = True
|
||||||
|
elif _envvar.lower() in {'0','false'} :
|
||||||
|
IPYTHON_SUPPRESS_CONFIG_ERRORS = False
|
||||||
|
else:
|
||||||
|
sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
|
||||||
|
|
||||||
|
# aliases and flags
|
||||||
|
|
||||||
|
base_aliases = {
|
||||||
|
'profile-dir' : 'ProfileDir.location',
|
||||||
|
'profile' : 'BaseIPythonApplication.profile',
|
||||||
|
'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
|
||||||
|
'log-level' : 'Application.log_level',
|
||||||
|
'config' : 'BaseIPythonApplication.extra_config_file',
|
||||||
|
}
|
||||||
|
|
||||||
|
base_flags = dict(
|
||||||
|
debug = ({'Application' : {'log_level' : logging.DEBUG}},
|
||||||
|
"set log level to logging.DEBUG (maximize logging output)"),
|
||||||
|
quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
|
||||||
|
"set log level to logging.CRITICAL (minimize logging output)"),
|
||||||
|
init = ({'BaseIPythonApplication' : {
|
||||||
|
'copy_config_files' : True,
|
||||||
|
'auto_create' : True}
|
||||||
|
}, """Initialize profile with default config files. This is equivalent
|
||||||
|
to running `ipython profile create <profile>` prior to startup.
|
||||||
|
""")
|
||||||
|
)
|
||||||
|
|
||||||
|
class ProfileAwareConfigLoader(PyFileConfigLoader):
|
||||||
|
"""A Python file config loader that is aware of IPython profiles."""
|
||||||
|
def load_subconfig(self, fname, path=None, profile=None):
|
||||||
|
if profile is not None:
|
||||||
|
try:
|
||||||
|
profile_dir = ProfileDir.find_profile_dir_by_name(
|
||||||
|
get_ipython_dir(),
|
||||||
|
profile,
|
||||||
|
)
|
||||||
|
except ProfileDirError:
|
||||||
|
return
|
||||||
|
path = profile_dir.location
|
||||||
|
return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
|
||||||
|
|
||||||
|
class BaseIPythonApplication(Application):
|
||||||
|
|
||||||
|
name = u'ipython'
|
||||||
|
description = Unicode(u'IPython: an enhanced interactive Python shell.')
|
||||||
|
version = Unicode(release.version)
|
||||||
|
|
||||||
|
aliases = base_aliases
|
||||||
|
flags = base_flags
|
||||||
|
classes = List([ProfileDir])
|
||||||
|
|
||||||
|
# enable `load_subconfig('cfg.py', profile='name')`
|
||||||
|
python_config_loader_class = ProfileAwareConfigLoader
|
||||||
|
|
||||||
|
# Track whether the config_file has changed,
|
||||||
|
# because some logic happens only if we aren't using the default.
|
||||||
|
config_file_specified = Set()
|
||||||
|
|
||||||
|
config_file_name = Unicode()
|
||||||
|
@default('config_file_name')
|
||||||
|
def _config_file_name_default(self):
|
||||||
|
return self.name.replace('-','_') + u'_config.py'
|
||||||
|
@observe('config_file_name')
|
||||||
|
def _config_file_name_changed(self, change):
|
||||||
|
if change['new'] != change['old']:
|
||||||
|
self.config_file_specified.add(change['new'])
|
||||||
|
|
||||||
|
# The directory that contains IPython's builtin profiles.
|
||||||
|
builtin_profile_dir = Unicode(
|
||||||
|
os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
|
||||||
|
)
|
||||||
|
|
||||||
|
config_file_paths = List(Unicode())
|
||||||
|
@default('config_file_paths')
|
||||||
|
def _config_file_paths_default(self):
|
||||||
|
return [os.getcwd()]
|
||||||
|
|
||||||
|
extra_config_file = Unicode(
|
||||||
|
help="""Path to an extra config file to load.
|
||||||
|
|
||||||
|
If specified, load this config file in addition to any other IPython config.
|
||||||
|
""").tag(config=True)
|
||||||
|
@observe('extra_config_file')
|
||||||
|
def _extra_config_file_changed(self, change):
|
||||||
|
old = change['old']
|
||||||
|
new = change['new']
|
||||||
|
try:
|
||||||
|
self.config_files.remove(old)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
self.config_file_specified.add(new)
|
||||||
|
self.config_files.append(new)
|
||||||
|
|
||||||
|
profile = Unicode(u'default',
|
||||||
|
help="""The IPython profile to use."""
|
||||||
|
).tag(config=True)
|
||||||
|
|
||||||
|
@observe('profile')
|
||||||
|
def _profile_changed(self, change):
|
||||||
|
self.builtin_profile_dir = os.path.join(
|
||||||
|
get_ipython_package_dir(), u'config', u'profile', change['new']
|
||||||
|
)
|
||||||
|
|
||||||
|
ipython_dir = Unicode(
|
||||||
|
help="""
|
||||||
|
The name of the IPython directory. This directory is used for logging
|
||||||
|
configuration (through profiles), history storage, etc. The default
|
||||||
|
is usually $HOME/.ipython. This option can also be specified through
|
||||||
|
the environment variable IPYTHONDIR.
|
||||||
|
"""
|
||||||
|
).tag(config=True)
|
||||||
|
@default('ipython_dir')
|
||||||
|
def _ipython_dir_default(self):
|
||||||
|
d = get_ipython_dir()
|
||||||
|
self._ipython_dir_changed({
|
||||||
|
'name': 'ipython_dir',
|
||||||
|
'old': d,
|
||||||
|
'new': d,
|
||||||
|
})
|
||||||
|
return d
|
||||||
|
|
||||||
|
_in_init_profile_dir = False
|
||||||
|
profile_dir = Instance(ProfileDir, allow_none=True)
|
||||||
|
@default('profile_dir')
|
||||||
|
def _profile_dir_default(self):
|
||||||
|
# avoid recursion
|
||||||
|
if self._in_init_profile_dir:
|
||||||
|
return
|
||||||
|
# profile_dir requested early, force initialization
|
||||||
|
self.init_profile_dir()
|
||||||
|
return self.profile_dir
|
||||||
|
|
||||||
|
overwrite = Bool(False,
|
||||||
|
help="""Whether to overwrite existing config files when copying"""
|
||||||
|
).tag(config=True)
|
||||||
|
auto_create = Bool(False,
|
||||||
|
help="""Whether to create profile dir if it doesn't exist"""
|
||||||
|
).tag(config=True)
|
||||||
|
|
||||||
|
config_files = List(Unicode())
|
||||||
|
@default('config_files')
|
||||||
|
def _config_files_default(self):
|
||||||
|
return [self.config_file_name]
|
||||||
|
|
||||||
|
copy_config_files = Bool(False,
|
||||||
|
help="""Whether to install the default config files into the profile dir.
|
||||||
|
If a new profile is being created, and IPython contains config files for that
|
||||||
|
profile, then they will be staged into the new directory. Otherwise,
|
||||||
|
default config files will be automatically generated.
|
||||||
|
""").tag(config=True)
|
||||||
|
|
||||||
|
verbose_crash = Bool(False,
|
||||||
|
help="""Create a massive crash report when IPython encounters what may be an
|
||||||
|
internal error. The default is to append a short message to the
|
||||||
|
usual traceback""").tag(config=True)
|
||||||
|
|
||||||
|
# The class to use as the crash handler.
|
||||||
|
crash_handler_class = Type(crashhandler.CrashHandler)
|
||||||
|
|
||||||
|
@catch_config_error
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(BaseIPythonApplication, self).__init__(**kwargs)
|
||||||
|
# ensure current working directory exists
|
||||||
|
try:
|
||||||
|
os.getcwd()
|
||||||
|
except:
|
||||||
|
# exit if cwd doesn't exist
|
||||||
|
self.log.error("Current working directory doesn't exist.")
|
||||||
|
self.exit(1)
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Various stages of Application creation
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
deprecated_subcommands = {}
|
||||||
|
|
||||||
|
def initialize_subcommand(self, subc, argv=None):
|
||||||
|
if subc in self.deprecated_subcommands:
|
||||||
|
self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
|
||||||
|
"in future versions.".format(sub=subc))
|
||||||
|
self.log.warning("You likely want to use `jupyter {sub}` in the "
|
||||||
|
"future".format(sub=subc))
|
||||||
|
return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
|
||||||
|
|
||||||
|
def init_crash_handler(self):
|
||||||
|
"""Create a crash handler, typically setting sys.excepthook to it."""
|
||||||
|
self.crash_handler = self.crash_handler_class(self)
|
||||||
|
sys.excepthook = self.excepthook
|
||||||
|
def unset_crashhandler():
|
||||||
|
sys.excepthook = sys.__excepthook__
|
||||||
|
atexit.register(unset_crashhandler)
|
||||||
|
|
||||||
|
def excepthook(self, etype, evalue, tb):
|
||||||
|
"""this is sys.excepthook after init_crashhandler
|
||||||
|
|
||||||
|
set self.verbose_crash=True to use our full crashhandler, instead of
|
||||||
|
a regular traceback with a short message (crash_handler_lite)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.verbose_crash:
|
||||||
|
return self.crash_handler(etype, evalue, tb)
|
||||||
|
else:
|
||||||
|
return crashhandler.crash_handler_lite(etype, evalue, tb)
|
||||||
|
|
||||||
|
@observe('ipython_dir')
|
||||||
|
def _ipython_dir_changed(self, change):
|
||||||
|
old = change['old']
|
||||||
|
new = change['new']
|
||||||
|
if old is not Undefined:
|
||||||
|
str_old = os.path.abspath(old)
|
||||||
|
if str_old in sys.path:
|
||||||
|
sys.path.remove(str_old)
|
||||||
|
str_path = os.path.abspath(new)
|
||||||
|
sys.path.append(str_path)
|
||||||
|
ensure_dir_exists(new)
|
||||||
|
readme = os.path.join(new, 'README')
|
||||||
|
readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
|
||||||
|
if not os.path.exists(readme) and os.path.exists(readme_src):
|
||||||
|
shutil.copy(readme_src, readme)
|
||||||
|
for d in ('extensions', 'nbextensions'):
|
||||||
|
path = os.path.join(new, d)
|
||||||
|
try:
|
||||||
|
ensure_dir_exists(path)
|
||||||
|
except OSError as e:
|
||||||
|
# this will not be EEXIST
|
||||||
|
self.log.error("couldn't create path %s: %s", path, e)
|
||||||
|
self.log.debug("IPYTHONDIR set to: %s" % new)
|
||||||
|
|
||||||
|
def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
|
||||||
|
"""Load the config file.
|
||||||
|
|
||||||
|
By default, errors in loading config are handled, and a warning
|
||||||
|
printed on screen. For testing, the suppress_errors option is set
|
||||||
|
to False, so errors will make tests fail.
|
||||||
|
|
||||||
|
`suppress_errors` default value is to be `None` in which case the
|
||||||
|
behavior default to the one of `traitlets.Application`.
|
||||||
|
|
||||||
|
The default value can be set :
|
||||||
|
- to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
|
||||||
|
- to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
|
||||||
|
- to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
|
||||||
|
|
||||||
|
Any other value are invalid, and will make IPython exit with a non-zero return code.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
self.log.debug("Searching path %s for config files", self.config_file_paths)
|
||||||
|
base_config = 'ipython_config.py'
|
||||||
|
self.log.debug("Attempting to load config file: %s" %
|
||||||
|
base_config)
|
||||||
|
try:
|
||||||
|
if suppress_errors is not None:
|
||||||
|
old_value = Application.raise_config_file_errors
|
||||||
|
Application.raise_config_file_errors = not suppress_errors;
|
||||||
|
Application.load_config_file(
|
||||||
|
self,
|
||||||
|
base_config,
|
||||||
|
path=self.config_file_paths
|
||||||
|
)
|
||||||
|
except ConfigFileNotFound:
|
||||||
|
# ignore errors loading parent
|
||||||
|
self.log.debug("Config file %s not found", base_config)
|
||||||
|
pass
|
||||||
|
if suppress_errors is not None:
|
||||||
|
Application.raise_config_file_errors = old_value
|
||||||
|
|
||||||
|
for config_file_name in self.config_files:
|
||||||
|
if not config_file_name or config_file_name == base_config:
|
||||||
|
continue
|
||||||
|
self.log.debug("Attempting to load config file: %s" %
|
||||||
|
self.config_file_name)
|
||||||
|
try:
|
||||||
|
Application.load_config_file(
|
||||||
|
self,
|
||||||
|
config_file_name,
|
||||||
|
path=self.config_file_paths
|
||||||
|
)
|
||||||
|
except ConfigFileNotFound:
|
||||||
|
# Only warn if the default config file was NOT being used.
|
||||||
|
if config_file_name in self.config_file_specified:
|
||||||
|
msg = self.log.warning
|
||||||
|
else:
|
||||||
|
msg = self.log.debug
|
||||||
|
msg("Config file not found, skipping: %s", config_file_name)
|
||||||
|
except Exception:
|
||||||
|
# For testing purposes.
|
||||||
|
if not suppress_errors:
|
||||||
|
raise
|
||||||
|
self.log.warning("Error loading config file: %s" %
|
||||||
|
self.config_file_name, exc_info=True)
|
||||||
|
|
||||||
|
def init_profile_dir(self):
|
||||||
|
"""initialize the profile dir"""
|
||||||
|
self._in_init_profile_dir = True
|
||||||
|
if self.profile_dir is not None:
|
||||||
|
# already ran
|
||||||
|
return
|
||||||
|
if 'ProfileDir.location' not in self.config:
|
||||||
|
# location not specified, find by profile name
|
||||||
|
try:
|
||||||
|
p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
|
||||||
|
except ProfileDirError:
|
||||||
|
# not found, maybe create it (always create default profile)
|
||||||
|
if self.auto_create or self.profile == 'default':
|
||||||
|
try:
|
||||||
|
p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
|
||||||
|
except ProfileDirError:
|
||||||
|
self.log.fatal("Could not create profile: %r"%self.profile)
|
||||||
|
self.exit(1)
|
||||||
|
else:
|
||||||
|
self.log.info("Created profile dir: %r"%p.location)
|
||||||
|
else:
|
||||||
|
self.log.fatal("Profile %r not found."%self.profile)
|
||||||
|
self.exit(1)
|
||||||
|
else:
|
||||||
|
self.log.debug("Using existing profile dir: %r"%p.location)
|
||||||
|
else:
|
||||||
|
location = self.config.ProfileDir.location
|
||||||
|
# location is fully specified
|
||||||
|
try:
|
||||||
|
p = ProfileDir.find_profile_dir(location, self.config)
|
||||||
|
except ProfileDirError:
|
||||||
|
# not found, maybe create it
|
||||||
|
if self.auto_create:
|
||||||
|
try:
|
||||||
|
p = ProfileDir.create_profile_dir(location, self.config)
|
||||||
|
except ProfileDirError:
|
||||||
|
self.log.fatal("Could not create profile directory: %r"%location)
|
||||||
|
self.exit(1)
|
||||||
|
else:
|
||||||
|
self.log.debug("Creating new profile dir: %r"%location)
|
||||||
|
else:
|
||||||
|
self.log.fatal("Profile directory %r not found."%location)
|
||||||
|
self.exit(1)
|
||||||
|
else:
|
||||||
|
self.log.info("Using existing profile dir: %r"%location)
|
||||||
|
# if profile_dir is specified explicitly, set profile name
|
||||||
|
dir_name = os.path.basename(p.location)
|
||||||
|
if dir_name.startswith('profile_'):
|
||||||
|
self.profile = dir_name[8:]
|
||||||
|
|
||||||
|
self.profile_dir = p
|
||||||
|
self.config_file_paths.append(p.location)
|
||||||
|
self._in_init_profile_dir = False
|
||||||
|
|
||||||
|
def init_config_files(self):
|
||||||
|
"""[optionally] copy default config files into profile dir."""
|
||||||
|
self.config_file_paths.extend(ENV_CONFIG_DIRS)
|
||||||
|
self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
|
||||||
|
# copy config files
|
||||||
|
path = self.builtin_profile_dir
|
||||||
|
if self.copy_config_files:
|
||||||
|
src = self.profile
|
||||||
|
|
||||||
|
cfg = self.config_file_name
|
||||||
|
if path and os.path.exists(os.path.join(path, cfg)):
|
||||||
|
self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
|
||||||
|
cfg, src, self.profile_dir.location, self.overwrite)
|
||||||
|
)
|
||||||
|
self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
|
||||||
|
else:
|
||||||
|
self.stage_default_config_file()
|
||||||
|
else:
|
||||||
|
# Still stage *bundled* config files, but not generated ones
|
||||||
|
# This is necessary for `ipython profile=sympy` to load the profile
|
||||||
|
# on the first go
|
||||||
|
files = glob.glob(os.path.join(path, '*.py'))
|
||||||
|
for fullpath in files:
|
||||||
|
cfg = os.path.basename(fullpath)
|
||||||
|
if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
|
||||||
|
# file was copied
|
||||||
|
self.log.warning("Staging bundled %s from %s into %r"%(
|
||||||
|
cfg, self.profile, self.profile_dir.location)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def stage_default_config_file(self):
|
||||||
|
"""auto generate default config file, and stage it into the profile."""
|
||||||
|
s = self.generate_config_file()
|
||||||
|
fname = os.path.join(self.profile_dir.location, self.config_file_name)
|
||||||
|
if self.overwrite or not os.path.exists(fname):
|
||||||
|
self.log.warning("Generating default config file: %r"%(fname))
|
||||||
|
with open(fname, 'w') as f:
|
||||||
|
f.write(s)
|
||||||
|
|
||||||
|
@catch_config_error
|
||||||
|
def initialize(self, argv=None):
|
||||||
|
# don't hook up crash handler before parsing command-line
|
||||||
|
self.parse_command_line(argv)
|
||||||
|
self.init_crash_handler()
|
||||||
|
if self.subapp is not None:
|
||||||
|
# stop here if subapp is taking over
|
||||||
|
return
|
||||||
|
# save a copy of CLI config to re-load after config files
|
||||||
|
# so that it has highest priority
|
||||||
|
cl_config = deepcopy(self.config)
|
||||||
|
self.init_profile_dir()
|
||||||
|
self.init_config_files()
|
||||||
|
self.load_config_file()
|
||||||
|
# enforce cl-opts override configfile opts:
|
||||||
|
self.update_config(cl_config)
|
173
venv/Lib/site-packages/IPython/core/async_helpers.py
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
"""
|
||||||
|
Async helper function that are invalid syntax on Python 3.5 and below.
|
||||||
|
|
||||||
|
This code is best effort, and may have edge cases not behaving as expected. In
|
||||||
|
particular it contain a number of heuristics to detect whether code is
|
||||||
|
effectively async and need to run in an event loop or not.
|
||||||
|
|
||||||
|
Some constructs (like top-level `return`, or `yield`) are taken care of
|
||||||
|
explicitly to actually raise a SyntaxError and stay as close as possible to
|
||||||
|
Python semantics.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import sys
|
||||||
|
import inspect
|
||||||
|
from textwrap import dedent, indent
|
||||||
|
|
||||||
|
|
||||||
|
class _AsyncIORunner:
|
||||||
|
|
||||||
|
def __call__(self, coro):
|
||||||
|
"""
|
||||||
|
Handler for asyncio autoawait
|
||||||
|
"""
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
return asyncio.get_event_loop().run_until_complete(coro)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return 'asyncio'
|
||||||
|
|
||||||
|
_asyncio_runner = _AsyncIORunner()
|
||||||
|
|
||||||
|
|
||||||
|
def _curio_runner(coroutine):
|
||||||
|
"""
|
||||||
|
handler for curio autoawait
|
||||||
|
"""
|
||||||
|
import curio
|
||||||
|
|
||||||
|
return curio.run(coroutine)
|
||||||
|
|
||||||
|
|
||||||
|
def _trio_runner(async_fn):
|
||||||
|
import trio
|
||||||
|
|
||||||
|
async def loc(coro):
|
||||||
|
"""
|
||||||
|
We need the dummy no-op async def to protect from
|
||||||
|
trio's internal. See https://github.com/python-trio/trio/issues/89
|
||||||
|
"""
|
||||||
|
return await coro
|
||||||
|
|
||||||
|
return trio.run(loc, async_fn)
|
||||||
|
|
||||||
|
|
||||||
|
def _pseudo_sync_runner(coro):
|
||||||
|
"""
|
||||||
|
A runner that does not really allow async execution, and just advance the coroutine.
|
||||||
|
|
||||||
|
See discussion in https://github.com/python-trio/trio/issues/608,
|
||||||
|
|
||||||
|
Credit to Nathaniel Smith
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
coro.send(None)
|
||||||
|
except StopIteration as exc:
|
||||||
|
return exc.value
|
||||||
|
else:
|
||||||
|
# TODO: do not raise but return an execution result with the right info.
|
||||||
|
raise RuntimeError(
|
||||||
|
"{coro_name!r} needs a real async loop".format(coro_name=coro.__name__)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _asyncify(code: str) -> str:
|
||||||
|
"""wrap code in async def definition.
|
||||||
|
|
||||||
|
And setup a bit of context to run it later.
|
||||||
|
"""
|
||||||
|
res = dedent(
|
||||||
|
"""
|
||||||
|
async def __wrapper__():
|
||||||
|
try:
|
||||||
|
{usercode}
|
||||||
|
finally:
|
||||||
|
locals()
|
||||||
|
"""
|
||||||
|
).format(usercode=indent(code, " " * 8))
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
class _AsyncSyntaxErrorVisitor(ast.NodeVisitor):
|
||||||
|
"""
|
||||||
|
Find syntax errors that would be an error in an async repl, but because
|
||||||
|
the implementation involves wrapping the repl in an async function, it
|
||||||
|
is erroneously allowed (e.g. yield or return at the top level)
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
if sys.version_info >= (3,8):
|
||||||
|
raise ValueError('DEPRECATED in Python 3.8+')
|
||||||
|
self.depth = 0
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def generic_visit(self, node):
|
||||||
|
func_types = (ast.FunctionDef, ast.AsyncFunctionDef)
|
||||||
|
invalid_types_by_depth = {
|
||||||
|
0: (ast.Return, ast.Yield, ast.YieldFrom),
|
||||||
|
1: (ast.Nonlocal,)
|
||||||
|
}
|
||||||
|
|
||||||
|
should_traverse = self.depth < max(invalid_types_by_depth.keys())
|
||||||
|
if isinstance(node, func_types) and should_traverse:
|
||||||
|
self.depth += 1
|
||||||
|
super().generic_visit(node)
|
||||||
|
self.depth -= 1
|
||||||
|
elif isinstance(node, invalid_types_by_depth[self.depth]):
|
||||||
|
raise SyntaxError()
|
||||||
|
else:
|
||||||
|
super().generic_visit(node)
|
||||||
|
|
||||||
|
|
||||||
|
def _async_parse_cell(cell: str) -> ast.AST:
|
||||||
|
"""
|
||||||
|
This is a compatibility shim for pre-3.7 when async outside of a function
|
||||||
|
is a syntax error at the parse stage.
|
||||||
|
|
||||||
|
It will return an abstract syntax tree parsed as if async and await outside
|
||||||
|
of a function were not a syntax error.
|
||||||
|
"""
|
||||||
|
if sys.version_info < (3, 7):
|
||||||
|
# Prior to 3.7 you need to asyncify before parse
|
||||||
|
wrapped_parse_tree = ast.parse(_asyncify(cell))
|
||||||
|
return wrapped_parse_tree.body[0].body[0]
|
||||||
|
else:
|
||||||
|
return ast.parse(cell)
|
||||||
|
|
||||||
|
|
||||||
|
def _should_be_async(cell: str) -> bool:
|
||||||
|
"""Detect if a block of code need to be wrapped in an `async def`
|
||||||
|
|
||||||
|
Attempt to parse the block of code, it it compile we're fine.
|
||||||
|
Otherwise we wrap if and try to compile.
|
||||||
|
|
||||||
|
If it works, assume it should be async. Otherwise Return False.
|
||||||
|
|
||||||
|
Not handled yet: If the block of code has a return statement as the top
|
||||||
|
level, it will be seen as async. This is a know limitation.
|
||||||
|
"""
|
||||||
|
if sys.version_info > (3, 8):
|
||||||
|
try:
|
||||||
|
code = compile(cell, "<>", "exec", flags=getattr(ast,'PyCF_ALLOW_TOP_LEVEL_AWAIT', 0x0))
|
||||||
|
return inspect.CO_COROUTINE & code.co_flags == inspect.CO_COROUTINE
|
||||||
|
except (SyntaxError, MemoryError):
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
# we can't limit ourself to ast.parse, as it __accepts__ to parse on
|
||||||
|
# 3.7+, but just does not _compile_
|
||||||
|
code = compile(cell, "<>", "exec")
|
||||||
|
except (SyntaxError, MemoryError):
|
||||||
|
try:
|
||||||
|
parse_tree = _async_parse_cell(cell)
|
||||||
|
|
||||||
|
# Raise a SyntaxError if there are top-level return or yields
|
||||||
|
v = _AsyncSyntaxErrorVisitor()
|
||||||
|
v.visit(parse_tree)
|
||||||
|
|
||||||
|
except (SyntaxError, MemoryError):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
return False
|
70
venv/Lib/site-packages/IPython/core/autocall.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
# encoding: utf-8
|
||||||
|
"""
|
||||||
|
Autocall capabilities for IPython.core.
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
|
||||||
|
* Brian Granger
|
||||||
|
* Fernando Perez
|
||||||
|
* Thomas Kluyver
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
"""
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (C) 2008-2011 The IPython Development Team
|
||||||
|
#
|
||||||
|
# Distributed under the terms of the BSD License. The full license is in
|
||||||
|
# the file COPYING, distributed as part of this software.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Imports
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Code
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class IPyAutocall(object):
|
||||||
|
""" Instances of this class are always autocalled
|
||||||
|
|
||||||
|
This happens regardless of 'autocall' variable state. Use this to
|
||||||
|
develop macro-like mechanisms.
|
||||||
|
"""
|
||||||
|
_ip = None
|
||||||
|
rewrite = True
|
||||||
|
def __init__(self, ip=None):
|
||||||
|
self._ip = ip
|
||||||
|
|
||||||
|
def set_ip(self, ip):
|
||||||
|
""" Will be used to set _ip point to current ipython instance b/f call
|
||||||
|
|
||||||
|
Override this method if you don't want this to happen.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self._ip = ip
|
||||||
|
|
||||||
|
|
||||||
|
class ExitAutocall(IPyAutocall):
|
||||||
|
"""An autocallable object which will be added to the user namespace so that
|
||||||
|
exit, exit(), quit or quit() are all valid ways to close the shell."""
|
||||||
|
rewrite = False
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
self._ip.ask_exit()
|
||||||
|
|
||||||
|
class ZMQExitAutocall(ExitAutocall):
|
||||||
|
"""Exit IPython. Autocallable, so it needn't be explicitly called.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
keep_kernel : bool
|
||||||
|
If True, leave the kernel alive. Otherwise, tell the kernel to exit too
|
||||||
|
(default).
|
||||||
|
"""
|
||||||
|
def __call__(self, keep_kernel=False):
|
||||||
|
self._ip.keepkernel_on_exit = keep_kernel
|
||||||
|
self._ip.ask_exit()
|
86
venv/Lib/site-packages/IPython/core/builtin_trap.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
"""
|
||||||
|
A context manager for managing things injected into :mod:`builtins`.
|
||||||
|
"""
|
||||||
|
# Copyright (c) IPython Development Team.
|
||||||
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
import builtins as builtin_mod
|
||||||
|
|
||||||
|
from traitlets.config.configurable import Configurable
|
||||||
|
|
||||||
|
from traitlets import Instance
|
||||||
|
|
||||||
|
|
||||||
|
class __BuiltinUndefined(object): pass
|
||||||
|
BuiltinUndefined = __BuiltinUndefined()
|
||||||
|
|
||||||
|
class __HideBuiltin(object): pass
|
||||||
|
HideBuiltin = __HideBuiltin()
|
||||||
|
|
||||||
|
|
||||||
|
class BuiltinTrap(Configurable):
|
||||||
|
|
||||||
|
shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
|
||||||
|
allow_none=True)
|
||||||
|
|
||||||
|
def __init__(self, shell=None):
|
||||||
|
super(BuiltinTrap, self).__init__(shell=shell, config=None)
|
||||||
|
self._orig_builtins = {}
|
||||||
|
# We define this to track if a single BuiltinTrap is nested.
|
||||||
|
# Only turn off the trap when the outermost call to __exit__ is made.
|
||||||
|
self._nested_level = 0
|
||||||
|
self.shell = shell
|
||||||
|
# builtins we always add - if set to HideBuiltin, they will just
|
||||||
|
# be removed instead of being replaced by something else
|
||||||
|
self.auto_builtins = {'exit': HideBuiltin,
|
||||||
|
'quit': HideBuiltin,
|
||||||
|
'get_ipython': self.shell.get_ipython,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
if self._nested_level == 0:
|
||||||
|
self.activate()
|
||||||
|
self._nested_level += 1
|
||||||
|
# I return self, so callers can use add_builtin in a with clause.
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
if self._nested_level == 1:
|
||||||
|
self.deactivate()
|
||||||
|
self._nested_level -= 1
|
||||||
|
# Returning False will cause exceptions to propagate
|
||||||
|
return False
|
||||||
|
|
||||||
|
def add_builtin(self, key, value):
|
||||||
|
"""Add a builtin and save the original."""
|
||||||
|
bdict = builtin_mod.__dict__
|
||||||
|
orig = bdict.get(key, BuiltinUndefined)
|
||||||
|
if value is HideBuiltin:
|
||||||
|
if orig is not BuiltinUndefined: #same as 'key in bdict'
|
||||||
|
self._orig_builtins[key] = orig
|
||||||
|
del bdict[key]
|
||||||
|
else:
|
||||||
|
self._orig_builtins[key] = orig
|
||||||
|
bdict[key] = value
|
||||||
|
|
||||||
|
def remove_builtin(self, key, orig):
|
||||||
|
"""Remove an added builtin and re-set the original."""
|
||||||
|
if orig is BuiltinUndefined:
|
||||||
|
del builtin_mod.__dict__[key]
|
||||||
|
else:
|
||||||
|
builtin_mod.__dict__[key] = orig
|
||||||
|
|
||||||
|
def activate(self):
|
||||||
|
"""Store ipython references in the __builtin__ namespace."""
|
||||||
|
|
||||||
|
add_builtin = self.add_builtin
|
||||||
|
for name, func in self.auto_builtins.items():
|
||||||
|
add_builtin(name, func)
|
||||||
|
|
||||||
|
def deactivate(self):
|
||||||
|
"""Remove any builtins which might have been added by add_builtins, or
|
||||||
|
restore overwritten ones to their previous values."""
|
||||||
|
remove_builtin = self.remove_builtin
|
||||||
|
for key, val in self._orig_builtins.items():
|
||||||
|
remove_builtin(key, val)
|
||||||
|
self._orig_builtins.clear()
|
||||||
|
self._builtins_added = False
|
160
venv/Lib/site-packages/IPython/core/compilerop.py
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
"""Compiler tools with improved interactive support.
|
||||||
|
|
||||||
|
Provides compilation machinery similar to codeop, but with caching support so
|
||||||
|
we can provide interactive tracebacks.
|
||||||
|
|
||||||
|
Authors
|
||||||
|
-------
|
||||||
|
* Robert Kern
|
||||||
|
* Fernando Perez
|
||||||
|
* Thomas Kluyver
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Note: though it might be more natural to name this module 'compiler', that
|
||||||
|
# name is in the stdlib and name collisions with the stdlib tend to produce
|
||||||
|
# weird problems (often with third-party tools).
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Copyright (C) 2010-2011 The IPython Development Team.
|
||||||
|
#
|
||||||
|
# Distributed under the terms of the BSD License.
|
||||||
|
#
|
||||||
|
# The full license is in the file COPYING.txt, distributed with this software.
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Imports
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Stdlib imports
|
||||||
|
import __future__
|
||||||
|
from ast import PyCF_ONLY_AST
|
||||||
|
import codeop
|
||||||
|
import functools
|
||||||
|
import hashlib
|
||||||
|
import linecache
|
||||||
|
import operator
|
||||||
|
import time
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Constants
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
|
||||||
|
# this is used as a bitmask to extract future-related code flags.
|
||||||
|
PyCF_MASK = functools.reduce(operator.or_,
|
||||||
|
(getattr(__future__, fname).compiler_flag
|
||||||
|
for fname in __future__.all_feature_names))
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Local utilities
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def code_name(code, number=0):
|
||||||
|
""" Compute a (probably) unique name for code for caching.
|
||||||
|
|
||||||
|
This now expects code to be unicode.
|
||||||
|
"""
|
||||||
|
hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
|
||||||
|
# Include the number and 12 characters of the hash in the name. It's
|
||||||
|
# pretty much impossible that in a single session we'll have collisions
|
||||||
|
# even with truncated hashes, and the full one makes tracebacks too long
|
||||||
|
return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Classes and functions
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CachingCompiler(codeop.Compile):
|
||||||
|
"""A compiler that caches code compiled from interactive statements.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
codeop.Compile.__init__(self)
|
||||||
|
|
||||||
|
# This is ugly, but it must be done this way to allow multiple
|
||||||
|
# simultaneous ipython instances to coexist. Since Python itself
|
||||||
|
# directly accesses the data structures in the linecache module, and
|
||||||
|
# the cache therein is global, we must work with that data structure.
|
||||||
|
# We must hold a reference to the original checkcache routine and call
|
||||||
|
# that in our own check_cache() below, but the special IPython cache
|
||||||
|
# must also be shared by all IPython instances. If we were to hold
|
||||||
|
# separate caches (one in each CachingCompiler instance), any call made
|
||||||
|
# by Python itself to linecache.checkcache() would obliterate the
|
||||||
|
# cached data from the other IPython instances.
|
||||||
|
if not hasattr(linecache, '_ipython_cache'):
|
||||||
|
linecache._ipython_cache = {}
|
||||||
|
if not hasattr(linecache, '_checkcache_ori'):
|
||||||
|
linecache._checkcache_ori = linecache.checkcache
|
||||||
|
# Now, we must monkeypatch the linecache directly so that parts of the
|
||||||
|
# stdlib that call it outside our control go through our codepath
|
||||||
|
# (otherwise we'd lose our tracebacks).
|
||||||
|
linecache.checkcache = check_linecache_ipython
|
||||||
|
|
||||||
|
|
||||||
|
def ast_parse(self, source, filename='<unknown>', symbol='exec'):
|
||||||
|
"""Parse code to an AST with the current compiler flags active.
|
||||||
|
|
||||||
|
Arguments are exactly the same as ast.parse (in the standard library),
|
||||||
|
and are passed to the built-in compile function."""
|
||||||
|
return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
|
||||||
|
|
||||||
|
def reset_compiler_flags(self):
|
||||||
|
"""Reset compiler flags to default state."""
|
||||||
|
# This value is copied from codeop.Compile.__init__, so if that ever
|
||||||
|
# changes, it will need to be updated.
|
||||||
|
self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
|
||||||
|
|
||||||
|
@property
|
||||||
|
def compiler_flags(self):
|
||||||
|
"""Flags currently active in the compilation process.
|
||||||
|
"""
|
||||||
|
return self.flags
|
||||||
|
|
||||||
|
def cache(self, code, number=0):
|
||||||
|
"""Make a name for a block of code, and cache the code.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
code : str
|
||||||
|
The Python source code to cache.
|
||||||
|
number : int
|
||||||
|
A number which forms part of the code's name. Used for the execution
|
||||||
|
counter.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
The name of the cached code (as a string). Pass this as the filename
|
||||||
|
argument to compilation, so that tracebacks are correctly hooked up.
|
||||||
|
"""
|
||||||
|
name = code_name(code, number)
|
||||||
|
entry = (len(code), time.time(),
|
||||||
|
[line+'\n' for line in code.splitlines()], name)
|
||||||
|
linecache.cache[name] = entry
|
||||||
|
linecache._ipython_cache[name] = entry
|
||||||
|
return name
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def extra_flags(self, flags):
|
||||||
|
## bits that we'll set to 1
|
||||||
|
turn_on_bits = ~self.flags & flags
|
||||||
|
|
||||||
|
|
||||||
|
self.flags = self.flags | flags
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
# turn off only the bits we turned on so that something like
|
||||||
|
# __future__ that set flags stays.
|
||||||
|
self.flags &= ~turn_on_bits
|
||||||
|
|
||||||
|
|
||||||
|
def check_linecache_ipython(*args):
|
||||||
|
"""Call linecache.checkcache() safely protecting our cached values.
|
||||||
|
"""
|
||||||
|
# First call the original checkcache as intended
|
||||||
|
linecache._checkcache_ori(*args)
|
||||||
|
# Then, update back the cache with our data, so that tracebacks related
|
||||||
|
# to our compiled codes can be produced.
|
||||||
|
linecache.cache.update(linecache._ipython_cache)
|