##// END OF EJS Templates
Merge remote-tracking branch 'public-upstream/master' into links-rebase...
Jason Grout -
r19202:bab26ab3 merge
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,18 +1,22 b''
1 MANIFEST
1 MANIFEST
2 build
2 build
3 dist
3 dist
4 _build
4 _build
5 docs/man/*.gz
5 docs/man/*.gz
6 docs/source/api/generated
6 docs/source/api/generated
7 docs/source/config/options
7 docs/source/config/options
8 docs/source/interactive/magics-generated.txt
8 docs/gh-pages
9 docs/gh-pages
9 IPython/html/notebook/static/mathjax
10 IPython/html/notebook/static/mathjax
10 IPython/html/static/style/*.map
11 IPython/html/static/style/*.map
11 *.py[co]
12 *.py[co]
12 __pycache__
13 __pycache__
13 *.egg-info
14 *.egg-info
14 *~
15 *~
15 *.bak
16 *.bak
16 .ipynb_checkpoints
17 .ipynb_checkpoints
17 .tox
18 .tox
18 .DS_Store
19 .DS_Store
20 \#*#
21 .#*
22 .coverage
@@ -1,28 +1,29 b''
1 # http://travis-ci.org/#!/ipython/ipython
1 # http://travis-ci.org/#!/ipython/ipython
2 language: python
2 language: python
3 python:
3 python:
4 - 3.4
4 - 3.4
5 - 2.7
5 - 2.7
6 - 3.3
6 - 3.3
7 env:
7 env:
8 - GROUP=js
8 - GROUP=js
9 - GROUP=
9 - GROUP=
10 before_install:
10 before_install:
11 # workaround for https://github.com/travis-ci/travis-cookbooks/issues/155
11 # workaround for https://github.com/travis-ci/travis-cookbooks/issues/155
12 - sudo rm -rf /dev/shm && sudo ln -s /run/shm /dev/shm
12 - sudo rm -rf /dev/shm && sudo ln -s /run/shm /dev/shm
13 # Pierre Carrier's PPA for PhantomJS and CasperJS
13 # Pierre Carrier's PPA for PhantomJS and CasperJS
14 - time sudo add-apt-repository -y ppa:pcarrier/ppa
14 - sudo add-apt-repository -y ppa:pcarrier/ppa
15 - time sudo apt-get update
15 # Needed to get recent version of pandoc in ubntu 12.04
16 - time sudo apt-get install pandoc casperjs libzmq3-dev
16 - sudo add-apt-repository -y ppa:marutter/c2d4u
17 # pin tornado < 4 for js tests while phantom is on super old webkit
17 - sudo apt-get update
18 - if [[ $GROUP == 'js' ]]; then pip install 'tornado<4'; fi
18 - sudo apt-get install pandoc casperjs libzmq3-dev
19 - time pip install -f https://nipy.bic.berkeley.edu/wheelhouse/travis jinja2 sphinx pygments tornado requests mock pyzmq jsonschema jsonpointer mistune
19 - git clone --quiet --depth 1 https://github.com/minrk/travis-wheels travis-wheels
20 - 'if [[ $GROUP == js* ]]; then python -m IPython.external.mathjax; fi'
20 install:
21 install:
21 - time python setup.py install -q
22 - pip install -f travis-wheels/wheelhouse file://$PWD#egg=ipython[all]
22 script:
23 script:
23 - cd /tmp && iptest $GROUP
24 - cd /tmp && iptest $GROUP
24
25
25 matrix:
26 matrix:
26 exclude:
27 exclude:
27 - python: 3.3
28 - python: 3.3
28 env: GROUP=js
29 env: GROUP=js
@@ -1,46 +1,66 b''
1 # Installs IPython from the current branch
1 # Installs IPython from the current branch
2 # Another Docker container should build from this one to get services like the notebook
2 # Another Docker container should build from this one to get services like the notebook
3
3
4 FROM ubuntu:14.04
4 FROM ubuntu:14.04
5
5
6 MAINTAINER IPython Project <ipython-dev@scipy.org>
6 MAINTAINER IPython Project <ipython-dev@scipy.org>
7
7
8 # Make sure apt is up to date
8 ENV DEBIAN_FRONTEND noninteractive
9 RUN apt-get update
10 RUN apt-get upgrade -y
11
9
12 # Not essential, but wise to set the lang
10 # Not essential, but wise to set the lang
13 # Note: Users with other languages should set this in their derivative image
11 # Note: Users with other languages should set this in their derivative image
14 RUN apt-get install -y language-pack-en
12 RUN apt-get update && apt-get install -y language-pack-en
15 ENV LANGUAGE en_US.UTF-8
13 ENV LANGUAGE en_US.UTF-8
16 ENV LANG en_US.UTF-8
14 ENV LANG en_US.UTF-8
17 ENV LC_ALL en_US.UTF-8
15 ENV LC_ALL en_US.UTF-8
18
16
19 RUN locale-gen en_US.UTF-8
17 RUN locale-gen en_US.UTF-8
20 RUN dpkg-reconfigure locales
18 RUN dpkg-reconfigure locales
21
19
22 # Python binary dependencies, developer tools
20 # Python binary dependencies, developer tools
23 RUN apt-get install -y -q build-essential make gcc zlib1g-dev git && \
21 RUN apt-get update && apt-get install -y -q \
24 apt-get install -y -q python python-dev python-pip python3-dev python3-pip && \
22 build-essential \
25 apt-get install -y -q libzmq3-dev sqlite3 libsqlite3-dev pandoc libcurl4-openssl-dev nodejs nodejs-legacy npm
23 make \
24 gcc \
25 zlib1g-dev \
26 git \
27 python \
28 python-dev \
29 python-pip \
30 python3-dev \
31 python3-pip \
32 python-sphinx \
33 python3-sphinx \
34 libzmq3-dev \
35 sqlite3 \
36 libsqlite3-dev \
37 pandoc \
38 libcurl4-openssl-dev \
39 nodejs \
40 nodejs-legacy \
41 npm
26
42
27 # In order to build from source, need less
43 # In order to build from source, need less
28 RUN npm install -g less
44 RUN npm install -g less@1.7.5
29
45
30 RUN apt-get -y install fabric
46 RUN pip install invoke
31
47
32 RUN mkdir -p /srv/
48 RUN mkdir -p /srv/
33 WORKDIR /srv/
49 WORKDIR /srv/
34 ADD . /srv/ipython
50 ADD . /srv/ipython
35 WORKDIR /srv/ipython/
51 WORKDIR /srv/ipython/
36 RUN chmod -R +rX /srv/ipython
52 RUN chmod -R +rX /srv/ipython
37
53
38 # .[all] only works with -e, so use file://path#egg
54 # .[all] only works with -e, so use file://path#egg
39 # Can't use -e because ipython2 and ipython3 will clobber each other
55 # Can't use -e because ipython2 and ipython3 will clobber each other
40 RUN pip2 install --upgrade file:///srv/ipython#egg=ipython[all]
56 RUN pip2 install file:///srv/ipython#egg=ipython[all]
41 RUN pip3 install --upgrade file:///srv/ipython#egg=ipython[all]
57 RUN pip3 install file:///srv/ipython#egg=ipython[all]
42
58
43 # install kernels
59 # install kernels
44 RUN python2 -m IPython kernelspec install-self --system
60 RUN python2 -m IPython kernelspec install-self --system
45 RUN python3 -m IPython kernelspec install-self --system
61 RUN python3 -m IPython kernelspec install-self --system
46
62
63 WORKDIR /tmp/
64
65 RUN iptest2
66 RUN iptest3
@@ -1,586 +1,611 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A base class for a configurable application."""
2 """A base class for a configurable application."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from __future__ import print_function
7 from __future__ import print_function
8
8
9 import json
9 import logging
10 import logging
10 import os
11 import os
11 import re
12 import re
12 import sys
13 import sys
13 from copy import deepcopy
14 from copy import deepcopy
14 from collections import defaultdict
15 from collections import defaultdict
15
16
16 from IPython.external.decorator import decorator
17 from IPython.external.decorator import decorator
17
18
18 from IPython.config.configurable import SingletonConfigurable
19 from IPython.config.configurable import SingletonConfigurable
19 from IPython.config.loader import (
20 from IPython.config.loader import (
20 KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound, JSONFileConfigLoader
21 KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound, JSONFileConfigLoader
21 )
22 )
22
23
23 from IPython.utils.traitlets import (
24 from IPython.utils.traitlets import (
24 Unicode, List, Enum, Dict, Instance, TraitError
25 Unicode, List, Enum, Dict, Instance, TraitError
25 )
26 )
26 from IPython.utils.importstring import import_item
27 from IPython.utils.importstring import import_item
27 from IPython.utils.text import indent, wrap_paragraphs, dedent
28 from IPython.utils.text import indent, wrap_paragraphs, dedent
28 from IPython.utils import py3compat
29 from IPython.utils import py3compat
29 from IPython.utils.py3compat import string_types, iteritems
30 from IPython.utils.py3compat import string_types, iteritems
30
31
31 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
32 # Descriptions for the various sections
33 # Descriptions for the various sections
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
34
35
35 # merge flags&aliases into options
36 # merge flags&aliases into options
36 option_description = """
37 option_description = """
37 Arguments that take values are actually convenience aliases to full
38 Arguments that take values are actually convenience aliases to full
38 Configurables, whose aliases are listed on the help line. For more information
39 Configurables, whose aliases are listed on the help line. For more information
39 on full configurables, see '--help-all'.
40 on full configurables, see '--help-all'.
40 """.strip() # trim newlines of front and back
41 """.strip() # trim newlines of front and back
41
42
42 keyvalue_description = """
43 keyvalue_description = """
43 Parameters are set from command-line arguments of the form:
44 Parameters are set from command-line arguments of the form:
44 `--Class.trait=value`.
45 `--Class.trait=value`.
45 This line is evaluated in Python, so simple expressions are allowed, e.g.::
46 This line is evaluated in Python, so simple expressions are allowed, e.g.::
46 `--C.a='range(3)'` For setting C.a=[0,1,2].
47 `--C.a='range(3)'` For setting C.a=[0,1,2].
47 """.strip() # trim newlines of front and back
48 """.strip() # trim newlines of front and back
48
49
49 # sys.argv can be missing, for example when python is embedded. See the docs
50 # sys.argv can be missing, for example when python is embedded. See the docs
50 # for details: http://docs.python.org/2/c-api/intro.html#embedding-python
51 # for details: http://docs.python.org/2/c-api/intro.html#embedding-python
51 if not hasattr(sys, "argv"):
52 if not hasattr(sys, "argv"):
52 sys.argv = [""]
53 sys.argv = [""]
53
54
54 subcommand_description = """
55 subcommand_description = """
55 Subcommands are launched as `{app} cmd [args]`. For information on using
56 Subcommands are launched as `{app} cmd [args]`. For information on using
56 subcommand 'cmd', do: `{app} cmd -h`.
57 subcommand 'cmd', do: `{app} cmd -h`.
57 """
58 """
58 # get running program name
59 # get running program name
59
60
60 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
61 # Application class
62 # Application class
62 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
63
64
64 @decorator
65 @decorator
65 def catch_config_error(method, app, *args, **kwargs):
66 def catch_config_error(method, app, *args, **kwargs):
66 """Method decorator for catching invalid config (Trait/ArgumentErrors) during init.
67 """Method decorator for catching invalid config (Trait/ArgumentErrors) during init.
67
68
68 On a TraitError (generally caused by bad config), this will print the trait's
69 On a TraitError (generally caused by bad config), this will print the trait's
69 message, and exit the app.
70 message, and exit the app.
70
71
71 For use on init methods, to prevent invoking excepthook on invalid input.
72 For use on init methods, to prevent invoking excepthook on invalid input.
72 """
73 """
73 try:
74 try:
74 return method(app, *args, **kwargs)
75 return method(app, *args, **kwargs)
75 except (TraitError, ArgumentError) as e:
76 except (TraitError, ArgumentError) as e:
76 app.print_help()
77 app.print_help()
77 app.log.fatal("Bad config encountered during initialization:")
78 app.log.fatal("Bad config encountered during initialization:")
78 app.log.fatal(str(e))
79 app.log.fatal(str(e))
79 app.log.debug("Config at the time: %s", app.config)
80 app.log.debug("Config at the time: %s", app.config)
80 app.exit(1)
81 app.exit(1)
81
82
82
83
83 class ApplicationError(Exception):
84 class ApplicationError(Exception):
84 pass
85 pass
85
86
86 class LevelFormatter(logging.Formatter):
87 class LevelFormatter(logging.Formatter):
87 """Formatter with additional `highlevel` record
88 """Formatter with additional `highlevel` record
88
89
89 This field is empty if log level is less than highlevel_limit,
90 This field is empty if log level is less than highlevel_limit,
90 otherwise it is formatted with self.highlevel_format.
91 otherwise it is formatted with self.highlevel_format.
91
92
92 Useful for adding 'WARNING' to warning messages,
93 Useful for adding 'WARNING' to warning messages,
93 without adding 'INFO' to info, etc.
94 without adding 'INFO' to info, etc.
94 """
95 """
95 highlevel_limit = logging.WARN
96 highlevel_limit = logging.WARN
96 highlevel_format = " %(levelname)s |"
97 highlevel_format = " %(levelname)s |"
97
98
98 def format(self, record):
99 def format(self, record):
99 if record.levelno >= self.highlevel_limit:
100 if record.levelno >= self.highlevel_limit:
100 record.highlevel = self.highlevel_format % record.__dict__
101 record.highlevel = self.highlevel_format % record.__dict__
101 else:
102 else:
102 record.highlevel = ""
103 record.highlevel = ""
103 return super(LevelFormatter, self).format(record)
104 return super(LevelFormatter, self).format(record)
104
105
105
106
106 class Application(SingletonConfigurable):
107 class Application(SingletonConfigurable):
107 """A singleton application with full configuration support."""
108 """A singleton application with full configuration support."""
108
109
109 # The name of the application, will usually match the name of the command
110 # The name of the application, will usually match the name of the command
110 # line application
111 # line application
111 name = Unicode(u'application')
112 name = Unicode(u'application')
112
113
113 # The description of the application that is printed at the beginning
114 # The description of the application that is printed at the beginning
114 # of the help.
115 # of the help.
115 description = Unicode(u'This is an application.')
116 description = Unicode(u'This is an application.')
116 # default section descriptions
117 # default section descriptions
117 option_description = Unicode(option_description)
118 option_description = Unicode(option_description)
118 keyvalue_description = Unicode(keyvalue_description)
119 keyvalue_description = Unicode(keyvalue_description)
119 subcommand_description = Unicode(subcommand_description)
120 subcommand_description = Unicode(subcommand_description)
120
121
121 # The usage and example string that goes at the end of the help string.
122 # The usage and example string that goes at the end of the help string.
122 examples = Unicode()
123 examples = Unicode()
123
124
124 # A sequence of Configurable subclasses whose config=True attributes will
125 # A sequence of Configurable subclasses whose config=True attributes will
125 # be exposed at the command line.
126 # be exposed at the command line.
126 classes = List([])
127 classes = []
128 @property
129 def _help_classes(self):
130 """Define `App.help_classes` if CLI classes should differ from config file classes"""
131 return getattr(self, 'help_classes', self.classes)
132
133 @property
134 def _config_classes(self):
135 """Define `App.config_classes` if config file classes should differ from CLI classes."""
136 return getattr(self, 'config_classes', self.classes)
127
137
128 # The version string of this application.
138 # The version string of this application.
129 version = Unicode(u'0.0')
139 version = Unicode(u'0.0')
130
140
131 # the argv used to initialize the application
141 # the argv used to initialize the application
132 argv = List()
142 argv = List()
133
143
134 # The log level for the application
144 # The log level for the application
135 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
145 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
136 default_value=logging.WARN,
146 default_value=logging.WARN,
137 config=True,
147 config=True,
138 help="Set the log level by value or name.")
148 help="Set the log level by value or name.")
139 def _log_level_changed(self, name, old, new):
149 def _log_level_changed(self, name, old, new):
140 """Adjust the log level when log_level is set."""
150 """Adjust the log level when log_level is set."""
141 if isinstance(new, string_types):
151 if isinstance(new, string_types):
142 new = getattr(logging, new)
152 new = getattr(logging, new)
143 self.log_level = new
153 self.log_level = new
144 self.log.setLevel(new)
154 self.log.setLevel(new)
145
155
146 _log_formatter_cls = LevelFormatter
156 _log_formatter_cls = LevelFormatter
147
157
148 log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", config=True,
158 log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", config=True,
149 help="The date format used by logging formatters for %(asctime)s"
159 help="The date format used by logging formatters for %(asctime)s"
150 )
160 )
151 def _log_datefmt_changed(self, name, old, new):
161 def _log_datefmt_changed(self, name, old, new):
152 self._log_format_changed()
162 self._log_format_changed()
153
163
154 log_format = Unicode("[%(name)s]%(highlevel)s %(message)s", config=True,
164 log_format = Unicode("[%(name)s]%(highlevel)s %(message)s", config=True,
155 help="The Logging format template",
165 help="The Logging format template",
156 )
166 )
157 def _log_format_changed(self, name, old, new):
167 def _log_format_changed(self, name, old, new):
158 """Change the log formatter when log_format is set."""
168 """Change the log formatter when log_format is set."""
159 _log_handler = self.log.handlers[0]
169 _log_handler = self.log.handlers[0]
160 _log_formatter = self._log_formatter_cls(fmt=new, datefmt=self.log_datefmt)
170 _log_formatter = self._log_formatter_cls(fmt=new, datefmt=self.log_datefmt)
161 _log_handler.setFormatter(_log_formatter)
171 _log_handler.setFormatter(_log_formatter)
162
172
163
173
164 log = Instance(logging.Logger)
174 log = Instance(logging.Logger)
165 def _log_default(self):
175 def _log_default(self):
166 """Start logging for this application.
176 """Start logging for this application.
167
177
168 The default is to log to stderr using a StreamHandler, if no default
178 The default is to log to stderr using a StreamHandler, if no default
169 handler already exists. The log level starts at logging.WARN, but this
179 handler already exists. The log level starts at logging.WARN, but this
170 can be adjusted by setting the ``log_level`` attribute.
180 can be adjusted by setting the ``log_level`` attribute.
171 """
181 """
172 log = logging.getLogger(self.__class__.__name__)
182 log = logging.getLogger(self.__class__.__name__)
173 log.setLevel(self.log_level)
183 log.setLevel(self.log_level)
174 log.propagate = False
184 log.propagate = False
175 _log = log # copied from Logger.hasHandlers() (new in Python 3.2)
185 _log = log # copied from Logger.hasHandlers() (new in Python 3.2)
176 while _log:
186 while _log:
177 if _log.handlers:
187 if _log.handlers:
178 return log
188 return log
179 if not _log.propagate:
189 if not _log.propagate:
180 break
190 break
181 else:
191 else:
182 _log = _log.parent
192 _log = _log.parent
183 if sys.executable.endswith('pythonw.exe'):
193 if sys.executable.endswith('pythonw.exe'):
184 # this should really go to a file, but file-logging is only
194 # this should really go to a file, but file-logging is only
185 # hooked up in parallel applications
195 # hooked up in parallel applications
186 _log_handler = logging.StreamHandler(open(os.devnull, 'w'))
196 _log_handler = logging.StreamHandler(open(os.devnull, 'w'))
187 else:
197 else:
188 _log_handler = logging.StreamHandler()
198 _log_handler = logging.StreamHandler()
189 _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt)
199 _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt)
190 _log_handler.setFormatter(_log_formatter)
200 _log_handler.setFormatter(_log_formatter)
191 log.addHandler(_log_handler)
201 log.addHandler(_log_handler)
192 return log
202 return log
193
203
194 # the alias map for configurables
204 # the alias map for configurables
195 aliases = Dict({'log-level' : 'Application.log_level'})
205 aliases = Dict({'log-level' : 'Application.log_level'})
196
206
197 # flags for loading Configurables or store_const style flags
207 # flags for loading Configurables or store_const style flags
198 # flags are loaded from this dict by '--key' flags
208 # flags are loaded from this dict by '--key' flags
199 # this must be a dict of two-tuples, the first element being the Config/dict
209 # this must be a dict of two-tuples, the first element being the Config/dict
200 # and the second being the help string for the flag
210 # and the second being the help string for the flag
201 flags = Dict()
211 flags = Dict()
202 def _flags_changed(self, name, old, new):
212 def _flags_changed(self, name, old, new):
203 """ensure flags dict is valid"""
213 """ensure flags dict is valid"""
204 for key,value in iteritems(new):
214 for key,value in iteritems(new):
205 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
215 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
206 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
216 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
207 assert isinstance(value[1], string_types), "Bad flag: %r:%s"%(key,value)
217 assert isinstance(value[1], string_types), "Bad flag: %r:%s"%(key,value)
208
218
209
219
210 # subcommands for launching other applications
220 # subcommands for launching other applications
211 # if this is not empty, this will be a parent Application
221 # if this is not empty, this will be a parent Application
212 # this must be a dict of two-tuples,
222 # this must be a dict of two-tuples,
213 # the first element being the application class/import string
223 # the first element being the application class/import string
214 # and the second being the help string for the subcommand
224 # and the second being the help string for the subcommand
215 subcommands = Dict()
225 subcommands = Dict()
216 # parse_command_line will initialize a subapp, if requested
226 # parse_command_line will initialize a subapp, if requested
217 subapp = Instance('IPython.config.application.Application', allow_none=True)
227 subapp = Instance('IPython.config.application.Application', allow_none=True)
218
228
219 # extra command-line arguments that don't set config values
229 # extra command-line arguments that don't set config values
220 extra_args = List(Unicode)
230 extra_args = List(Unicode)
221
231
222
232
223 def __init__(self, **kwargs):
233 def __init__(self, **kwargs):
224 SingletonConfigurable.__init__(self, **kwargs)
234 SingletonConfigurable.__init__(self, **kwargs)
225 # Ensure my class is in self.classes, so my attributes appear in command line
235 # Ensure my class is in self.classes, so my attributes appear in command line
226 # options and config files.
236 # options and config files.
227 if self.__class__ not in self.classes:
237 if self.__class__ not in self.classes:
228 self.classes.insert(0, self.__class__)
238 self.classes.insert(0, self.__class__)
229
239
230 def _config_changed(self, name, old, new):
240 def _config_changed(self, name, old, new):
231 SingletonConfigurable._config_changed(self, name, old, new)
241 SingletonConfigurable._config_changed(self, name, old, new)
232 self.log.debug('Config changed:')
242 self.log.debug('Config changed:')
233 self.log.debug(repr(new))
243 self.log.debug(repr(new))
234
244
235 @catch_config_error
245 @catch_config_error
236 def initialize(self, argv=None):
246 def initialize(self, argv=None):
237 """Do the basic steps to configure me.
247 """Do the basic steps to configure me.
238
248
239 Override in subclasses.
249 Override in subclasses.
240 """
250 """
241 self.parse_command_line(argv)
251 self.parse_command_line(argv)
242
252
243
253
244 def start(self):
254 def start(self):
245 """Start the app mainloop.
255 """Start the app mainloop.
246
256
247 Override in subclasses.
257 Override in subclasses.
248 """
258 """
249 if self.subapp is not None:
259 if self.subapp is not None:
250 return self.subapp.start()
260 return self.subapp.start()
251
261
252 def print_alias_help(self):
262 def print_alias_help(self):
253 """Print the alias part of the help."""
263 """Print the alias part of the help."""
254 if not self.aliases:
264 if not self.aliases:
255 return
265 return
256
266
257 lines = []
267 lines = []
258 classdict = {}
268 classdict = {}
259 for cls in self.classes:
269 for cls in self._help_classes:
260 # include all parents (up to, but excluding Configurable) in available names
270 # include all parents (up to, but excluding Configurable) in available names
261 for c in cls.mro()[:-3]:
271 for c in cls.mro()[:-3]:
262 classdict[c.__name__] = c
272 classdict[c.__name__] = c
263
273
264 for alias, longname in iteritems(self.aliases):
274 for alias, longname in iteritems(self.aliases):
265 classname, traitname = longname.split('.',1)
275 classname, traitname = longname.split('.',1)
266 cls = classdict[classname]
276 cls = classdict[classname]
267
277
268 trait = cls.class_traits(config=True)[traitname]
278 trait = cls.class_traits(config=True)[traitname]
269 help = cls.class_get_trait_help(trait).splitlines()
279 help = cls.class_get_trait_help(trait).splitlines()
270 # reformat first line
280 # reformat first line
271 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
281 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
272 if len(alias) == 1:
282 if len(alias) == 1:
273 help[0] = help[0].replace('--%s='%alias, '-%s '%alias)
283 help[0] = help[0].replace('--%s='%alias, '-%s '%alias)
274 lines.extend(help)
284 lines.extend(help)
275 # lines.append('')
285 # lines.append('')
276 print(os.linesep.join(lines))
286 print(os.linesep.join(lines))
277
287
278 def print_flag_help(self):
288 def print_flag_help(self):
279 """Print the flag part of the help."""
289 """Print the flag part of the help."""
280 if not self.flags:
290 if not self.flags:
281 return
291 return
282
292
283 lines = []
293 lines = []
284 for m, (cfg,help) in iteritems(self.flags):
294 for m, (cfg,help) in iteritems(self.flags):
285 prefix = '--' if len(m) > 1 else '-'
295 prefix = '--' if len(m) > 1 else '-'
286 lines.append(prefix+m)
296 lines.append(prefix+m)
287 lines.append(indent(dedent(help.strip())))
297 lines.append(indent(dedent(help.strip())))
288 # lines.append('')
298 # lines.append('')
289 print(os.linesep.join(lines))
299 print(os.linesep.join(lines))
290
300
291 def print_options(self):
301 def print_options(self):
292 if not self.flags and not self.aliases:
302 if not self.flags and not self.aliases:
293 return
303 return
294 lines = ['Options']
304 lines = ['Options']
295 lines.append('-'*len(lines[0]))
305 lines.append('-'*len(lines[0]))
296 lines.append('')
306 lines.append('')
297 for p in wrap_paragraphs(self.option_description):
307 for p in wrap_paragraphs(self.option_description):
298 lines.append(p)
308 lines.append(p)
299 lines.append('')
309 lines.append('')
300 print(os.linesep.join(lines))
310 print(os.linesep.join(lines))
301 self.print_flag_help()
311 self.print_flag_help()
302 self.print_alias_help()
312 self.print_alias_help()
303 print()
313 print()
304
314
305 def print_subcommands(self):
315 def print_subcommands(self):
306 """Print the subcommand part of the help."""
316 """Print the subcommand part of the help."""
307 if not self.subcommands:
317 if not self.subcommands:
308 return
318 return
309
319
310 lines = ["Subcommands"]
320 lines = ["Subcommands"]
311 lines.append('-'*len(lines[0]))
321 lines.append('-'*len(lines[0]))
312 lines.append('')
322 lines.append('')
313 for p in wrap_paragraphs(self.subcommand_description.format(
323 for p in wrap_paragraphs(self.subcommand_description.format(
314 app=self.name)):
324 app=self.name)):
315 lines.append(p)
325 lines.append(p)
316 lines.append('')
326 lines.append('')
317 for subc, (cls, help) in iteritems(self.subcommands):
327 for subc, (cls, help) in iteritems(self.subcommands):
318 lines.append(subc)
328 lines.append(subc)
319 if help:
329 if help:
320 lines.append(indent(dedent(help.strip())))
330 lines.append(indent(dedent(help.strip())))
321 lines.append('')
331 lines.append('')
322 print(os.linesep.join(lines))
332 print(os.linesep.join(lines))
323
333
324 def print_help(self, classes=False):
334 def print_help(self, classes=False):
325 """Print the help for each Configurable class in self.classes.
335 """Print the help for each Configurable class in self.classes.
326
336
327 If classes=False (the default), only flags and aliases are printed.
337 If classes=False (the default), only flags and aliases are printed.
328 """
338 """
329 self.print_description()
339 self.print_description()
330 self.print_subcommands()
340 self.print_subcommands()
331 self.print_options()
341 self.print_options()
332
342
333 if classes:
343 if classes:
334 if self.classes:
344 help_classes = self._help_classes
345 if help_classes:
335 print("Class parameters")
346 print("Class parameters")
336 print("----------------")
347 print("----------------")
337 print()
348 print()
338 for p in wrap_paragraphs(self.keyvalue_description):
349 for p in wrap_paragraphs(self.keyvalue_description):
339 print(p)
350 print(p)
340 print()
351 print()
341
352
342 for cls in self.classes:
353 for cls in help_classes:
343 cls.class_print_help()
354 cls.class_print_help()
344 print()
355 print()
345 else:
356 else:
346 print("To see all available configurables, use `--help-all`")
357 print("To see all available configurables, use `--help-all`")
347 print()
358 print()
348
359
349 self.print_examples()
360 self.print_examples()
350
361
351
362
352 def print_description(self):
363 def print_description(self):
353 """Print the application description."""
364 """Print the application description."""
354 for p in wrap_paragraphs(self.description):
365 for p in wrap_paragraphs(self.description):
355 print(p)
366 print(p)
356 print()
367 print()
357
368
358 def print_examples(self):
369 def print_examples(self):
359 """Print usage and examples.
370 """Print usage and examples.
360
371
361 This usage string goes at the end of the command line help string
372 This usage string goes at the end of the command line help string
362 and should contain examples of the application's usage.
373 and should contain examples of the application's usage.
363 """
374 """
364 if self.examples:
375 if self.examples:
365 print("Examples")
376 print("Examples")
366 print("--------")
377 print("--------")
367 print()
378 print()
368 print(indent(dedent(self.examples.strip())))
379 print(indent(dedent(self.examples.strip())))
369 print()
380 print()
370
381
371 def print_version(self):
382 def print_version(self):
372 """Print the version string."""
383 """Print the version string."""
373 print(self.version)
384 print(self.version)
374
385
375 def update_config(self, config):
386 def update_config(self, config):
376 """Fire the traits events when the config is updated."""
387 """Fire the traits events when the config is updated."""
377 # Save a copy of the current config.
388 # Save a copy of the current config.
378 newconfig = deepcopy(self.config)
389 newconfig = deepcopy(self.config)
379 # Merge the new config into the current one.
390 # Merge the new config into the current one.
380 newconfig.merge(config)
391 newconfig.merge(config)
381 # Save the combined config as self.config, which triggers the traits
392 # Save the combined config as self.config, which triggers the traits
382 # events.
393 # events.
383 self.config = newconfig
394 self.config = newconfig
384
395
385 @catch_config_error
396 @catch_config_error
386 def initialize_subcommand(self, subc, argv=None):
397 def initialize_subcommand(self, subc, argv=None):
387 """Initialize a subcommand with argv."""
398 """Initialize a subcommand with argv."""
388 subapp,help = self.subcommands.get(subc)
399 subapp,help = self.subcommands.get(subc)
389
400
390 if isinstance(subapp, string_types):
401 if isinstance(subapp, string_types):
391 subapp = import_item(subapp)
402 subapp = import_item(subapp)
392
403
393 # clear existing instances
404 # clear existing instances
394 self.__class__.clear_instance()
405 self.__class__.clear_instance()
395 # instantiate
406 # instantiate
396 self.subapp = subapp.instance(config=self.config)
407 self.subapp = subapp.instance(config=self.config)
397 # and initialize subapp
408 # and initialize subapp
398 self.subapp.initialize(argv)
409 self.subapp.initialize(argv)
399
410
400 def flatten_flags(self):
411 def flatten_flags(self):
401 """flatten flags and aliases, so cl-args override as expected.
412 """flatten flags and aliases, so cl-args override as expected.
402
413
403 This prevents issues such as an alias pointing to InteractiveShell,
414 This prevents issues such as an alias pointing to InteractiveShell,
404 but a config file setting the same trait in TerminalInteraciveShell
415 but a config file setting the same trait in TerminalInteraciveShell
405 getting inappropriate priority over the command-line arg.
416 getting inappropriate priority over the command-line arg.
406
417
407 Only aliases with exactly one descendent in the class list
418 Only aliases with exactly one descendent in the class list
408 will be promoted.
419 will be promoted.
409
420
410 """
421 """
411 # build a tree of classes in our list that inherit from a particular
422 # build a tree of classes in our list that inherit from a particular
412 # it will be a dict by parent classname of classes in our list
423 # it will be a dict by parent classname of classes in our list
413 # that are descendents
424 # that are descendents
414 mro_tree = defaultdict(list)
425 mro_tree = defaultdict(list)
415 for cls in self.classes:
426 for cls in self._help_classes:
416 clsname = cls.__name__
427 clsname = cls.__name__
417 for parent in cls.mro()[1:-3]:
428 for parent in cls.mro()[1:-3]:
418 # exclude cls itself and Configurable,HasTraits,object
429 # exclude cls itself and Configurable,HasTraits,object
419 mro_tree[parent.__name__].append(clsname)
430 mro_tree[parent.__name__].append(clsname)
420 # flatten aliases, which have the form:
431 # flatten aliases, which have the form:
421 # { 'alias' : 'Class.trait' }
432 # { 'alias' : 'Class.trait' }
422 aliases = {}
433 aliases = {}
423 for alias, cls_trait in iteritems(self.aliases):
434 for alias, cls_trait in iteritems(self.aliases):
424 cls,trait = cls_trait.split('.',1)
435 cls,trait = cls_trait.split('.',1)
425 children = mro_tree[cls]
436 children = mro_tree[cls]
426 if len(children) == 1:
437 if len(children) == 1:
427 # exactly one descendent, promote alias
438 # exactly one descendent, promote alias
428 cls = children[0]
439 cls = children[0]
429 aliases[alias] = '.'.join([cls,trait])
440 aliases[alias] = '.'.join([cls,trait])
430
441
431 # flatten flags, which are of the form:
442 # flatten flags, which are of the form:
432 # { 'key' : ({'Cls' : {'trait' : value}}, 'help')}
443 # { 'key' : ({'Cls' : {'trait' : value}}, 'help')}
433 flags = {}
444 flags = {}
434 for key, (flagdict, help) in iteritems(self.flags):
445 for key, (flagdict, help) in iteritems(self.flags):
435 newflag = {}
446 newflag = {}
436 for cls, subdict in iteritems(flagdict):
447 for cls, subdict in iteritems(flagdict):
437 children = mro_tree[cls]
448 children = mro_tree[cls]
438 # exactly one descendent, promote flag section
449 # exactly one descendent, promote flag section
439 if len(children) == 1:
450 if len(children) == 1:
440 cls = children[0]
451 cls = children[0]
441 newflag[cls] = subdict
452 newflag[cls] = subdict
442 flags[key] = (newflag, help)
453 flags[key] = (newflag, help)
443 return flags, aliases
454 return flags, aliases
444
455
445 @catch_config_error
456 @catch_config_error
446 def parse_command_line(self, argv=None):
457 def parse_command_line(self, argv=None):
447 """Parse the command line arguments."""
458 """Parse the command line arguments."""
448 argv = sys.argv[1:] if argv is None else argv
459 argv = sys.argv[1:] if argv is None else argv
449 self.argv = [ py3compat.cast_unicode(arg) for arg in argv ]
460 self.argv = [ py3compat.cast_unicode(arg) for arg in argv ]
450
461
451 if argv and argv[0] == 'help':
462 if argv and argv[0] == 'help':
452 # turn `ipython help notebook` into `ipython notebook -h`
463 # turn `ipython help notebook` into `ipython notebook -h`
453 argv = argv[1:] + ['-h']
464 argv = argv[1:] + ['-h']
454
465
455 if self.subcommands and len(argv) > 0:
466 if self.subcommands and len(argv) > 0:
456 # we have subcommands, and one may have been specified
467 # we have subcommands, and one may have been specified
457 subc, subargv = argv[0], argv[1:]
468 subc, subargv = argv[0], argv[1:]
458 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
469 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
459 # it's a subcommand, and *not* a flag or class parameter
470 # it's a subcommand, and *not* a flag or class parameter
460 return self.initialize_subcommand(subc, subargv)
471 return self.initialize_subcommand(subc, subargv)
461
472
462 # Arguments after a '--' argument are for the script IPython may be
473 # Arguments after a '--' argument are for the script IPython may be
463 # about to run, not IPython iteslf. For arguments parsed here (help and
474 # about to run, not IPython iteslf. For arguments parsed here (help and
464 # version), we want to only search the arguments up to the first
475 # version), we want to only search the arguments up to the first
465 # occurrence of '--', which we're calling interpreted_argv.
476 # occurrence of '--', which we're calling interpreted_argv.
466 try:
477 try:
467 interpreted_argv = argv[:argv.index('--')]
478 interpreted_argv = argv[:argv.index('--')]
468 except ValueError:
479 except ValueError:
469 interpreted_argv = argv
480 interpreted_argv = argv
470
481
471 if any(x in interpreted_argv for x in ('-h', '--help-all', '--help')):
482 if any(x in interpreted_argv for x in ('-h', '--help-all', '--help')):
472 self.print_help('--help-all' in interpreted_argv)
483 self.print_help('--help-all' in interpreted_argv)
473 self.exit(0)
484 self.exit(0)
474
485
475 if '--version' in interpreted_argv or '-V' in interpreted_argv:
486 if '--version' in interpreted_argv or '-V' in interpreted_argv:
476 self.print_version()
487 self.print_version()
477 self.exit(0)
488 self.exit(0)
478
489
479 # flatten flags&aliases, so cl-args get appropriate priority:
490 # flatten flags&aliases, so cl-args get appropriate priority:
480 flags,aliases = self.flatten_flags()
491 flags,aliases = self.flatten_flags()
481 loader = KVArgParseConfigLoader(argv=argv, aliases=aliases,
492 loader = KVArgParseConfigLoader(argv=argv, aliases=aliases,
482 flags=flags, log=self.log)
493 flags=flags, log=self.log)
483 config = loader.load_config()
494 config = loader.load_config()
484 self.update_config(config)
495 self.update_config(config)
485 # store unparsed args in extra_args
496 # store unparsed args in extra_args
486 self.extra_args = loader.extra_args
497 self.extra_args = loader.extra_args
487
498
488 @classmethod
499 @classmethod
489 def _load_config_files(cls, basefilename, path=None, log=None):
500 def _load_config_files(cls, basefilename, path=None, log=None):
490 """Load config files (py,json) by filename and path.
501 """Load config files (py,json) by filename and path.
491
502
492 yield each config object in turn.
503 yield each config object in turn.
493 """
504 """
494 pyloader = PyFileConfigLoader(basefilename+'.py', path=path, log=log)
505
495 jsonloader = JSONFileConfigLoader(basefilename+'.json', path=path, log=log)
506 if not isinstance(path, list):
496 config = None
507 path = [path]
497 for loader in [pyloader, jsonloader]:
508 for path in path[::-1]:
498 try:
509 # path list is in descending priority order, so load files backwards:
499 config = loader.load_config()
510 pyloader = PyFileConfigLoader(basefilename+'.py', path=path, log=log)
500 except ConfigFileNotFound:
511 jsonloader = JSONFileConfigLoader(basefilename+'.json', path=path, log=log)
501 pass
512 config = None
502 except Exception:
513 for loader in [pyloader, jsonloader]:
503 # try to get the full filename, but it will be empty in the
514 try:
504 # unlikely event that the error raised before filefind finished
515 config = loader.load_config()
505 filename = loader.full_filename or basefilename
516 except ConfigFileNotFound:
506 # problem while running the file
517 pass
507 if log:
518 except Exception:
508 log.error("Exception while loading config file %s",
519 # try to get the full filename, but it will be empty in the
509 filename, exc_info=True)
520 # unlikely event that the error raised before filefind finished
510 else:
521 filename = loader.full_filename or basefilename
511 if log:
522 # problem while running the file
512 log.debug("Loaded config file: %s", loader.full_filename)
523 if log:
513 if config:
524 log.error("Exception while loading config file %s",
514 yield config
525 filename, exc_info=True)
526 else:
527 if log:
528 log.debug("Loaded config file: %s", loader.full_filename)
529 if config:
530 yield config
515
531
516 raise StopIteration
532 raise StopIteration
517
533
518
534
519 @catch_config_error
535 @catch_config_error
520 def load_config_file(self, filename, path=None):
536 def load_config_file(self, filename, path=None):
521 """Load config files by filename and path."""
537 """Load config files by filename and path."""
522 filename, ext = os.path.splitext(filename)
538 filename, ext = os.path.splitext(filename)
539 loaded = []
523 for config in self._load_config_files(filename, path=path, log=self.log):
540 for config in self._load_config_files(filename, path=path, log=self.log):
541 loaded.append(config)
524 self.update_config(config)
542 self.update_config(config)
543 if len(loaded) > 1:
544 collisions = loaded[0].collisions(loaded[1])
545 if collisions:
546 self.log.warn("Collisions detected in {0}.py and {0}.json config files."
547 " {0}.json has higher priority: {1}".format(
548 filename, json.dumps(collisions, indent=2),
549 ))
525
550
526
551
527 def generate_config_file(self):
552 def generate_config_file(self):
528 """generate default config file from Configurables"""
553 """generate default config file from Configurables"""
529 lines = ["# Configuration file for %s."%self.name]
554 lines = ["# Configuration file for %s."%self.name]
530 lines.append('')
555 lines.append('')
531 lines.append('c = get_config()')
556 lines.append('c = get_config()')
532 lines.append('')
557 lines.append('')
533 for cls in self.classes:
558 for cls in self._config_classes:
534 lines.append(cls.class_config_section())
559 lines.append(cls.class_config_section())
535 return '\n'.join(lines)
560 return '\n'.join(lines)
536
561
537 def exit(self, exit_status=0):
562 def exit(self, exit_status=0):
538 self.log.debug("Exiting application: %s" % self.name)
563 self.log.debug("Exiting application: %s" % self.name)
539 sys.exit(exit_status)
564 sys.exit(exit_status)
540
565
541 @classmethod
566 @classmethod
542 def launch_instance(cls, argv=None, **kwargs):
567 def launch_instance(cls, argv=None, **kwargs):
543 """Launch a global instance of this Application
568 """Launch a global instance of this Application
544
569
545 If a global instance already exists, this reinitializes and starts it
570 If a global instance already exists, this reinitializes and starts it
546 """
571 """
547 app = cls.instance(**kwargs)
572 app = cls.instance(**kwargs)
548 app.initialize(argv)
573 app.initialize(argv)
549 app.start()
574 app.start()
550
575
551 #-----------------------------------------------------------------------------
576 #-----------------------------------------------------------------------------
552 # utility functions, for convenience
577 # utility functions, for convenience
553 #-----------------------------------------------------------------------------
578 #-----------------------------------------------------------------------------
554
579
555 def boolean_flag(name, configurable, set_help='', unset_help=''):
580 def boolean_flag(name, configurable, set_help='', unset_help=''):
556 """Helper for building basic --trait, --no-trait flags.
581 """Helper for building basic --trait, --no-trait flags.
557
582
558 Parameters
583 Parameters
559 ----------
584 ----------
560
585
561 name : str
586 name : str
562 The name of the flag.
587 The name of the flag.
563 configurable : str
588 configurable : str
564 The 'Class.trait' string of the trait to be set/unset with the flag
589 The 'Class.trait' string of the trait to be set/unset with the flag
565 set_help : unicode
590 set_help : unicode
566 help string for --name flag
591 help string for --name flag
567 unset_help : unicode
592 unset_help : unicode
568 help string for --no-name flag
593 help string for --no-name flag
569
594
570 Returns
595 Returns
571 -------
596 -------
572
597
573 cfg : dict
598 cfg : dict
574 A dict with two keys: 'name', and 'no-name', for setting and unsetting
599 A dict with two keys: 'name', and 'no-name', for setting and unsetting
575 the trait, respectively.
600 the trait, respectively.
576 """
601 """
577 # default helpstrings
602 # default helpstrings
578 set_help = set_help or "set %s=True"%configurable
603 set_help = set_help or "set %s=True"%configurable
579 unset_help = unset_help or "set %s=False"%configurable
604 unset_help = unset_help or "set %s=False"%configurable
580
605
581 cls,trait = configurable.split('.')
606 cls,trait = configurable.split('.')
582
607
583 setter = {cls : {trait : True}}
608 setter = {cls : {trait : True}}
584 unsetter = {cls : {trait : False}}
609 unsetter = {cls : {trait : False}}
585 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
610 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
586
611
@@ -1,824 +1,844 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """A simple configuration system."""
2 """A simple configuration system."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 import argparse
7 import argparse
8 import copy
8 import copy
9 import logging
9 import logging
10 import os
10 import os
11 import re
11 import re
12 import sys
12 import sys
13 import json
13 import json
14
14
15 from IPython.utils.path import filefind, get_ipython_dir
15 from IPython.utils.path import filefind, get_ipython_dir
16 from IPython.utils import py3compat
16 from IPython.utils import py3compat
17 from IPython.utils.encoding import DEFAULT_ENCODING
17 from IPython.utils.encoding import DEFAULT_ENCODING
18 from IPython.utils.py3compat import unicode_type, iteritems
18 from IPython.utils.py3compat import unicode_type, iteritems
19 from IPython.utils.traitlets import HasTraits, List, Any
19 from IPython.utils.traitlets import HasTraits, List, Any
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Exceptions
22 # Exceptions
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25
25
26 class ConfigError(Exception):
26 class ConfigError(Exception):
27 pass
27 pass
28
28
29 class ConfigLoaderError(ConfigError):
29 class ConfigLoaderError(ConfigError):
30 pass
30 pass
31
31
32 class ConfigFileNotFound(ConfigError):
32 class ConfigFileNotFound(ConfigError):
33 pass
33 pass
34
34
35 class ArgumentError(ConfigLoaderError):
35 class ArgumentError(ConfigLoaderError):
36 pass
36 pass
37
37
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Argparse fix
39 # Argparse fix
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41
41
42 # Unfortunately argparse by default prints help messages to stderr instead of
42 # Unfortunately argparse by default prints help messages to stderr instead of
43 # stdout. This makes it annoying to capture long help screens at the command
43 # stdout. This makes it annoying to capture long help screens at the command
44 # line, since one must know how to pipe stderr, which many users don't know how
44 # line, since one must know how to pipe stderr, which many users don't know how
45 # to do. So we override the print_help method with one that defaults to
45 # to do. So we override the print_help method with one that defaults to
46 # stdout and use our class instead.
46 # stdout and use our class instead.
47
47
48 class ArgumentParser(argparse.ArgumentParser):
48 class ArgumentParser(argparse.ArgumentParser):
49 """Simple argparse subclass that prints help to stdout by default."""
49 """Simple argparse subclass that prints help to stdout by default."""
50
50
51 def print_help(self, file=None):
51 def print_help(self, file=None):
52 if file is None:
52 if file is None:
53 file = sys.stdout
53 file = sys.stdout
54 return super(ArgumentParser, self).print_help(file)
54 return super(ArgumentParser, self).print_help(file)
55
55
56 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
56 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
57
57
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59 # Config class for holding config information
59 # Config class for holding config information
60 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
61
61
62 class LazyConfigValue(HasTraits):
62 class LazyConfigValue(HasTraits):
63 """Proxy object for exposing methods on configurable containers
63 """Proxy object for exposing methods on configurable containers
64
64
65 Exposes:
65 Exposes:
66
66
67 - append, extend, insert on lists
67 - append, extend, insert on lists
68 - update on dicts
68 - update on dicts
69 - update, add on sets
69 - update, add on sets
70 """
70 """
71
71
72 _value = None
72 _value = None
73
73
74 # list methods
74 # list methods
75 _extend = List()
75 _extend = List()
76 _prepend = List()
76 _prepend = List()
77
77
78 def append(self, obj):
78 def append(self, obj):
79 self._extend.append(obj)
79 self._extend.append(obj)
80
80
81 def extend(self, other):
81 def extend(self, other):
82 self._extend.extend(other)
82 self._extend.extend(other)
83
83
84 def prepend(self, other):
84 def prepend(self, other):
85 """like list.extend, but for the front"""
85 """like list.extend, but for the front"""
86 self._prepend[:0] = other
86 self._prepend[:0] = other
87
87
88 _inserts = List()
88 _inserts = List()
89 def insert(self, index, other):
89 def insert(self, index, other):
90 if not isinstance(index, int):
90 if not isinstance(index, int):
91 raise TypeError("An integer is required")
91 raise TypeError("An integer is required")
92 self._inserts.append((index, other))
92 self._inserts.append((index, other))
93
93
94 # dict methods
94 # dict methods
95 # update is used for both dict and set
95 # update is used for both dict and set
96 _update = Any()
96 _update = Any()
97 def update(self, other):
97 def update(self, other):
98 if self._update is None:
98 if self._update is None:
99 if isinstance(other, dict):
99 if isinstance(other, dict):
100 self._update = {}
100 self._update = {}
101 else:
101 else:
102 self._update = set()
102 self._update = set()
103 self._update.update(other)
103 self._update.update(other)
104
104
105 # set methods
105 # set methods
106 def add(self, obj):
106 def add(self, obj):
107 self.update({obj})
107 self.update({obj})
108
108
109 def get_value(self, initial):
109 def get_value(self, initial):
110 """construct the value from the initial one
110 """construct the value from the initial one
111
111
112 after applying any insert / extend / update changes
112 after applying any insert / extend / update changes
113 """
113 """
114 if self._value is not None:
114 if self._value is not None:
115 return self._value
115 return self._value
116 value = copy.deepcopy(initial)
116 value = copy.deepcopy(initial)
117 if isinstance(value, list):
117 if isinstance(value, list):
118 for idx, obj in self._inserts:
118 for idx, obj in self._inserts:
119 value.insert(idx, obj)
119 value.insert(idx, obj)
120 value[:0] = self._prepend
120 value[:0] = self._prepend
121 value.extend(self._extend)
121 value.extend(self._extend)
122
122
123 elif isinstance(value, dict):
123 elif isinstance(value, dict):
124 if self._update:
124 if self._update:
125 value.update(self._update)
125 value.update(self._update)
126 elif isinstance(value, set):
126 elif isinstance(value, set):
127 if self._update:
127 if self._update:
128 value.update(self._update)
128 value.update(self._update)
129 self._value = value
129 self._value = value
130 return value
130 return value
131
131
132 def to_dict(self):
132 def to_dict(self):
133 """return JSONable dict form of my data
133 """return JSONable dict form of my data
134
134
135 Currently update as dict or set, extend, prepend as lists, and inserts as list of tuples.
135 Currently update as dict or set, extend, prepend as lists, and inserts as list of tuples.
136 """
136 """
137 d = {}
137 d = {}
138 if self._update:
138 if self._update:
139 d['update'] = self._update
139 d['update'] = self._update
140 if self._extend:
140 if self._extend:
141 d['extend'] = self._extend
141 d['extend'] = self._extend
142 if self._prepend:
142 if self._prepend:
143 d['prepend'] = self._prepend
143 d['prepend'] = self._prepend
144 elif self._inserts:
144 elif self._inserts:
145 d['inserts'] = self._inserts
145 d['inserts'] = self._inserts
146 return d
146 return d
147
147
148
148
149 def _is_section_key(key):
149 def _is_section_key(key):
150 """Is a Config key a section name (does it start with a capital)?"""
150 """Is a Config key a section name (does it start with a capital)?"""
151 if key and key[0].upper()==key[0] and not key.startswith('_'):
151 if key and key[0].upper()==key[0] and not key.startswith('_'):
152 return True
152 return True
153 else:
153 else:
154 return False
154 return False
155
155
156
156
157 class Config(dict):
157 class Config(dict):
158 """An attribute based dict that can do smart merges."""
158 """An attribute based dict that can do smart merges."""
159
159
160 def __init__(self, *args, **kwds):
160 def __init__(self, *args, **kwds):
161 dict.__init__(self, *args, **kwds)
161 dict.__init__(self, *args, **kwds)
162 self._ensure_subconfig()
162 self._ensure_subconfig()
163
163
164 def _ensure_subconfig(self):
164 def _ensure_subconfig(self):
165 """ensure that sub-dicts that should be Config objects are
165 """ensure that sub-dicts that should be Config objects are
166
166
167 casts dicts that are under section keys to Config objects,
167 casts dicts that are under section keys to Config objects,
168 which is necessary for constructing Config objects from dict literals.
168 which is necessary for constructing Config objects from dict literals.
169 """
169 """
170 for key in self:
170 for key in self:
171 obj = self[key]
171 obj = self[key]
172 if _is_section_key(key) \
172 if _is_section_key(key) \
173 and isinstance(obj, dict) \
173 and isinstance(obj, dict) \
174 and not isinstance(obj, Config):
174 and not isinstance(obj, Config):
175 setattr(self, key, Config(obj))
175 setattr(self, key, Config(obj))
176
176
177 def _merge(self, other):
177 def _merge(self, other):
178 """deprecated alias, use Config.merge()"""
178 """deprecated alias, use Config.merge()"""
179 self.merge(other)
179 self.merge(other)
180
180
181 def merge(self, other):
181 def merge(self, other):
182 """merge another config object into this one"""
182 """merge another config object into this one"""
183 to_update = {}
183 to_update = {}
184 for k, v in iteritems(other):
184 for k, v in iteritems(other):
185 if k not in self:
185 if k not in self:
186 to_update[k] = copy.deepcopy(v)
186 to_update[k] = copy.deepcopy(v)
187 else: # I have this key
187 else: # I have this key
188 if isinstance(v, Config) and isinstance(self[k], Config):
188 if isinstance(v, Config) and isinstance(self[k], Config):
189 # Recursively merge common sub Configs
189 # Recursively merge common sub Configs
190 self[k].merge(v)
190 self[k].merge(v)
191 else:
191 else:
192 # Plain updates for non-Configs
192 # Plain updates for non-Configs
193 to_update[k] = copy.deepcopy(v)
193 to_update[k] = copy.deepcopy(v)
194
194
195 self.update(to_update)
195 self.update(to_update)
196
196
197 def collisions(self, other):
198 """Check for collisions between two config objects.
199
200 Returns a dict of the form {"Class": {"trait": "collision message"}}`,
201 indicating which values have been ignored.
202
203 An empty dict indicates no collisions.
204 """
205 collisions = {}
206 for section in self:
207 if section not in other:
208 continue
209 mine = self[section]
210 theirs = other[section]
211 for key in mine:
212 if key in theirs and mine[key] != theirs[key]:
213 collisions.setdefault(section, {})
214 collisions[section][key] = "%r ignored, using %r" % (mine[key], theirs[key])
215 return collisions
216
197 def __contains__(self, key):
217 def __contains__(self, key):
198 # allow nested contains of the form `"Section.key" in config`
218 # allow nested contains of the form `"Section.key" in config`
199 if '.' in key:
219 if '.' in key:
200 first, remainder = key.split('.', 1)
220 first, remainder = key.split('.', 1)
201 if first not in self:
221 if first not in self:
202 return False
222 return False
203 return remainder in self[first]
223 return remainder in self[first]
204
224
205 return super(Config, self).__contains__(key)
225 return super(Config, self).__contains__(key)
206
226
207 # .has_key is deprecated for dictionaries.
227 # .has_key is deprecated for dictionaries.
208 has_key = __contains__
228 has_key = __contains__
209
229
210 def _has_section(self, key):
230 def _has_section(self, key):
211 return _is_section_key(key) and key in self
231 return _is_section_key(key) and key in self
212
232
213 def copy(self):
233 def copy(self):
214 return type(self)(dict.copy(self))
234 return type(self)(dict.copy(self))
215
235
216 def __copy__(self):
236 def __copy__(self):
217 return self.copy()
237 return self.copy()
218
238
219 def __deepcopy__(self, memo):
239 def __deepcopy__(self, memo):
220 import copy
240 import copy
221 return type(self)(copy.deepcopy(list(self.items())))
241 return type(self)(copy.deepcopy(list(self.items())))
222
242
223 def __getitem__(self, key):
243 def __getitem__(self, key):
224 try:
244 try:
225 return dict.__getitem__(self, key)
245 return dict.__getitem__(self, key)
226 except KeyError:
246 except KeyError:
227 if _is_section_key(key):
247 if _is_section_key(key):
228 c = Config()
248 c = Config()
229 dict.__setitem__(self, key, c)
249 dict.__setitem__(self, key, c)
230 return c
250 return c
231 elif not key.startswith('_'):
251 elif not key.startswith('_'):
232 # undefined, create lazy value, used for container methods
252 # undefined, create lazy value, used for container methods
233 v = LazyConfigValue()
253 v = LazyConfigValue()
234 dict.__setitem__(self, key, v)
254 dict.__setitem__(self, key, v)
235 return v
255 return v
236 else:
256 else:
237 raise KeyError
257 raise KeyError
238
258
239 def __setitem__(self, key, value):
259 def __setitem__(self, key, value):
240 if _is_section_key(key):
260 if _is_section_key(key):
241 if not isinstance(value, Config):
261 if not isinstance(value, Config):
242 raise ValueError('values whose keys begin with an uppercase '
262 raise ValueError('values whose keys begin with an uppercase '
243 'char must be Config instances: %r, %r' % (key, value))
263 'char must be Config instances: %r, %r' % (key, value))
244 dict.__setitem__(self, key, value)
264 dict.__setitem__(self, key, value)
245
265
246 def __getattr__(self, key):
266 def __getattr__(self, key):
247 if key.startswith('__'):
267 if key.startswith('__'):
248 return dict.__getattr__(self, key)
268 return dict.__getattr__(self, key)
249 try:
269 try:
250 return self.__getitem__(key)
270 return self.__getitem__(key)
251 except KeyError as e:
271 except KeyError as e:
252 raise AttributeError(e)
272 raise AttributeError(e)
253
273
254 def __setattr__(self, key, value):
274 def __setattr__(self, key, value):
255 if key.startswith('__'):
275 if key.startswith('__'):
256 return dict.__setattr__(self, key, value)
276 return dict.__setattr__(self, key, value)
257 try:
277 try:
258 self.__setitem__(key, value)
278 self.__setitem__(key, value)
259 except KeyError as e:
279 except KeyError as e:
260 raise AttributeError(e)
280 raise AttributeError(e)
261
281
262 def __delattr__(self, key):
282 def __delattr__(self, key):
263 if key.startswith('__'):
283 if key.startswith('__'):
264 return dict.__delattr__(self, key)
284 return dict.__delattr__(self, key)
265 try:
285 try:
266 dict.__delitem__(self, key)
286 dict.__delitem__(self, key)
267 except KeyError as e:
287 except KeyError as e:
268 raise AttributeError(e)
288 raise AttributeError(e)
269
289
270
290
271 #-----------------------------------------------------------------------------
291 #-----------------------------------------------------------------------------
272 # Config loading classes
292 # Config loading classes
273 #-----------------------------------------------------------------------------
293 #-----------------------------------------------------------------------------
274
294
275
295
276 class ConfigLoader(object):
296 class ConfigLoader(object):
277 """A object for loading configurations from just about anywhere.
297 """A object for loading configurations from just about anywhere.
278
298
279 The resulting configuration is packaged as a :class:`Config`.
299 The resulting configuration is packaged as a :class:`Config`.
280
300
281 Notes
301 Notes
282 -----
302 -----
283 A :class:`ConfigLoader` does one thing: load a config from a source
303 A :class:`ConfigLoader` does one thing: load a config from a source
284 (file, command line arguments) and returns the data as a :class:`Config` object.
304 (file, command line arguments) and returns the data as a :class:`Config` object.
285 There are lots of things that :class:`ConfigLoader` does not do. It does
305 There are lots of things that :class:`ConfigLoader` does not do. It does
286 not implement complex logic for finding config files. It does not handle
306 not implement complex logic for finding config files. It does not handle
287 default values or merge multiple configs. These things need to be
307 default values or merge multiple configs. These things need to be
288 handled elsewhere.
308 handled elsewhere.
289 """
309 """
290
310
291 def _log_default(self):
311 def _log_default(self):
292 from IPython.utils.log import get_logger
312 from IPython.utils.log import get_logger
293 return get_logger()
313 return get_logger()
294
314
295 def __init__(self, log=None):
315 def __init__(self, log=None):
296 """A base class for config loaders.
316 """A base class for config loaders.
297
317
298 log : instance of :class:`logging.Logger` to use.
318 log : instance of :class:`logging.Logger` to use.
299 By default loger of :meth:`IPython.config.application.Application.instance()`
319 By default loger of :meth:`IPython.config.application.Application.instance()`
300 will be used
320 will be used
301
321
302 Examples
322 Examples
303 --------
323 --------
304
324
305 >>> cl = ConfigLoader()
325 >>> cl = ConfigLoader()
306 >>> config = cl.load_config()
326 >>> config = cl.load_config()
307 >>> config
327 >>> config
308 {}
328 {}
309 """
329 """
310 self.clear()
330 self.clear()
311 if log is None:
331 if log is None:
312 self.log = self._log_default()
332 self.log = self._log_default()
313 self.log.debug('Using default logger')
333 self.log.debug('Using default logger')
314 else:
334 else:
315 self.log = log
335 self.log = log
316
336
317 def clear(self):
337 def clear(self):
318 self.config = Config()
338 self.config = Config()
319
339
320 def load_config(self):
340 def load_config(self):
321 """Load a config from somewhere, return a :class:`Config` instance.
341 """Load a config from somewhere, return a :class:`Config` instance.
322
342
323 Usually, this will cause self.config to be set and then returned.
343 Usually, this will cause self.config to be set and then returned.
324 However, in most cases, :meth:`ConfigLoader.clear` should be called
344 However, in most cases, :meth:`ConfigLoader.clear` should be called
325 to erase any previous state.
345 to erase any previous state.
326 """
346 """
327 self.clear()
347 self.clear()
328 return self.config
348 return self.config
329
349
330
350
331 class FileConfigLoader(ConfigLoader):
351 class FileConfigLoader(ConfigLoader):
332 """A base class for file based configurations.
352 """A base class for file based configurations.
333
353
334 As we add more file based config loaders, the common logic should go
354 As we add more file based config loaders, the common logic should go
335 here.
355 here.
336 """
356 """
337
357
338 def __init__(self, filename, path=None, **kw):
358 def __init__(self, filename, path=None, **kw):
339 """Build a config loader for a filename and path.
359 """Build a config loader for a filename and path.
340
360
341 Parameters
361 Parameters
342 ----------
362 ----------
343 filename : str
363 filename : str
344 The file name of the config file.
364 The file name of the config file.
345 path : str, list, tuple
365 path : str, list, tuple
346 The path to search for the config file on, or a sequence of
366 The path to search for the config file on, or a sequence of
347 paths to try in order.
367 paths to try in order.
348 """
368 """
349 super(FileConfigLoader, self).__init__(**kw)
369 super(FileConfigLoader, self).__init__(**kw)
350 self.filename = filename
370 self.filename = filename
351 self.path = path
371 self.path = path
352 self.full_filename = ''
372 self.full_filename = ''
353
373
354 def _find_file(self):
374 def _find_file(self):
355 """Try to find the file by searching the paths."""
375 """Try to find the file by searching the paths."""
356 self.full_filename = filefind(self.filename, self.path)
376 self.full_filename = filefind(self.filename, self.path)
357
377
358 class JSONFileConfigLoader(FileConfigLoader):
378 class JSONFileConfigLoader(FileConfigLoader):
359 """A Json file loader for config"""
379 """A Json file loader for config"""
360
380
361 def load_config(self):
381 def load_config(self):
362 """Load the config from a file and return it as a Config object."""
382 """Load the config from a file and return it as a Config object."""
363 self.clear()
383 self.clear()
364 try:
384 try:
365 self._find_file()
385 self._find_file()
366 except IOError as e:
386 except IOError as e:
367 raise ConfigFileNotFound(str(e))
387 raise ConfigFileNotFound(str(e))
368 dct = self._read_file_as_dict()
388 dct = self._read_file_as_dict()
369 self.config = self._convert_to_config(dct)
389 self.config = self._convert_to_config(dct)
370 return self.config
390 return self.config
371
391
372 def _read_file_as_dict(self):
392 def _read_file_as_dict(self):
373 with open(self.full_filename) as f:
393 with open(self.full_filename) as f:
374 return json.load(f)
394 return json.load(f)
375
395
376 def _convert_to_config(self, dictionary):
396 def _convert_to_config(self, dictionary):
377 if 'version' in dictionary:
397 if 'version' in dictionary:
378 version = dictionary.pop('version')
398 version = dictionary.pop('version')
379 else:
399 else:
380 version = 1
400 version = 1
381 self.log.warn("Unrecognized JSON config file version, assuming version {}".format(version))
401 self.log.warn("Unrecognized JSON config file version, assuming version {}".format(version))
382
402
383 if version == 1:
403 if version == 1:
384 return Config(dictionary)
404 return Config(dictionary)
385 else:
405 else:
386 raise ValueError('Unknown version of JSON config file: {version}'.format(version=version))
406 raise ValueError('Unknown version of JSON config file: {version}'.format(version=version))
387
407
388
408
389 class PyFileConfigLoader(FileConfigLoader):
409 class PyFileConfigLoader(FileConfigLoader):
390 """A config loader for pure python files.
410 """A config loader for pure python files.
391
411
392 This is responsible for locating a Python config file by filename and
412 This is responsible for locating a Python config file by filename and
393 path, then executing it to construct a Config object.
413 path, then executing it to construct a Config object.
394 """
414 """
395
415
396 def load_config(self):
416 def load_config(self):
397 """Load the config from a file and return it as a Config object."""
417 """Load the config from a file and return it as a Config object."""
398 self.clear()
418 self.clear()
399 try:
419 try:
400 self._find_file()
420 self._find_file()
401 except IOError as e:
421 except IOError as e:
402 raise ConfigFileNotFound(str(e))
422 raise ConfigFileNotFound(str(e))
403 self._read_file_as_dict()
423 self._read_file_as_dict()
404 return self.config
424 return self.config
405
425
406
426
407 def _read_file_as_dict(self):
427 def _read_file_as_dict(self):
408 """Load the config file into self.config, with recursive loading."""
428 """Load the config file into self.config, with recursive loading."""
409 # This closure is made available in the namespace that is used
429 # This closure is made available in the namespace that is used
410 # to exec the config file. It allows users to call
430 # to exec the config file. It allows users to call
411 # load_subconfig('myconfig.py') to load config files recursively.
431 # load_subconfig('myconfig.py') to load config files recursively.
412 # It needs to be a closure because it has references to self.path
432 # It needs to be a closure because it has references to self.path
413 # and self.config. The sub-config is loaded with the same path
433 # and self.config. The sub-config is loaded with the same path
414 # as the parent, but it uses an empty config which is then merged
434 # as the parent, but it uses an empty config which is then merged
415 # with the parents.
435 # with the parents.
416
436
417 # If a profile is specified, the config file will be loaded
437 # If a profile is specified, the config file will be loaded
418 # from that profile
438 # from that profile
419
439
420 def load_subconfig(fname, profile=None):
440 def load_subconfig(fname, profile=None):
421 # import here to prevent circular imports
441 # import here to prevent circular imports
422 from IPython.core.profiledir import ProfileDir, ProfileDirError
442 from IPython.core.profiledir import ProfileDir, ProfileDirError
423 if profile is not None:
443 if profile is not None:
424 try:
444 try:
425 profile_dir = ProfileDir.find_profile_dir_by_name(
445 profile_dir = ProfileDir.find_profile_dir_by_name(
426 get_ipython_dir(),
446 get_ipython_dir(),
427 profile,
447 profile,
428 )
448 )
429 except ProfileDirError:
449 except ProfileDirError:
430 return
450 return
431 path = profile_dir.location
451 path = profile_dir.location
432 else:
452 else:
433 path = self.path
453 path = self.path
434 loader = PyFileConfigLoader(fname, path)
454 loader = PyFileConfigLoader(fname, path)
435 try:
455 try:
436 sub_config = loader.load_config()
456 sub_config = loader.load_config()
437 except ConfigFileNotFound:
457 except ConfigFileNotFound:
438 # Pass silently if the sub config is not there. This happens
458 # Pass silently if the sub config is not there. This happens
439 # when a user s using a profile, but not the default config.
459 # when a user s using a profile, but not the default config.
440 pass
460 pass
441 else:
461 else:
442 self.config.merge(sub_config)
462 self.config.merge(sub_config)
443
463
444 # Again, this needs to be a closure and should be used in config
464 # Again, this needs to be a closure and should be used in config
445 # files to get the config being loaded.
465 # files to get the config being loaded.
446 def get_config():
466 def get_config():
447 return self.config
467 return self.config
448
468
449 namespace = dict(
469 namespace = dict(
450 load_subconfig=load_subconfig,
470 load_subconfig=load_subconfig,
451 get_config=get_config,
471 get_config=get_config,
452 __file__=self.full_filename,
472 __file__=self.full_filename,
453 )
473 )
454 fs_encoding = sys.getfilesystemencoding() or 'ascii'
474 fs_encoding = sys.getfilesystemencoding() or 'ascii'
455 conf_filename = self.full_filename.encode(fs_encoding)
475 conf_filename = self.full_filename.encode(fs_encoding)
456 py3compat.execfile(conf_filename, namespace)
476 py3compat.execfile(conf_filename, namespace)
457
477
458
478
459 class CommandLineConfigLoader(ConfigLoader):
479 class CommandLineConfigLoader(ConfigLoader):
460 """A config loader for command line arguments.
480 """A config loader for command line arguments.
461
481
462 As we add more command line based loaders, the common logic should go
482 As we add more command line based loaders, the common logic should go
463 here.
483 here.
464 """
484 """
465
485
466 def _exec_config_str(self, lhs, rhs):
486 def _exec_config_str(self, lhs, rhs):
467 """execute self.config.<lhs> = <rhs>
487 """execute self.config.<lhs> = <rhs>
468
488
469 * expands ~ with expanduser
489 * expands ~ with expanduser
470 * tries to assign with raw eval, otherwise assigns with just the string,
490 * tries to assign with raw eval, otherwise assigns with just the string,
471 allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not*
491 allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not*
472 equivalent are `--C.a=4` and `--C.a='4'`.
492 equivalent are `--C.a=4` and `--C.a='4'`.
473 """
493 """
474 rhs = os.path.expanduser(rhs)
494 rhs = os.path.expanduser(rhs)
475 try:
495 try:
476 # Try to see if regular Python syntax will work. This
496 # Try to see if regular Python syntax will work. This
477 # won't handle strings as the quote marks are removed
497 # won't handle strings as the quote marks are removed
478 # by the system shell.
498 # by the system shell.
479 value = eval(rhs)
499 value = eval(rhs)
480 except (NameError, SyntaxError):
500 except (NameError, SyntaxError):
481 # This case happens if the rhs is a string.
501 # This case happens if the rhs is a string.
482 value = rhs
502 value = rhs
483
503
484 exec(u'self.config.%s = value' % lhs)
504 exec(u'self.config.%s = value' % lhs)
485
505
486 def _load_flag(self, cfg):
506 def _load_flag(self, cfg):
487 """update self.config from a flag, which can be a dict or Config"""
507 """update self.config from a flag, which can be a dict or Config"""
488 if isinstance(cfg, (dict, Config)):
508 if isinstance(cfg, (dict, Config)):
489 # don't clobber whole config sections, update
509 # don't clobber whole config sections, update
490 # each section from config:
510 # each section from config:
491 for sec,c in iteritems(cfg):
511 for sec,c in iteritems(cfg):
492 self.config[sec].update(c)
512 self.config[sec].update(c)
493 else:
513 else:
494 raise TypeError("Invalid flag: %r" % cfg)
514 raise TypeError("Invalid flag: %r" % cfg)
495
515
496 # raw --identifier=value pattern
516 # raw --identifier=value pattern
497 # but *also* accept '-' as wordsep, for aliases
517 # but *also* accept '-' as wordsep, for aliases
498 # accepts: --foo=a
518 # accepts: --foo=a
499 # --Class.trait=value
519 # --Class.trait=value
500 # --alias-name=value
520 # --alias-name=value
501 # rejects: -foo=value
521 # rejects: -foo=value
502 # --foo
522 # --foo
503 # --Class.trait
523 # --Class.trait
504 kv_pattern = re.compile(r'\-\-[A-Za-z][\w\-]*(\.[\w\-]+)*\=.*')
524 kv_pattern = re.compile(r'\-\-[A-Za-z][\w\-]*(\.[\w\-]+)*\=.*')
505
525
506 # just flags, no assignments, with two *or one* leading '-'
526 # just flags, no assignments, with two *or one* leading '-'
507 # accepts: --foo
527 # accepts: --foo
508 # -foo-bar-again
528 # -foo-bar-again
509 # rejects: --anything=anything
529 # rejects: --anything=anything
510 # --two.word
530 # --two.word
511
531
512 flag_pattern = re.compile(r'\-\-?\w+[\-\w]*$')
532 flag_pattern = re.compile(r'\-\-?\w+[\-\w]*$')
513
533
514 class KeyValueConfigLoader(CommandLineConfigLoader):
534 class KeyValueConfigLoader(CommandLineConfigLoader):
515 """A config loader that loads key value pairs from the command line.
535 """A config loader that loads key value pairs from the command line.
516
536
517 This allows command line options to be gives in the following form::
537 This allows command line options to be gives in the following form::
518
538
519 ipython --profile="foo" --InteractiveShell.autocall=False
539 ipython --profile="foo" --InteractiveShell.autocall=False
520 """
540 """
521
541
522 def __init__(self, argv=None, aliases=None, flags=None, **kw):
542 def __init__(self, argv=None, aliases=None, flags=None, **kw):
523 """Create a key value pair config loader.
543 """Create a key value pair config loader.
524
544
525 Parameters
545 Parameters
526 ----------
546 ----------
527 argv : list
547 argv : list
528 A list that has the form of sys.argv[1:] which has unicode
548 A list that has the form of sys.argv[1:] which has unicode
529 elements of the form u"key=value". If this is None (default),
549 elements of the form u"key=value". If this is None (default),
530 then sys.argv[1:] will be used.
550 then sys.argv[1:] will be used.
531 aliases : dict
551 aliases : dict
532 A dict of aliases for configurable traits.
552 A dict of aliases for configurable traits.
533 Keys are the short aliases, Values are the resolved trait.
553 Keys are the short aliases, Values are the resolved trait.
534 Of the form: `{'alias' : 'Configurable.trait'}`
554 Of the form: `{'alias' : 'Configurable.trait'}`
535 flags : dict
555 flags : dict
536 A dict of flags, keyed by str name. Vaues can be Config objects,
556 A dict of flags, keyed by str name. Vaues can be Config objects,
537 dicts, or "key=value" strings. If Config or dict, when the flag
557 dicts, or "key=value" strings. If Config or dict, when the flag
538 is triggered, The flag is loaded as `self.config.update(m)`.
558 is triggered, The flag is loaded as `self.config.update(m)`.
539
559
540 Returns
560 Returns
541 -------
561 -------
542 config : Config
562 config : Config
543 The resulting Config object.
563 The resulting Config object.
544
564
545 Examples
565 Examples
546 --------
566 --------
547
567
548 >>> from IPython.config.loader import KeyValueConfigLoader
568 >>> from IPython.config.loader import KeyValueConfigLoader
549 >>> cl = KeyValueConfigLoader()
569 >>> cl = KeyValueConfigLoader()
550 >>> d = cl.load_config(["--A.name='brian'","--B.number=0"])
570 >>> d = cl.load_config(["--A.name='brian'","--B.number=0"])
551 >>> sorted(d.items())
571 >>> sorted(d.items())
552 [('A', {'name': 'brian'}), ('B', {'number': 0})]
572 [('A', {'name': 'brian'}), ('B', {'number': 0})]
553 """
573 """
554 super(KeyValueConfigLoader, self).__init__(**kw)
574 super(KeyValueConfigLoader, self).__init__(**kw)
555 if argv is None:
575 if argv is None:
556 argv = sys.argv[1:]
576 argv = sys.argv[1:]
557 self.argv = argv
577 self.argv = argv
558 self.aliases = aliases or {}
578 self.aliases = aliases or {}
559 self.flags = flags or {}
579 self.flags = flags or {}
560
580
561
581
562 def clear(self):
582 def clear(self):
563 super(KeyValueConfigLoader, self).clear()
583 super(KeyValueConfigLoader, self).clear()
564 self.extra_args = []
584 self.extra_args = []
565
585
566
586
567 def _decode_argv(self, argv, enc=None):
587 def _decode_argv(self, argv, enc=None):
568 """decode argv if bytes, using stin.encoding, falling back on default enc"""
588 """decode argv if bytes, using stdin.encoding, falling back on default enc"""
569 uargv = []
589 uargv = []
570 if enc is None:
590 if enc is None:
571 enc = DEFAULT_ENCODING
591 enc = DEFAULT_ENCODING
572 for arg in argv:
592 for arg in argv:
573 if not isinstance(arg, unicode_type):
593 if not isinstance(arg, unicode_type):
574 # only decode if not already decoded
594 # only decode if not already decoded
575 arg = arg.decode(enc)
595 arg = arg.decode(enc)
576 uargv.append(arg)
596 uargv.append(arg)
577 return uargv
597 return uargv
578
598
579
599
580 def load_config(self, argv=None, aliases=None, flags=None):
600 def load_config(self, argv=None, aliases=None, flags=None):
581 """Parse the configuration and generate the Config object.
601 """Parse the configuration and generate the Config object.
582
602
583 After loading, any arguments that are not key-value or
603 After loading, any arguments that are not key-value or
584 flags will be stored in self.extra_args - a list of
604 flags will be stored in self.extra_args - a list of
585 unparsed command-line arguments. This is used for
605 unparsed command-line arguments. This is used for
586 arguments such as input files or subcommands.
606 arguments such as input files or subcommands.
587
607
588 Parameters
608 Parameters
589 ----------
609 ----------
590 argv : list, optional
610 argv : list, optional
591 A list that has the form of sys.argv[1:] which has unicode
611 A list that has the form of sys.argv[1:] which has unicode
592 elements of the form u"key=value". If this is None (default),
612 elements of the form u"key=value". If this is None (default),
593 then self.argv will be used.
613 then self.argv will be used.
594 aliases : dict
614 aliases : dict
595 A dict of aliases for configurable traits.
615 A dict of aliases for configurable traits.
596 Keys are the short aliases, Values are the resolved trait.
616 Keys are the short aliases, Values are the resolved trait.
597 Of the form: `{'alias' : 'Configurable.trait'}`
617 Of the form: `{'alias' : 'Configurable.trait'}`
598 flags : dict
618 flags : dict
599 A dict of flags, keyed by str name. Values can be Config objects
619 A dict of flags, keyed by str name. Values can be Config objects
600 or dicts. When the flag is triggered, The config is loaded as
620 or dicts. When the flag is triggered, The config is loaded as
601 `self.config.update(cfg)`.
621 `self.config.update(cfg)`.
602 """
622 """
603 self.clear()
623 self.clear()
604 if argv is None:
624 if argv is None:
605 argv = self.argv
625 argv = self.argv
606 if aliases is None:
626 if aliases is None:
607 aliases = self.aliases
627 aliases = self.aliases
608 if flags is None:
628 if flags is None:
609 flags = self.flags
629 flags = self.flags
610
630
611 # ensure argv is a list of unicode strings:
631 # ensure argv is a list of unicode strings:
612 uargv = self._decode_argv(argv)
632 uargv = self._decode_argv(argv)
613 for idx,raw in enumerate(uargv):
633 for idx,raw in enumerate(uargv):
614 # strip leading '-'
634 # strip leading '-'
615 item = raw.lstrip('-')
635 item = raw.lstrip('-')
616
636
617 if raw == '--':
637 if raw == '--':
618 # don't parse arguments after '--'
638 # don't parse arguments after '--'
619 # this is useful for relaying arguments to scripts, e.g.
639 # this is useful for relaying arguments to scripts, e.g.
620 # ipython -i foo.py --matplotlib=qt -- args after '--' go-to-foo.py
640 # ipython -i foo.py --matplotlib=qt -- args after '--' go-to-foo.py
621 self.extra_args.extend(uargv[idx+1:])
641 self.extra_args.extend(uargv[idx+1:])
622 break
642 break
623
643
624 if kv_pattern.match(raw):
644 if kv_pattern.match(raw):
625 lhs,rhs = item.split('=',1)
645 lhs,rhs = item.split('=',1)
626 # Substitute longnames for aliases.
646 # Substitute longnames for aliases.
627 if lhs in aliases:
647 if lhs in aliases:
628 lhs = aliases[lhs]
648 lhs = aliases[lhs]
629 if '.' not in lhs:
649 if '.' not in lhs:
630 # probably a mistyped alias, but not technically illegal
650 # probably a mistyped alias, but not technically illegal
631 self.log.warn("Unrecognized alias: '%s', it will probably have no effect.", raw)
651 self.log.warn("Unrecognized alias: '%s', it will probably have no effect.", raw)
632 try:
652 try:
633 self._exec_config_str(lhs, rhs)
653 self._exec_config_str(lhs, rhs)
634 except Exception:
654 except Exception:
635 raise ArgumentError("Invalid argument: '%s'" % raw)
655 raise ArgumentError("Invalid argument: '%s'" % raw)
636
656
637 elif flag_pattern.match(raw):
657 elif flag_pattern.match(raw):
638 if item in flags:
658 if item in flags:
639 cfg,help = flags[item]
659 cfg,help = flags[item]
640 self._load_flag(cfg)
660 self._load_flag(cfg)
641 else:
661 else:
642 raise ArgumentError("Unrecognized flag: '%s'"%raw)
662 raise ArgumentError("Unrecognized flag: '%s'"%raw)
643 elif raw.startswith('-'):
663 elif raw.startswith('-'):
644 kv = '--'+item
664 kv = '--'+item
645 if kv_pattern.match(kv):
665 if kv_pattern.match(kv):
646 raise ArgumentError("Invalid argument: '%s', did you mean '%s'?"%(raw, kv))
666 raise ArgumentError("Invalid argument: '%s', did you mean '%s'?"%(raw, kv))
647 else:
667 else:
648 raise ArgumentError("Invalid argument: '%s'"%raw)
668 raise ArgumentError("Invalid argument: '%s'"%raw)
649 else:
669 else:
650 # keep all args that aren't valid in a list,
670 # keep all args that aren't valid in a list,
651 # in case our parent knows what to do with them.
671 # in case our parent knows what to do with them.
652 self.extra_args.append(item)
672 self.extra_args.append(item)
653 return self.config
673 return self.config
654
674
655 class ArgParseConfigLoader(CommandLineConfigLoader):
675 class ArgParseConfigLoader(CommandLineConfigLoader):
656 """A loader that uses the argparse module to load from the command line."""
676 """A loader that uses the argparse module to load from the command line."""
657
677
658 def __init__(self, argv=None, aliases=None, flags=None, log=None, *parser_args, **parser_kw):
678 def __init__(self, argv=None, aliases=None, flags=None, log=None, *parser_args, **parser_kw):
659 """Create a config loader for use with argparse.
679 """Create a config loader for use with argparse.
660
680
661 Parameters
681 Parameters
662 ----------
682 ----------
663
683
664 argv : optional, list
684 argv : optional, list
665 If given, used to read command-line arguments from, otherwise
685 If given, used to read command-line arguments from, otherwise
666 sys.argv[1:] is used.
686 sys.argv[1:] is used.
667
687
668 parser_args : tuple
688 parser_args : tuple
669 A tuple of positional arguments that will be passed to the
689 A tuple of positional arguments that will be passed to the
670 constructor of :class:`argparse.ArgumentParser`.
690 constructor of :class:`argparse.ArgumentParser`.
671
691
672 parser_kw : dict
692 parser_kw : dict
673 A tuple of keyword arguments that will be passed to the
693 A tuple of keyword arguments that will be passed to the
674 constructor of :class:`argparse.ArgumentParser`.
694 constructor of :class:`argparse.ArgumentParser`.
675
695
676 Returns
696 Returns
677 -------
697 -------
678 config : Config
698 config : Config
679 The resulting Config object.
699 The resulting Config object.
680 """
700 """
681 super(CommandLineConfigLoader, self).__init__(log=log)
701 super(CommandLineConfigLoader, self).__init__(log=log)
682 self.clear()
702 self.clear()
683 if argv is None:
703 if argv is None:
684 argv = sys.argv[1:]
704 argv = sys.argv[1:]
685 self.argv = argv
705 self.argv = argv
686 self.aliases = aliases or {}
706 self.aliases = aliases or {}
687 self.flags = flags or {}
707 self.flags = flags or {}
688
708
689 self.parser_args = parser_args
709 self.parser_args = parser_args
690 self.version = parser_kw.pop("version", None)
710 self.version = parser_kw.pop("version", None)
691 kwargs = dict(argument_default=argparse.SUPPRESS)
711 kwargs = dict(argument_default=argparse.SUPPRESS)
692 kwargs.update(parser_kw)
712 kwargs.update(parser_kw)
693 self.parser_kw = kwargs
713 self.parser_kw = kwargs
694
714
695 def load_config(self, argv=None, aliases=None, flags=None):
715 def load_config(self, argv=None, aliases=None, flags=None):
696 """Parse command line arguments and return as a Config object.
716 """Parse command line arguments and return as a Config object.
697
717
698 Parameters
718 Parameters
699 ----------
719 ----------
700
720
701 args : optional, list
721 args : optional, list
702 If given, a list with the structure of sys.argv[1:] to parse
722 If given, a list with the structure of sys.argv[1:] to parse
703 arguments from. If not given, the instance's self.argv attribute
723 arguments from. If not given, the instance's self.argv attribute
704 (given at construction time) is used."""
724 (given at construction time) is used."""
705 self.clear()
725 self.clear()
706 if argv is None:
726 if argv is None:
707 argv = self.argv
727 argv = self.argv
708 if aliases is None:
728 if aliases is None:
709 aliases = self.aliases
729 aliases = self.aliases
710 if flags is None:
730 if flags is None:
711 flags = self.flags
731 flags = self.flags
712 self._create_parser(aliases, flags)
732 self._create_parser(aliases, flags)
713 self._parse_args(argv)
733 self._parse_args(argv)
714 self._convert_to_config()
734 self._convert_to_config()
715 return self.config
735 return self.config
716
736
717 def get_extra_args(self):
737 def get_extra_args(self):
718 if hasattr(self, 'extra_args'):
738 if hasattr(self, 'extra_args'):
719 return self.extra_args
739 return self.extra_args
720 else:
740 else:
721 return []
741 return []
722
742
723 def _create_parser(self, aliases=None, flags=None):
743 def _create_parser(self, aliases=None, flags=None):
724 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
744 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
725 self._add_arguments(aliases, flags)
745 self._add_arguments(aliases, flags)
726
746
727 def _add_arguments(self, aliases=None, flags=None):
747 def _add_arguments(self, aliases=None, flags=None):
728 raise NotImplementedError("subclasses must implement _add_arguments")
748 raise NotImplementedError("subclasses must implement _add_arguments")
729
749
730 def _parse_args(self, args):
750 def _parse_args(self, args):
731 """self.parser->self.parsed_data"""
751 """self.parser->self.parsed_data"""
732 # decode sys.argv to support unicode command-line options
752 # decode sys.argv to support unicode command-line options
733 enc = DEFAULT_ENCODING
753 enc = DEFAULT_ENCODING
734 uargs = [py3compat.cast_unicode(a, enc) for a in args]
754 uargs = [py3compat.cast_unicode(a, enc) for a in args]
735 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
755 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
736
756
737 def _convert_to_config(self):
757 def _convert_to_config(self):
738 """self.parsed_data->self.config"""
758 """self.parsed_data->self.config"""
739 for k, v in iteritems(vars(self.parsed_data)):
759 for k, v in iteritems(vars(self.parsed_data)):
740 exec("self.config.%s = v"%k, locals(), globals())
760 exec("self.config.%s = v"%k, locals(), globals())
741
761
742 class KVArgParseConfigLoader(ArgParseConfigLoader):
762 class KVArgParseConfigLoader(ArgParseConfigLoader):
743 """A config loader that loads aliases and flags with argparse,
763 """A config loader that loads aliases and flags with argparse,
744 but will use KVLoader for the rest. This allows better parsing
764 but will use KVLoader for the rest. This allows better parsing
745 of common args, such as `ipython -c 'print 5'`, but still gets
765 of common args, such as `ipython -c 'print 5'`, but still gets
746 arbitrary config with `ipython --InteractiveShell.use_readline=False`"""
766 arbitrary config with `ipython --InteractiveShell.use_readline=False`"""
747
767
748 def _add_arguments(self, aliases=None, flags=None):
768 def _add_arguments(self, aliases=None, flags=None):
749 self.alias_flags = {}
769 self.alias_flags = {}
750 # print aliases, flags
770 # print aliases, flags
751 if aliases is None:
771 if aliases is None:
752 aliases = self.aliases
772 aliases = self.aliases
753 if flags is None:
773 if flags is None:
754 flags = self.flags
774 flags = self.flags
755 paa = self.parser.add_argument
775 paa = self.parser.add_argument
756 for key,value in iteritems(aliases):
776 for key,value in iteritems(aliases):
757 if key in flags:
777 if key in flags:
758 # flags
778 # flags
759 nargs = '?'
779 nargs = '?'
760 else:
780 else:
761 nargs = None
781 nargs = None
762 if len(key) is 1:
782 if len(key) is 1:
763 paa('-'+key, '--'+key, type=unicode_type, dest=value, nargs=nargs)
783 paa('-'+key, '--'+key, type=unicode_type, dest=value, nargs=nargs)
764 else:
784 else:
765 paa('--'+key, type=unicode_type, dest=value, nargs=nargs)
785 paa('--'+key, type=unicode_type, dest=value, nargs=nargs)
766 for key, (value, help) in iteritems(flags):
786 for key, (value, help) in iteritems(flags):
767 if key in self.aliases:
787 if key in self.aliases:
768 #
788 #
769 self.alias_flags[self.aliases[key]] = value
789 self.alias_flags[self.aliases[key]] = value
770 continue
790 continue
771 if len(key) is 1:
791 if len(key) is 1:
772 paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)
792 paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)
773 else:
793 else:
774 paa('--'+key, action='append_const', dest='_flags', const=value)
794 paa('--'+key, action='append_const', dest='_flags', const=value)
775
795
776 def _convert_to_config(self):
796 def _convert_to_config(self):
777 """self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
797 """self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
778 # remove subconfigs list from namespace before transforming the Namespace
798 # remove subconfigs list from namespace before transforming the Namespace
779 if '_flags' in self.parsed_data:
799 if '_flags' in self.parsed_data:
780 subcs = self.parsed_data._flags
800 subcs = self.parsed_data._flags
781 del self.parsed_data._flags
801 del self.parsed_data._flags
782 else:
802 else:
783 subcs = []
803 subcs = []
784
804
785 for k, v in iteritems(vars(self.parsed_data)):
805 for k, v in iteritems(vars(self.parsed_data)):
786 if v is None:
806 if v is None:
787 # it was a flag that shares the name of an alias
807 # it was a flag that shares the name of an alias
788 subcs.append(self.alias_flags[k])
808 subcs.append(self.alias_flags[k])
789 else:
809 else:
790 # eval the KV assignment
810 # eval the KV assignment
791 self._exec_config_str(k, v)
811 self._exec_config_str(k, v)
792
812
793 for subc in subcs:
813 for subc in subcs:
794 self._load_flag(subc)
814 self._load_flag(subc)
795
815
796 if self.extra_args:
816 if self.extra_args:
797 sub_parser = KeyValueConfigLoader(log=self.log)
817 sub_parser = KeyValueConfigLoader(log=self.log)
798 sub_parser.load_config(self.extra_args)
818 sub_parser.load_config(self.extra_args)
799 self.config.merge(sub_parser.config)
819 self.config.merge(sub_parser.config)
800 self.extra_args = sub_parser.extra_args
820 self.extra_args = sub_parser.extra_args
801
821
802
822
803 def load_pyconfig_files(config_files, path):
823 def load_pyconfig_files(config_files, path):
804 """Load multiple Python config files, merging each of them in turn.
824 """Load multiple Python config files, merging each of them in turn.
805
825
806 Parameters
826 Parameters
807 ==========
827 ==========
808 config_files : list of str
828 config_files : list of str
809 List of config files names to load and merge into the config.
829 List of config files names to load and merge into the config.
810 path : unicode
830 path : unicode
811 The full path to the location of the config files.
831 The full path to the location of the config files.
812 """
832 """
813 config = Config()
833 config = Config()
814 for cf in config_files:
834 for cf in config_files:
815 loader = PyFileConfigLoader(cf, path=path)
835 loader = PyFileConfigLoader(cf, path=path)
816 try:
836 try:
817 next_config = loader.load_config()
837 next_config = loader.load_config()
818 except ConfigFileNotFound:
838 except ConfigFileNotFound:
819 pass
839 pass
820 except:
840 except:
821 raise
841 raise
822 else:
842 else:
823 config.merge(next_config)
843 config.merge(next_config)
824 return config
844 return config
@@ -1,193 +1,198 b''
1 # coding: utf-8
1 # coding: utf-8
2 """
2 """
3 Tests for IPython.config.application.Application
3 Tests for IPython.config.application.Application
4
5 Authors:
6
7 * Brian Granger
8 """
4 """
9
5
10 #-----------------------------------------------------------------------------
6 # Copyright (c) IPython Development Team.
11 # Copyright (C) 2008-2011 The IPython Development Team
7 # Distributed under the terms of the Modified BSD License.
12 #
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
16
17 #-----------------------------------------------------------------------------
18 # Imports
19 #-----------------------------------------------------------------------------
20
8
21 import logging
9 import logging
10 import os
22 from io import StringIO
11 from io import StringIO
23 from unittest import TestCase
12 from unittest import TestCase
24
13
14 pjoin = os.path.join
15
25 import nose.tools as nt
16 import nose.tools as nt
26
17
27 from IPython.config.configurable import Configurable
18 from IPython.config.configurable import Configurable
28 from IPython.config.loader import Config
19 from IPython.config.loader import Config
29
20
30 from IPython.config.application import (
21 from IPython.config.application import (
31 Application
22 Application
32 )
23 )
33
24
25 from IPython.utils.tempdir import TemporaryDirectory
34 from IPython.utils.traitlets import (
26 from IPython.utils.traitlets import (
35 Bool, Unicode, Integer, List, Dict
27 Bool, Unicode, Integer, List, Dict
36 )
28 )
37
29
38 #-----------------------------------------------------------------------------
39 # Code
40 #-----------------------------------------------------------------------------
41
30
42 class Foo(Configurable):
31 class Foo(Configurable):
43
32
44 i = Integer(0, config=True, help="The integer i.")
33 i = Integer(0, config=True, help="The integer i.")
45 j = Integer(1, config=True, help="The integer j.")
34 j = Integer(1, config=True, help="The integer j.")
46 name = Unicode(u'Brian', config=True, help="First name.")
35 name = Unicode(u'Brian', config=True, help="First name.")
47
36
48
37
49 class Bar(Configurable):
38 class Bar(Configurable):
50
39
51 b = Integer(0, config=True, help="The integer b.")
40 b = Integer(0, config=True, help="The integer b.")
52 enabled = Bool(True, config=True, help="Enable bar.")
41 enabled = Bool(True, config=True, help="Enable bar.")
53
42
54
43
55 class MyApp(Application):
44 class MyApp(Application):
56
45
57 name = Unicode(u'myapp')
46 name = Unicode(u'myapp')
58 running = Bool(False, config=True,
47 running = Bool(False, config=True,
59 help="Is the app running?")
48 help="Is the app running?")
60 classes = List([Bar, Foo])
49 classes = List([Bar, Foo])
61 config_file = Unicode(u'', config=True,
50 config_file = Unicode(u'', config=True,
62 help="Load this config file")
51 help="Load this config file")
63
52
64 aliases = Dict({
53 aliases = Dict({
65 'i' : 'Foo.i',
54 'i' : 'Foo.i',
66 'j' : 'Foo.j',
55 'j' : 'Foo.j',
67 'name' : 'Foo.name',
56 'name' : 'Foo.name',
68 'enabled' : 'Bar.enabled',
57 'enabled' : 'Bar.enabled',
69 'log-level' : 'Application.log_level',
58 'log-level' : 'Application.log_level',
70 })
59 })
71
60
72 flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Set Bar.enabled to True"),
61 flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Set Bar.enabled to True"),
73 disable=({'Bar': {'enabled' : False}}, "Set Bar.enabled to False"),
62 disable=({'Bar': {'enabled' : False}}, "Set Bar.enabled to False"),
74 crit=({'Application' : {'log_level' : logging.CRITICAL}},
63 crit=({'Application' : {'log_level' : logging.CRITICAL}},
75 "set level=CRITICAL"),
64 "set level=CRITICAL"),
76 ))
65 ))
77
66
78 def init_foo(self):
67 def init_foo(self):
79 self.foo = Foo(parent=self)
68 self.foo = Foo(parent=self)
80
69
81 def init_bar(self):
70 def init_bar(self):
82 self.bar = Bar(parent=self)
71 self.bar = Bar(parent=self)
83
72
84
73
85 class TestApplication(TestCase):
74 class TestApplication(TestCase):
86
75
87 def test_log(self):
76 def test_log(self):
88 stream = StringIO()
77 stream = StringIO()
89 app = MyApp(log_level=logging.INFO)
78 app = MyApp(log_level=logging.INFO)
90 handler = logging.StreamHandler(stream)
79 handler = logging.StreamHandler(stream)
91 # trigger reconstruction of the log formatter
80 # trigger reconstruction of the log formatter
92 app.log.handlers = [handler]
81 app.log.handlers = [handler]
93 app.log_format = "%(message)s"
82 app.log_format = "%(message)s"
94 app.log.info("hello")
83 app.log.info("hello")
95 nt.assert_in("hello", stream.getvalue())
84 nt.assert_in("hello", stream.getvalue())
96
85
97 def test_basic(self):
86 def test_basic(self):
98 app = MyApp()
87 app = MyApp()
99 self.assertEqual(app.name, u'myapp')
88 self.assertEqual(app.name, u'myapp')
100 self.assertEqual(app.running, False)
89 self.assertEqual(app.running, False)
101 self.assertEqual(app.classes, [MyApp,Bar,Foo])
90 self.assertEqual(app.classes, [MyApp,Bar,Foo])
102 self.assertEqual(app.config_file, u'')
91 self.assertEqual(app.config_file, u'')
103
92
104 def test_config(self):
93 def test_config(self):
105 app = MyApp()
94 app = MyApp()
106 app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"])
95 app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"])
107 config = app.config
96 config = app.config
108 self.assertEqual(config.Foo.i, 10)
97 self.assertEqual(config.Foo.i, 10)
109 self.assertEqual(config.Foo.j, 10)
98 self.assertEqual(config.Foo.j, 10)
110 self.assertEqual(config.Bar.enabled, False)
99 self.assertEqual(config.Bar.enabled, False)
111 self.assertEqual(config.MyApp.log_level,50)
100 self.assertEqual(config.MyApp.log_level,50)
112
101
113 def test_config_propagation(self):
102 def test_config_propagation(self):
114 app = MyApp()
103 app = MyApp()
115 app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"])
104 app.parse_command_line(["--i=10","--Foo.j=10","--enabled=False","--log-level=50"])
116 app.init_foo()
105 app.init_foo()
117 app.init_bar()
106 app.init_bar()
118 self.assertEqual(app.foo.i, 10)
107 self.assertEqual(app.foo.i, 10)
119 self.assertEqual(app.foo.j, 10)
108 self.assertEqual(app.foo.j, 10)
120 self.assertEqual(app.bar.enabled, False)
109 self.assertEqual(app.bar.enabled, False)
121
110
122 def test_flags(self):
111 def test_flags(self):
123 app = MyApp()
112 app = MyApp()
124 app.parse_command_line(["--disable"])
113 app.parse_command_line(["--disable"])
125 app.init_bar()
114 app.init_bar()
126 self.assertEqual(app.bar.enabled, False)
115 self.assertEqual(app.bar.enabled, False)
127 app.parse_command_line(["--enable"])
116 app.parse_command_line(["--enable"])
128 app.init_bar()
117 app.init_bar()
129 self.assertEqual(app.bar.enabled, True)
118 self.assertEqual(app.bar.enabled, True)
130
119
131 def test_aliases(self):
120 def test_aliases(self):
132 app = MyApp()
121 app = MyApp()
133 app.parse_command_line(["--i=5", "--j=10"])
122 app.parse_command_line(["--i=5", "--j=10"])
134 app.init_foo()
123 app.init_foo()
135 self.assertEqual(app.foo.i, 5)
124 self.assertEqual(app.foo.i, 5)
136 app.init_foo()
125 app.init_foo()
137 self.assertEqual(app.foo.j, 10)
126 self.assertEqual(app.foo.j, 10)
138
127
139 def test_flag_clobber(self):
128 def test_flag_clobber(self):
140 """test that setting flags doesn't clobber existing settings"""
129 """test that setting flags doesn't clobber existing settings"""
141 app = MyApp()
130 app = MyApp()
142 app.parse_command_line(["--Bar.b=5", "--disable"])
131 app.parse_command_line(["--Bar.b=5", "--disable"])
143 app.init_bar()
132 app.init_bar()
144 self.assertEqual(app.bar.enabled, False)
133 self.assertEqual(app.bar.enabled, False)
145 self.assertEqual(app.bar.b, 5)
134 self.assertEqual(app.bar.b, 5)
146 app.parse_command_line(["--enable", "--Bar.b=10"])
135 app.parse_command_line(["--enable", "--Bar.b=10"])
147 app.init_bar()
136 app.init_bar()
148 self.assertEqual(app.bar.enabled, True)
137 self.assertEqual(app.bar.enabled, True)
149 self.assertEqual(app.bar.b, 10)
138 self.assertEqual(app.bar.b, 10)
150
139
151 def test_flatten_flags(self):
140 def test_flatten_flags(self):
152 cfg = Config()
141 cfg = Config()
153 cfg.MyApp.log_level = logging.WARN
142 cfg.MyApp.log_level = logging.WARN
154 app = MyApp()
143 app = MyApp()
155 app.update_config(cfg)
144 app.update_config(cfg)
156 self.assertEqual(app.log_level, logging.WARN)
145 self.assertEqual(app.log_level, logging.WARN)
157 self.assertEqual(app.config.MyApp.log_level, logging.WARN)
146 self.assertEqual(app.config.MyApp.log_level, logging.WARN)
158 app.initialize(["--crit"])
147 app.initialize(["--crit"])
159 self.assertEqual(app.log_level, logging.CRITICAL)
148 self.assertEqual(app.log_level, logging.CRITICAL)
160 # this would be app.config.Application.log_level if it failed:
149 # this would be app.config.Application.log_level if it failed:
161 self.assertEqual(app.config.MyApp.log_level, logging.CRITICAL)
150 self.assertEqual(app.config.MyApp.log_level, logging.CRITICAL)
162
151
163 def test_flatten_aliases(self):
152 def test_flatten_aliases(self):
164 cfg = Config()
153 cfg = Config()
165 cfg.MyApp.log_level = logging.WARN
154 cfg.MyApp.log_level = logging.WARN
166 app = MyApp()
155 app = MyApp()
167 app.update_config(cfg)
156 app.update_config(cfg)
168 self.assertEqual(app.log_level, logging.WARN)
157 self.assertEqual(app.log_level, logging.WARN)
169 self.assertEqual(app.config.MyApp.log_level, logging.WARN)
158 self.assertEqual(app.config.MyApp.log_level, logging.WARN)
170 app.initialize(["--log-level", "CRITICAL"])
159 app.initialize(["--log-level", "CRITICAL"])
171 self.assertEqual(app.log_level, logging.CRITICAL)
160 self.assertEqual(app.log_level, logging.CRITICAL)
172 # this would be app.config.Application.log_level if it failed:
161 # this would be app.config.Application.log_level if it failed:
173 self.assertEqual(app.config.MyApp.log_level, "CRITICAL")
162 self.assertEqual(app.config.MyApp.log_level, "CRITICAL")
174
163
175 def test_extra_args(self):
164 def test_extra_args(self):
176 app = MyApp()
165 app = MyApp()
177 app.parse_command_line(["--Bar.b=5", 'extra', "--disable", 'args'])
166 app.parse_command_line(["--Bar.b=5", 'extra', "--disable", 'args'])
178 app.init_bar()
167 app.init_bar()
179 self.assertEqual(app.bar.enabled, False)
168 self.assertEqual(app.bar.enabled, False)
180 self.assertEqual(app.bar.b, 5)
169 self.assertEqual(app.bar.b, 5)
181 self.assertEqual(app.extra_args, ['extra', 'args'])
170 self.assertEqual(app.extra_args, ['extra', 'args'])
182 app = MyApp()
171 app = MyApp()
183 app.parse_command_line(["--Bar.b=5", '--', 'extra', "--disable", 'args'])
172 app.parse_command_line(["--Bar.b=5", '--', 'extra', "--disable", 'args'])
184 app.init_bar()
173 app.init_bar()
185 self.assertEqual(app.bar.enabled, True)
174 self.assertEqual(app.bar.enabled, True)
186 self.assertEqual(app.bar.b, 5)
175 self.assertEqual(app.bar.b, 5)
187 self.assertEqual(app.extra_args, ['extra', '--disable', 'args'])
176 self.assertEqual(app.extra_args, ['extra', '--disable', 'args'])
188
177
189 def test_unicode_argv(self):
178 def test_unicode_argv(self):
190 app = MyApp()
179 app = MyApp()
191 app.parse_command_line(['ünîcødé'])
180 app.parse_command_line(['ünîcødé'])
192
181
182 def test_multi_file(self):
183 app = MyApp()
184 app.log = logging.getLogger()
185 name = 'config.py'
186 with TemporaryDirectory('_1') as td1:
187 with open(pjoin(td1, name), 'w') as f1:
188 f1.write("get_config().MyApp.Bar.b = 1")
189 with TemporaryDirectory('_2') as td2:
190 with open(pjoin(td2, name), 'w') as f2:
191 f2.write("get_config().MyApp.Bar.b = 2")
192 app.load_config_file(name, path=[td2, td1])
193 app.init_bar()
194 self.assertEqual(app.bar.b, 2)
195 app.load_config_file(name, path=[td1, td2])
196 app.init_bar()
197 self.assertEqual(app.bar.b, 1)
193
198
@@ -1,396 +1,404 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """Tests for IPython.config.loader"""
3 Tests for IPython.config.loader
4
5 Authors:
6
7 * Brian Granger
8 * Fernando Perez (design help)
9 """
10
3
11 #-----------------------------------------------------------------------------
4 # Copyright (c) IPython Development Team.
12 # Copyright (C) 2008 The IPython Development Team
5 # Distributed under the terms of the Modified BSD License.
13 #
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
17
18 #-----------------------------------------------------------------------------
19 # Imports
20 #-----------------------------------------------------------------------------
21
6
22 import os
7 import os
23 import pickle
8 import pickle
24 import sys
9 import sys
25 import json
26
10
27 from tempfile import mkstemp
11 from tempfile import mkstemp
28 from unittest import TestCase
12 from unittest import TestCase
29
13
30 from nose import SkipTest
14 from nose import SkipTest
31 import nose.tools as nt
15 import nose.tools as nt
32
16
33
17
34
18
35 from IPython.config.loader import (
19 from IPython.config.loader import (
36 Config,
20 Config,
37 LazyConfigValue,
21 LazyConfigValue,
38 PyFileConfigLoader,
22 PyFileConfigLoader,
39 JSONFileConfigLoader,
23 JSONFileConfigLoader,
40 KeyValueConfigLoader,
24 KeyValueConfigLoader,
41 ArgParseConfigLoader,
25 ArgParseConfigLoader,
42 KVArgParseConfigLoader,
26 KVArgParseConfigLoader,
43 ConfigError,
27 ConfigError,
44 )
28 )
45
29
46 #-----------------------------------------------------------------------------
47 # Actual tests
48 #-----------------------------------------------------------------------------
49
50
30
51 pyfile = """
31 pyfile = """
52 c = get_config()
32 c = get_config()
53 c.a=10
33 c.a=10
54 c.b=20
34 c.b=20
55 c.Foo.Bar.value=10
35 c.Foo.Bar.value=10
56 c.Foo.Bam.value=list(range(10)) # list() is just so it's the same on Python 3
36 c.Foo.Bam.value=list(range(10)) # list() is just so it's the same on Python 3
57 c.D.C.value='hi there'
37 c.D.C.value='hi there'
58 """
38 """
59
39
60 json1file = """
40 json1file = """
61 {
41 {
62 "version": 1,
42 "version": 1,
63 "a": 10,
43 "a": 10,
64 "b": 20,
44 "b": 20,
65 "Foo": {
45 "Foo": {
66 "Bam": {
46 "Bam": {
67 "value": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
47 "value": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
68 },
48 },
69 "Bar": {
49 "Bar": {
70 "value": 10
50 "value": 10
71 }
51 }
72 },
52 },
73 "D": {
53 "D": {
74 "C": {
54 "C": {
75 "value": "hi there"
55 "value": "hi there"
76 }
56 }
77 }
57 }
78 }
58 }
79 """
59 """
80
60
81 # should not load
61 # should not load
82 json2file = """
62 json2file = """
83 {
63 {
84 "version": 2
64 "version": 2
85 }
65 }
86 """
66 """
87
67
88 import logging
68 import logging
89 log = logging.getLogger('devnull')
69 log = logging.getLogger('devnull')
90 log.setLevel(0)
70 log.setLevel(0)
91
71
92 class TestFileCL(TestCase):
72 class TestFileCL(TestCase):
93
73
94 def _check_conf(self, config):
74 def _check_conf(self, config):
95 self.assertEqual(config.a, 10)
75 self.assertEqual(config.a, 10)
96 self.assertEqual(config.b, 20)
76 self.assertEqual(config.b, 20)
97 self.assertEqual(config.Foo.Bar.value, 10)
77 self.assertEqual(config.Foo.Bar.value, 10)
98 self.assertEqual(config.Foo.Bam.value, list(range(10)))
78 self.assertEqual(config.Foo.Bam.value, list(range(10)))
99 self.assertEqual(config.D.C.value, 'hi there')
79 self.assertEqual(config.D.C.value, 'hi there')
100
80
101 def test_python(self):
81 def test_python(self):
102 fd, fname = mkstemp('.py')
82 fd, fname = mkstemp('.py')
103 f = os.fdopen(fd, 'w')
83 f = os.fdopen(fd, 'w')
104 f.write(pyfile)
84 f.write(pyfile)
105 f.close()
85 f.close()
106 # Unlink the file
86 # Unlink the file
107 cl = PyFileConfigLoader(fname, log=log)
87 cl = PyFileConfigLoader(fname, log=log)
108 config = cl.load_config()
88 config = cl.load_config()
109 self._check_conf(config)
89 self._check_conf(config)
110
90
111 def test_json(self):
91 def test_json(self):
112 fd, fname = mkstemp('.json')
92 fd, fname = mkstemp('.json')
113 f = os.fdopen(fd, 'w')
93 f = os.fdopen(fd, 'w')
114 f.write(json1file)
94 f.write(json1file)
115 f.close()
95 f.close()
116 # Unlink the file
96 # Unlink the file
117 cl = JSONFileConfigLoader(fname, log=log)
97 cl = JSONFileConfigLoader(fname, log=log)
118 config = cl.load_config()
98 config = cl.load_config()
119 self._check_conf(config)
99 self._check_conf(config)
100
101 def test_collision(self):
102 a = Config()
103 b = Config()
104 self.assertEqual(a.collisions(b), {})
105 a.A.trait1 = 1
106 b.A.trait2 = 2
107 self.assertEqual(a.collisions(b), {})
108 b.A.trait1 = 1
109 self.assertEqual(a.collisions(b), {})
110 b.A.trait1 = 0
111 self.assertEqual(a.collisions(b), {
112 'A': {
113 'trait1': "1 ignored, using 0",
114 }
115 })
116 self.assertEqual(b.collisions(a), {
117 'A': {
118 'trait1': "0 ignored, using 1",
119 }
120 })
121 a.A.trait2 = 3
122 self.assertEqual(b.collisions(a), {
123 'A': {
124 'trait1': "0 ignored, using 1",
125 'trait2': "2 ignored, using 3",
126 }
127 })
120
128
121 def test_v2raise(self):
129 def test_v2raise(self):
122 fd, fname = mkstemp('.json')
130 fd, fname = mkstemp('.json')
123 f = os.fdopen(fd, 'w')
131 f = os.fdopen(fd, 'w')
124 f.write(json2file)
132 f.write(json2file)
125 f.close()
133 f.close()
126 # Unlink the file
134 # Unlink the file
127 cl = JSONFileConfigLoader(fname, log=log)
135 cl = JSONFileConfigLoader(fname, log=log)
128 with nt.assert_raises(ValueError):
136 with nt.assert_raises(ValueError):
129 cl.load_config()
137 cl.load_config()
130
138
131
139
132 class MyLoader1(ArgParseConfigLoader):
140 class MyLoader1(ArgParseConfigLoader):
133 def _add_arguments(self, aliases=None, flags=None):
141 def _add_arguments(self, aliases=None, flags=None):
134 p = self.parser
142 p = self.parser
135 p.add_argument('-f', '--foo', dest='Global.foo', type=str)
143 p.add_argument('-f', '--foo', dest='Global.foo', type=str)
136 p.add_argument('-b', dest='MyClass.bar', type=int)
144 p.add_argument('-b', dest='MyClass.bar', type=int)
137 p.add_argument('-n', dest='n', action='store_true')
145 p.add_argument('-n', dest='n', action='store_true')
138 p.add_argument('Global.bam', type=str)
146 p.add_argument('Global.bam', type=str)
139
147
140 class MyLoader2(ArgParseConfigLoader):
148 class MyLoader2(ArgParseConfigLoader):
141 def _add_arguments(self, aliases=None, flags=None):
149 def _add_arguments(self, aliases=None, flags=None):
142 subparsers = self.parser.add_subparsers(dest='subparser_name')
150 subparsers = self.parser.add_subparsers(dest='subparser_name')
143 subparser1 = subparsers.add_parser('1')
151 subparser1 = subparsers.add_parser('1')
144 subparser1.add_argument('-x',dest='Global.x')
152 subparser1.add_argument('-x',dest='Global.x')
145 subparser2 = subparsers.add_parser('2')
153 subparser2 = subparsers.add_parser('2')
146 subparser2.add_argument('y')
154 subparser2.add_argument('y')
147
155
148 class TestArgParseCL(TestCase):
156 class TestArgParseCL(TestCase):
149
157
150 def test_basic(self):
158 def test_basic(self):
151 cl = MyLoader1()
159 cl = MyLoader1()
152 config = cl.load_config('-f hi -b 10 -n wow'.split())
160 config = cl.load_config('-f hi -b 10 -n wow'.split())
153 self.assertEqual(config.Global.foo, 'hi')
161 self.assertEqual(config.Global.foo, 'hi')
154 self.assertEqual(config.MyClass.bar, 10)
162 self.assertEqual(config.MyClass.bar, 10)
155 self.assertEqual(config.n, True)
163 self.assertEqual(config.n, True)
156 self.assertEqual(config.Global.bam, 'wow')
164 self.assertEqual(config.Global.bam, 'wow')
157 config = cl.load_config(['wow'])
165 config = cl.load_config(['wow'])
158 self.assertEqual(list(config.keys()), ['Global'])
166 self.assertEqual(list(config.keys()), ['Global'])
159 self.assertEqual(list(config.Global.keys()), ['bam'])
167 self.assertEqual(list(config.Global.keys()), ['bam'])
160 self.assertEqual(config.Global.bam, 'wow')
168 self.assertEqual(config.Global.bam, 'wow')
161
169
162 def test_add_arguments(self):
170 def test_add_arguments(self):
163 cl = MyLoader2()
171 cl = MyLoader2()
164 config = cl.load_config('2 frobble'.split())
172 config = cl.load_config('2 frobble'.split())
165 self.assertEqual(config.subparser_name, '2')
173 self.assertEqual(config.subparser_name, '2')
166 self.assertEqual(config.y, 'frobble')
174 self.assertEqual(config.y, 'frobble')
167 config = cl.load_config('1 -x frobble'.split())
175 config = cl.load_config('1 -x frobble'.split())
168 self.assertEqual(config.subparser_name, '1')
176 self.assertEqual(config.subparser_name, '1')
169 self.assertEqual(config.Global.x, 'frobble')
177 self.assertEqual(config.Global.x, 'frobble')
170
178
171 def test_argv(self):
179 def test_argv(self):
172 cl = MyLoader1(argv='-f hi -b 10 -n wow'.split())
180 cl = MyLoader1(argv='-f hi -b 10 -n wow'.split())
173 config = cl.load_config()
181 config = cl.load_config()
174 self.assertEqual(config.Global.foo, 'hi')
182 self.assertEqual(config.Global.foo, 'hi')
175 self.assertEqual(config.MyClass.bar, 10)
183 self.assertEqual(config.MyClass.bar, 10)
176 self.assertEqual(config.n, True)
184 self.assertEqual(config.n, True)
177 self.assertEqual(config.Global.bam, 'wow')
185 self.assertEqual(config.Global.bam, 'wow')
178
186
179
187
180 class TestKeyValueCL(TestCase):
188 class TestKeyValueCL(TestCase):
181 klass = KeyValueConfigLoader
189 klass = KeyValueConfigLoader
182
190
183 def test_basic(self):
191 def test_basic(self):
184 cl = self.klass(log=log)
192 cl = self.klass(log=log)
185 argv = ['--'+s.strip('c.') for s in pyfile.split('\n')[2:-1]]
193 argv = ['--'+s.strip('c.') for s in pyfile.split('\n')[2:-1]]
186 config = cl.load_config(argv)
194 config = cl.load_config(argv)
187 self.assertEqual(config.a, 10)
195 self.assertEqual(config.a, 10)
188 self.assertEqual(config.b, 20)
196 self.assertEqual(config.b, 20)
189 self.assertEqual(config.Foo.Bar.value, 10)
197 self.assertEqual(config.Foo.Bar.value, 10)
190 self.assertEqual(config.Foo.Bam.value, list(range(10)))
198 self.assertEqual(config.Foo.Bam.value, list(range(10)))
191 self.assertEqual(config.D.C.value, 'hi there')
199 self.assertEqual(config.D.C.value, 'hi there')
192
200
193 def test_expanduser(self):
201 def test_expanduser(self):
194 cl = self.klass(log=log)
202 cl = self.klass(log=log)
195 argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"']
203 argv = ['--a=~/1/2/3', '--b=~', '--c=~/', '--d="~/"']
196 config = cl.load_config(argv)
204 config = cl.load_config(argv)
197 self.assertEqual(config.a, os.path.expanduser('~/1/2/3'))
205 self.assertEqual(config.a, os.path.expanduser('~/1/2/3'))
198 self.assertEqual(config.b, os.path.expanduser('~'))
206 self.assertEqual(config.b, os.path.expanduser('~'))
199 self.assertEqual(config.c, os.path.expanduser('~/'))
207 self.assertEqual(config.c, os.path.expanduser('~/'))
200 self.assertEqual(config.d, '~/')
208 self.assertEqual(config.d, '~/')
201
209
202 def test_extra_args(self):
210 def test_extra_args(self):
203 cl = self.klass(log=log)
211 cl = self.klass(log=log)
204 config = cl.load_config(['--a=5', 'b', '--c=10', 'd'])
212 config = cl.load_config(['--a=5', 'b', '--c=10', 'd'])
205 self.assertEqual(cl.extra_args, ['b', 'd'])
213 self.assertEqual(cl.extra_args, ['b', 'd'])
206 self.assertEqual(config.a, 5)
214 self.assertEqual(config.a, 5)
207 self.assertEqual(config.c, 10)
215 self.assertEqual(config.c, 10)
208 config = cl.load_config(['--', '--a=5', '--c=10'])
216 config = cl.load_config(['--', '--a=5', '--c=10'])
209 self.assertEqual(cl.extra_args, ['--a=5', '--c=10'])
217 self.assertEqual(cl.extra_args, ['--a=5', '--c=10'])
210
218
211 def test_unicode_args(self):
219 def test_unicode_args(self):
212 cl = self.klass(log=log)
220 cl = self.klass(log=log)
213 argv = [u'--a=épsîlön']
221 argv = [u'--a=épsîlön']
214 config = cl.load_config(argv)
222 config = cl.load_config(argv)
215 self.assertEqual(config.a, u'épsîlön')
223 self.assertEqual(config.a, u'épsîlön')
216
224
217 def test_unicode_bytes_args(self):
225 def test_unicode_bytes_args(self):
218 uarg = u'--a=é'
226 uarg = u'--a=é'
219 try:
227 try:
220 barg = uarg.encode(sys.stdin.encoding)
228 barg = uarg.encode(sys.stdin.encoding)
221 except (TypeError, UnicodeEncodeError):
229 except (TypeError, UnicodeEncodeError):
222 raise SkipTest("sys.stdin.encoding can't handle 'é'")
230 raise SkipTest("sys.stdin.encoding can't handle 'é'")
223
231
224 cl = self.klass(log=log)
232 cl = self.klass(log=log)
225 config = cl.load_config([barg])
233 config = cl.load_config([barg])
226 self.assertEqual(config.a, u'é')
234 self.assertEqual(config.a, u'é')
227
235
228 def test_unicode_alias(self):
236 def test_unicode_alias(self):
229 cl = self.klass(log=log)
237 cl = self.klass(log=log)
230 argv = [u'--a=épsîlön']
238 argv = [u'--a=épsîlön']
231 config = cl.load_config(argv, aliases=dict(a='A.a'))
239 config = cl.load_config(argv, aliases=dict(a='A.a'))
232 self.assertEqual(config.A.a, u'épsîlön')
240 self.assertEqual(config.A.a, u'épsîlön')
233
241
234
242
235 class TestArgParseKVCL(TestKeyValueCL):
243 class TestArgParseKVCL(TestKeyValueCL):
236 klass = KVArgParseConfigLoader
244 klass = KVArgParseConfigLoader
237
245
238 def test_expanduser2(self):
246 def test_expanduser2(self):
239 cl = self.klass(log=log)
247 cl = self.klass(log=log)
240 argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"]
248 argv = ['-a', '~/1/2/3', '--b', "'~/1/2/3'"]
241 config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b'))
249 config = cl.load_config(argv, aliases=dict(a='A.a', b='A.b'))
242 self.assertEqual(config.A.a, os.path.expanduser('~/1/2/3'))
250 self.assertEqual(config.A.a, os.path.expanduser('~/1/2/3'))
243 self.assertEqual(config.A.b, '~/1/2/3')
251 self.assertEqual(config.A.b, '~/1/2/3')
244
252
245 def test_eval(self):
253 def test_eval(self):
246 cl = self.klass(log=log)
254 cl = self.klass(log=log)
247 argv = ['-c', 'a=5']
255 argv = ['-c', 'a=5']
248 config = cl.load_config(argv, aliases=dict(c='A.c'))
256 config = cl.load_config(argv, aliases=dict(c='A.c'))
249 self.assertEqual(config.A.c, u"a=5")
257 self.assertEqual(config.A.c, u"a=5")
250
258
251
259
252 class TestConfig(TestCase):
260 class TestConfig(TestCase):
253
261
254 def test_setget(self):
262 def test_setget(self):
255 c = Config()
263 c = Config()
256 c.a = 10
264 c.a = 10
257 self.assertEqual(c.a, 10)
265 self.assertEqual(c.a, 10)
258 self.assertEqual('b' in c, False)
266 self.assertEqual('b' in c, False)
259
267
260 def test_auto_section(self):
268 def test_auto_section(self):
261 c = Config()
269 c = Config()
262 self.assertNotIn('A', c)
270 self.assertNotIn('A', c)
263 assert not c._has_section('A')
271 assert not c._has_section('A')
264 A = c.A
272 A = c.A
265 A.foo = 'hi there'
273 A.foo = 'hi there'
266 self.assertIn('A', c)
274 self.assertIn('A', c)
267 assert c._has_section('A')
275 assert c._has_section('A')
268 self.assertEqual(c.A.foo, 'hi there')
276 self.assertEqual(c.A.foo, 'hi there')
269 del c.A
277 del c.A
270 self.assertEqual(c.A, Config())
278 self.assertEqual(c.A, Config())
271
279
272 def test_merge_doesnt_exist(self):
280 def test_merge_doesnt_exist(self):
273 c1 = Config()
281 c1 = Config()
274 c2 = Config()
282 c2 = Config()
275 c2.bar = 10
283 c2.bar = 10
276 c2.Foo.bar = 10
284 c2.Foo.bar = 10
277 c1.merge(c2)
285 c1.merge(c2)
278 self.assertEqual(c1.Foo.bar, 10)
286 self.assertEqual(c1.Foo.bar, 10)
279 self.assertEqual(c1.bar, 10)
287 self.assertEqual(c1.bar, 10)
280 c2.Bar.bar = 10
288 c2.Bar.bar = 10
281 c1.merge(c2)
289 c1.merge(c2)
282 self.assertEqual(c1.Bar.bar, 10)
290 self.assertEqual(c1.Bar.bar, 10)
283
291
284 def test_merge_exists(self):
292 def test_merge_exists(self):
285 c1 = Config()
293 c1 = Config()
286 c2 = Config()
294 c2 = Config()
287 c1.Foo.bar = 10
295 c1.Foo.bar = 10
288 c1.Foo.bam = 30
296 c1.Foo.bam = 30
289 c2.Foo.bar = 20
297 c2.Foo.bar = 20
290 c2.Foo.wow = 40
298 c2.Foo.wow = 40
291 c1.merge(c2)
299 c1.merge(c2)
292 self.assertEqual(c1.Foo.bam, 30)
300 self.assertEqual(c1.Foo.bam, 30)
293 self.assertEqual(c1.Foo.bar, 20)
301 self.assertEqual(c1.Foo.bar, 20)
294 self.assertEqual(c1.Foo.wow, 40)
302 self.assertEqual(c1.Foo.wow, 40)
295 c2.Foo.Bam.bam = 10
303 c2.Foo.Bam.bam = 10
296 c1.merge(c2)
304 c1.merge(c2)
297 self.assertEqual(c1.Foo.Bam.bam, 10)
305 self.assertEqual(c1.Foo.Bam.bam, 10)
298
306
299 def test_deepcopy(self):
307 def test_deepcopy(self):
300 c1 = Config()
308 c1 = Config()
301 c1.Foo.bar = 10
309 c1.Foo.bar = 10
302 c1.Foo.bam = 30
310 c1.Foo.bam = 30
303 c1.a = 'asdf'
311 c1.a = 'asdf'
304 c1.b = range(10)
312 c1.b = range(10)
305 import copy
313 import copy
306 c2 = copy.deepcopy(c1)
314 c2 = copy.deepcopy(c1)
307 self.assertEqual(c1, c2)
315 self.assertEqual(c1, c2)
308 self.assertTrue(c1 is not c2)
316 self.assertTrue(c1 is not c2)
309 self.assertTrue(c1.Foo is not c2.Foo)
317 self.assertTrue(c1.Foo is not c2.Foo)
310
318
311 def test_builtin(self):
319 def test_builtin(self):
312 c1 = Config()
320 c1 = Config()
313 c1.format = "json"
321 c1.format = "json"
314
322
315 def test_fromdict(self):
323 def test_fromdict(self):
316 c1 = Config({'Foo' : {'bar' : 1}})
324 c1 = Config({'Foo' : {'bar' : 1}})
317 self.assertEqual(c1.Foo.__class__, Config)
325 self.assertEqual(c1.Foo.__class__, Config)
318 self.assertEqual(c1.Foo.bar, 1)
326 self.assertEqual(c1.Foo.bar, 1)
319
327
320 def test_fromdictmerge(self):
328 def test_fromdictmerge(self):
321 c1 = Config()
329 c1 = Config()
322 c2 = Config({'Foo' : {'bar' : 1}})
330 c2 = Config({'Foo' : {'bar' : 1}})
323 c1.merge(c2)
331 c1.merge(c2)
324 self.assertEqual(c1.Foo.__class__, Config)
332 self.assertEqual(c1.Foo.__class__, Config)
325 self.assertEqual(c1.Foo.bar, 1)
333 self.assertEqual(c1.Foo.bar, 1)
326
334
327 def test_fromdictmerge2(self):
335 def test_fromdictmerge2(self):
328 c1 = Config({'Foo' : {'baz' : 2}})
336 c1 = Config({'Foo' : {'baz' : 2}})
329 c2 = Config({'Foo' : {'bar' : 1}})
337 c2 = Config({'Foo' : {'bar' : 1}})
330 c1.merge(c2)
338 c1.merge(c2)
331 self.assertEqual(c1.Foo.__class__, Config)
339 self.assertEqual(c1.Foo.__class__, Config)
332 self.assertEqual(c1.Foo.bar, 1)
340 self.assertEqual(c1.Foo.bar, 1)
333 self.assertEqual(c1.Foo.baz, 2)
341 self.assertEqual(c1.Foo.baz, 2)
334 self.assertNotIn('baz', c2.Foo)
342 self.assertNotIn('baz', c2.Foo)
335
343
336 def test_contains(self):
344 def test_contains(self):
337 c1 = Config({'Foo' : {'baz' : 2}})
345 c1 = Config({'Foo' : {'baz' : 2}})
338 c2 = Config({'Foo' : {'bar' : 1}})
346 c2 = Config({'Foo' : {'bar' : 1}})
339 self.assertIn('Foo', c1)
347 self.assertIn('Foo', c1)
340 self.assertIn('Foo.baz', c1)
348 self.assertIn('Foo.baz', c1)
341 self.assertIn('Foo.bar', c2)
349 self.assertIn('Foo.bar', c2)
342 self.assertNotIn('Foo.bar', c1)
350 self.assertNotIn('Foo.bar', c1)
343
351
344 def test_pickle_config(self):
352 def test_pickle_config(self):
345 cfg = Config()
353 cfg = Config()
346 cfg.Foo.bar = 1
354 cfg.Foo.bar = 1
347 pcfg = pickle.dumps(cfg)
355 pcfg = pickle.dumps(cfg)
348 cfg2 = pickle.loads(pcfg)
356 cfg2 = pickle.loads(pcfg)
349 self.assertEqual(cfg2, cfg)
357 self.assertEqual(cfg2, cfg)
350
358
351 def test_getattr_section(self):
359 def test_getattr_section(self):
352 cfg = Config()
360 cfg = Config()
353 self.assertNotIn('Foo', cfg)
361 self.assertNotIn('Foo', cfg)
354 Foo = cfg.Foo
362 Foo = cfg.Foo
355 assert isinstance(Foo, Config)
363 assert isinstance(Foo, Config)
356 self.assertIn('Foo', cfg)
364 self.assertIn('Foo', cfg)
357
365
358 def test_getitem_section(self):
366 def test_getitem_section(self):
359 cfg = Config()
367 cfg = Config()
360 self.assertNotIn('Foo', cfg)
368 self.assertNotIn('Foo', cfg)
361 Foo = cfg['Foo']
369 Foo = cfg['Foo']
362 assert isinstance(Foo, Config)
370 assert isinstance(Foo, Config)
363 self.assertIn('Foo', cfg)
371 self.assertIn('Foo', cfg)
364
372
365 def test_getattr_not_section(self):
373 def test_getattr_not_section(self):
366 cfg = Config()
374 cfg = Config()
367 self.assertNotIn('foo', cfg)
375 self.assertNotIn('foo', cfg)
368 foo = cfg.foo
376 foo = cfg.foo
369 assert isinstance(foo, LazyConfigValue)
377 assert isinstance(foo, LazyConfigValue)
370 self.assertIn('foo', cfg)
378 self.assertIn('foo', cfg)
371
379
372 def test_getattr_private_missing(self):
380 def test_getattr_private_missing(self):
373 cfg = Config()
381 cfg = Config()
374 self.assertNotIn('_repr_html_', cfg)
382 self.assertNotIn('_repr_html_', cfg)
375 with self.assertRaises(AttributeError):
383 with self.assertRaises(AttributeError):
376 _ = cfg._repr_html_
384 _ = cfg._repr_html_
377 self.assertNotIn('_repr_html_', cfg)
385 self.assertNotIn('_repr_html_', cfg)
378 self.assertEqual(len(cfg), 0)
386 self.assertEqual(len(cfg), 0)
379
387
380 def test_getitem_not_section(self):
388 def test_getitem_not_section(self):
381 cfg = Config()
389 cfg = Config()
382 self.assertNotIn('foo', cfg)
390 self.assertNotIn('foo', cfg)
383 foo = cfg['foo']
391 foo = cfg['foo']
384 assert isinstance(foo, LazyConfigValue)
392 assert isinstance(foo, LazyConfigValue)
385 self.assertIn('foo', cfg)
393 self.assertIn('foo', cfg)
386
394
387 def test_merge_copies(self):
395 def test_merge_copies(self):
388 c = Config()
396 c = Config()
389 c2 = Config()
397 c2 = Config()
390 c2.Foo.trait = []
398 c2.Foo.trait = []
391 c.merge(c2)
399 c.merge(c2)
392 c2.Foo.trait.append(1)
400 c2.Foo.trait.append(1)
393 self.assertIsNot(c.Foo, c2.Foo)
401 self.assertIsNot(c.Foo, c2.Foo)
394 self.assertEqual(c.Foo.trait, [])
402 self.assertEqual(c.Foo.trait, [])
395 self.assertEqual(c2.Foo.trait, [1])
403 self.assertEqual(c2.Foo.trait, [1])
396
404
@@ -1,353 +1,345 b''
1 """ A minimal application base mixin for all ZMQ based IPython frontends.
1 """ A minimal application base mixin for all ZMQ based IPython frontends.
2
2
3 This is not a complete console app, as subprocess will not be able to receive
3 This is not a complete console app, as subprocess will not be able to receive
4 input, there is no real readline support, among other limitations. This is a
4 input, there is no real readline support, among other limitations. This is a
5 refactoring of what used to be the IPython/qt/console/qtconsoleapp.py
5 refactoring of what used to be the IPython/qt/console/qtconsoleapp.py
6 """
6 """
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 #-----------------------------------------------------------------------------
11 # Imports
12 #-----------------------------------------------------------------------------
13
14 # stdlib imports
15 import atexit
10 import atexit
16 import os
11 import os
17 import signal
12 import signal
18 import sys
13 import sys
19 import uuid
14 import uuid
20
15
21
16
22 # Local imports
23 from IPython.config.application import boolean_flag
17 from IPython.config.application import boolean_flag
24 from IPython.core.profiledir import ProfileDir
18 from IPython.core.profiledir import ProfileDir
25 from IPython.kernel.blocking import BlockingKernelClient
19 from IPython.kernel.blocking import BlockingKernelClient
26 from IPython.kernel import KernelManager
20 from IPython.kernel import KernelManager
27 from IPython.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
21 from IPython.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
28 from IPython.kernel.kernelspec import NoSuchKernel
22 from IPython.kernel.kernelspec import NoSuchKernel
29 from IPython.utils.path import filefind
23 from IPython.utils.path import filefind
30 from IPython.utils.traitlets import (
24 from IPython.utils.traitlets import (
31 Dict, List, Unicode, CUnicode, CBool, Any
25 Dict, List, Unicode, CUnicode, CBool, Any
32 )
26 )
33 from IPython.kernel.zmq.kernelapp import (
27 from IPython.kernel.zmq.kernelapp import (
34 kernel_flags,
28 kernel_flags,
35 kernel_aliases,
29 kernel_aliases,
36 IPKernelApp
30 IPKernelApp
37 )
31 )
38 from IPython.kernel.zmq.pylab.config import InlineBackend
32 from IPython.kernel.zmq.pylab.config import InlineBackend
39 from IPython.kernel.zmq.session import Session, default_secure
33 from IPython.kernel.zmq.session import Session, default_secure
40 from IPython.kernel.zmq.zmqshell import ZMQInteractiveShell
34 from IPython.kernel.zmq.zmqshell import ZMQInteractiveShell
41 from IPython.kernel.connect import ConnectionFileMixin
35 from IPython.kernel.connect import ConnectionFileMixin
42
36
43 #-----------------------------------------------------------------------------
44 # Network Constants
45 #-----------------------------------------------------------------------------
46
47 from IPython.utils.localinterfaces import localhost
37 from IPython.utils.localinterfaces import localhost
48
38
49 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
50 # Globals
51 #-----------------------------------------------------------------------------
52
53
54 #-----------------------------------------------------------------------------
55 # Aliases and Flags
40 # Aliases and Flags
56 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
57
42
58 flags = dict(kernel_flags)
43 flags = dict(kernel_flags)
59
44
60 # the flags that are specific to the frontend
45 # the flags that are specific to the frontend
61 # these must be scrubbed before being passed to the kernel,
46 # these must be scrubbed before being passed to the kernel,
62 # or it will raise an error on unrecognized flags
47 # or it will raise an error on unrecognized flags
63 app_flags = {
48 app_flags = {
64 'existing' : ({'IPythonConsoleApp' : {'existing' : 'kernel*.json'}},
49 'existing' : ({'IPythonConsoleApp' : {'existing' : 'kernel*.json'}},
65 "Connect to an existing kernel. If no argument specified, guess most recent"),
50 "Connect to an existing kernel. If no argument specified, guess most recent"),
66 }
51 }
67 app_flags.update(boolean_flag(
52 app_flags.update(boolean_flag(
68 'confirm-exit', 'IPythonConsoleApp.confirm_exit',
53 'confirm-exit', 'IPythonConsoleApp.confirm_exit',
69 """Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
54 """Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
70 to force a direct exit without any confirmation.
55 to force a direct exit without any confirmation.
71 """,
56 """,
72 """Don't prompt the user when exiting. This will terminate the kernel
57 """Don't prompt the user when exiting. This will terminate the kernel
73 if it is owned by the frontend, and leave it alive if it is external.
58 if it is owned by the frontend, and leave it alive if it is external.
74 """
59 """
75 ))
60 ))
76 flags.update(app_flags)
61 flags.update(app_flags)
77
62
78 aliases = dict(kernel_aliases)
63 aliases = dict(kernel_aliases)
79
64
80 # also scrub aliases from the frontend
65 # also scrub aliases from the frontend
81 app_aliases = dict(
66 app_aliases = dict(
82 ip = 'IPythonConsoleApp.ip',
67 ip = 'IPythonConsoleApp.ip',
83 transport = 'IPythonConsoleApp.transport',
68 transport = 'IPythonConsoleApp.transport',
84 hb = 'IPythonConsoleApp.hb_port',
69 hb = 'IPythonConsoleApp.hb_port',
85 shell = 'IPythonConsoleApp.shell_port',
70 shell = 'IPythonConsoleApp.shell_port',
86 iopub = 'IPythonConsoleApp.iopub_port',
71 iopub = 'IPythonConsoleApp.iopub_port',
87 stdin = 'IPythonConsoleApp.stdin_port',
72 stdin = 'IPythonConsoleApp.stdin_port',
88 existing = 'IPythonConsoleApp.existing',
73 existing = 'IPythonConsoleApp.existing',
89 f = 'IPythonConsoleApp.connection_file',
74 f = 'IPythonConsoleApp.connection_file',
90
75
91 kernel = 'IPythonConsoleApp.kernel_name',
76 kernel = 'IPythonConsoleApp.kernel_name',
92
77
93 ssh = 'IPythonConsoleApp.sshserver',
78 ssh = 'IPythonConsoleApp.sshserver',
94 )
79 )
95 aliases.update(app_aliases)
80 aliases.update(app_aliases)
96
81
97 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
98 # Classes
83 # Classes
99 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
100
85
101 #-----------------------------------------------------------------------------
86 classes = [KernelManager, ProfileDir, Session]
102 # IPythonConsole
103 #-----------------------------------------------------------------------------
104
105 classes = [IPKernelApp, ZMQInteractiveShell, KernelManager, ProfileDir, Session, InlineBackend]
106
87
107 class IPythonConsoleApp(ConnectionFileMixin):
88 class IPythonConsoleApp(ConnectionFileMixin):
108 name = 'ipython-console-mixin'
89 name = 'ipython-console-mixin'
109
90
110 description = """
91 description = """
111 The IPython Mixin Console.
92 The IPython Mixin Console.
112
93
113 This class contains the common portions of console client (QtConsole,
94 This class contains the common portions of console client (QtConsole,
114 ZMQ-based terminal console, etc). It is not a full console, in that
95 ZMQ-based terminal console, etc). It is not a full console, in that
115 launched terminal subprocesses will not be able to accept input.
96 launched terminal subprocesses will not be able to accept input.
116
97
117 The Console using this mixing supports various extra features beyond
98 The Console using this mixing supports various extra features beyond
118 the single-process Terminal IPython shell, such as connecting to
99 the single-process Terminal IPython shell, such as connecting to
119 existing kernel, via:
100 existing kernel, via:
120
101
121 ipython <appname> --existing
102 ipython <appname> --existing
122
103
123 as well as tunnel via SSH
104 as well as tunnel via SSH
124
105
125 """
106 """
126
107
127 classes = classes
108 classes = classes
128 flags = Dict(flags)
109 flags = Dict(flags)
129 aliases = Dict(aliases)
110 aliases = Dict(aliases)
130 kernel_manager_class = KernelManager
111 kernel_manager_class = KernelManager
131 kernel_client_class = BlockingKernelClient
112 kernel_client_class = BlockingKernelClient
132
113
133 kernel_argv = List(Unicode)
114 kernel_argv = List(Unicode)
134 # frontend flags&aliases to be stripped when building kernel_argv
115 # frontend flags&aliases to be stripped when building kernel_argv
135 frontend_flags = Any(app_flags)
116 frontend_flags = Any(app_flags)
136 frontend_aliases = Any(app_aliases)
117 frontend_aliases = Any(app_aliases)
137
118
138 # create requested profiles by default, if they don't exist:
119 # create requested profiles by default, if they don't exist:
139 auto_create = CBool(True)
120 auto_create = CBool(True)
140 # connection info:
121 # connection info:
141
122
142 sshserver = Unicode('', config=True,
123 sshserver = Unicode('', config=True,
143 help="""The SSH server to use to connect to the kernel.""")
124 help="""The SSH server to use to connect to the kernel.""")
144 sshkey = Unicode('', config=True,
125 sshkey = Unicode('', config=True,
145 help="""Path to the ssh key to use for logging in to the ssh server.""")
126 help="""Path to the ssh key to use for logging in to the ssh server.""")
146
127
147 def _connection_file_default(self):
128 def _connection_file_default(self):
148 return 'kernel-%i.json' % os.getpid()
129 return 'kernel-%i.json' % os.getpid()
149
130
150 existing = CUnicode('', config=True,
131 existing = CUnicode('', config=True,
151 help="""Connect to an already running kernel""")
132 help="""Connect to an already running kernel""")
152
133
153 kernel_name = Unicode('python', config=True,
134 kernel_name = Unicode('python', config=True,
154 help="""The name of the default kernel to start.""")
135 help="""The name of the default kernel to start.""")
155
136
156 confirm_exit = CBool(True, config=True,
137 confirm_exit = CBool(True, config=True,
157 help="""
138 help="""
158 Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
139 Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
159 to force a direct exit without any confirmation.""",
140 to force a direct exit without any confirmation.""",
160 )
141 )
161
142
162
143 @property
144 def help_classes(self):
145 """ConsoleApps can configure kernels on the command-line
146
147 But this shouldn't be written to a file
148 """
149 return self.classes + [IPKernelApp] + IPKernelApp.classes
150
163 def build_kernel_argv(self, argv=None):
151 def build_kernel_argv(self, argv=None):
164 """build argv to be passed to kernel subprocess"""
152 """build argv to be passed to kernel subprocess"""
165 if argv is None:
153 if argv is None:
166 argv = sys.argv[1:]
154 argv = sys.argv[1:]
167 self.kernel_argv = swallow_argv(argv, self.frontend_aliases, self.frontend_flags)
155 self.kernel_argv = swallow_argv(argv, self.frontend_aliases, self.frontend_flags)
168
156
169 def init_connection_file(self):
157 def init_connection_file(self):
170 """find the connection file, and load the info if found.
158 """find the connection file, and load the info if found.
171
159
172 The current working directory and the current profile's security
160 The current working directory and the current profile's security
173 directory will be searched for the file if it is not given by
161 directory will be searched for the file if it is not given by
174 absolute path.
162 absolute path.
175
163
176 When attempting to connect to an existing kernel and the `--existing`
164 When attempting to connect to an existing kernel and the `--existing`
177 argument does not match an existing file, it will be interpreted as a
165 argument does not match an existing file, it will be interpreted as a
178 fileglob, and the matching file in the current profile's security dir
166 fileglob, and the matching file in the current profile's security dir
179 with the latest access time will be used.
167 with the latest access time will be used.
180
168
181 After this method is called, self.connection_file contains the *full path*
169 After this method is called, self.connection_file contains the *full path*
182 to the connection file, never just its name.
170 to the connection file, never just its name.
183 """
171 """
184 if self.existing:
172 if self.existing:
185 try:
173 try:
186 cf = find_connection_file(self.existing)
174 cf = find_connection_file(self.existing)
187 except Exception:
175 except Exception:
188 self.log.critical("Could not find existing kernel connection file %s", self.existing)
176 self.log.critical("Could not find existing kernel connection file %s", self.existing)
189 self.exit(1)
177 self.exit(1)
190 self.log.debug("Connecting to existing kernel: %s" % cf)
178 self.log.debug("Connecting to existing kernel: %s" % cf)
191 self.connection_file = cf
179 self.connection_file = cf
192 else:
180 else:
193 # not existing, check if we are going to write the file
181 # not existing, check if we are going to write the file
194 # and ensure that self.connection_file is a full path, not just the shortname
182 # and ensure that self.connection_file is a full path, not just the shortname
195 try:
183 try:
196 cf = find_connection_file(self.connection_file)
184 cf = find_connection_file(self.connection_file)
197 except Exception:
185 except Exception:
198 # file might not exist
186 # file might not exist
199 if self.connection_file == os.path.basename(self.connection_file):
187 if self.connection_file == os.path.basename(self.connection_file):
200 # just shortname, put it in security dir
188 # just shortname, put it in security dir
201 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
189 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
202 else:
190 else:
203 cf = self.connection_file
191 cf = self.connection_file
204 self.connection_file = cf
192 self.connection_file = cf
205 try:
193 try:
206 self.connection_file = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
194 self.connection_file = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
207 except IOError:
195 except IOError:
208 self.log.debug("Connection File not found: %s", self.connection_file)
196 self.log.debug("Connection File not found: %s", self.connection_file)
209 return
197 return
210
198
211 # should load_connection_file only be used for existing?
199 # should load_connection_file only be used for existing?
212 # as it is now, this allows reusing ports if an existing
200 # as it is now, this allows reusing ports if an existing
213 # file is requested
201 # file is requested
214 try:
202 try:
215 self.load_connection_file()
203 self.load_connection_file()
216 except Exception:
204 except Exception:
217 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
205 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
218 self.exit(1)
206 self.exit(1)
219
207
220 def init_ssh(self):
208 def init_ssh(self):
221 """set up ssh tunnels, if needed."""
209 """set up ssh tunnels, if needed."""
222 if not self.existing or (not self.sshserver and not self.sshkey):
210 if not self.existing or (not self.sshserver and not self.sshkey):
223 return
211 return
224 self.load_connection_file()
212 self.load_connection_file()
225
213
226 transport = self.transport
214 transport = self.transport
227 ip = self.ip
215 ip = self.ip
228
216
229 if transport != 'tcp':
217 if transport != 'tcp':
230 self.log.error("Can only use ssh tunnels with TCP sockets, not %s", transport)
218 self.log.error("Can only use ssh tunnels with TCP sockets, not %s", transport)
231 sys.exit(-1)
219 sys.exit(-1)
232
220
233 if self.sshkey and not self.sshserver:
221 if self.sshkey and not self.sshserver:
234 # specifying just the key implies that we are connecting directly
222 # specifying just the key implies that we are connecting directly
235 self.sshserver = ip
223 self.sshserver = ip
236 ip = localhost()
224 ip = localhost()
237
225
238 # build connection dict for tunnels:
226 # build connection dict for tunnels:
239 info = dict(ip=ip,
227 info = dict(ip=ip,
240 shell_port=self.shell_port,
228 shell_port=self.shell_port,
241 iopub_port=self.iopub_port,
229 iopub_port=self.iopub_port,
242 stdin_port=self.stdin_port,
230 stdin_port=self.stdin_port,
243 hb_port=self.hb_port
231 hb_port=self.hb_port
244 )
232 )
245
233
246 self.log.info("Forwarding connections to %s via %s"%(ip, self.sshserver))
234 self.log.info("Forwarding connections to %s via %s"%(ip, self.sshserver))
247
235
248 # tunnels return a new set of ports, which will be on localhost:
236 # tunnels return a new set of ports, which will be on localhost:
249 self.ip = localhost()
237 self.ip = localhost()
250 try:
238 try:
251 newports = tunnel_to_kernel(info, self.sshserver, self.sshkey)
239 newports = tunnel_to_kernel(info, self.sshserver, self.sshkey)
252 except:
240 except:
253 # even catch KeyboardInterrupt
241 # even catch KeyboardInterrupt
254 self.log.error("Could not setup tunnels", exc_info=True)
242 self.log.error("Could not setup tunnels", exc_info=True)
255 self.exit(1)
243 self.exit(1)
256
244
257 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = newports
245 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = newports
258
246
259 cf = self.connection_file
247 cf = self.connection_file
260 base,ext = os.path.splitext(cf)
248 base,ext = os.path.splitext(cf)
261 base = os.path.basename(base)
249 base = os.path.basename(base)
262 self.connection_file = os.path.basename(base)+'-ssh'+ext
250 self.connection_file = os.path.basename(base)+'-ssh'+ext
263 self.log.info("To connect another client via this tunnel, use:")
251 self.log.info("To connect another client via this tunnel, use:")
264 self.log.info("--existing %s" % self.connection_file)
252 self.log.info("--existing %s" % self.connection_file)
265
253
266 def _new_connection_file(self):
254 def _new_connection_file(self):
267 cf = ''
255 cf = ''
268 while not cf:
256 while not cf:
269 # we don't need a 128b id to distinguish kernels, use more readable
257 # we don't need a 128b id to distinguish kernels, use more readable
270 # 48b node segment (12 hex chars). Users running more than 32k simultaneous
258 # 48b node segment (12 hex chars). Users running more than 32k simultaneous
271 # kernels can subclass.
259 # kernels can subclass.
272 ident = str(uuid.uuid4()).split('-')[-1]
260 ident = str(uuid.uuid4()).split('-')[-1]
273 cf = os.path.join(self.profile_dir.security_dir, 'kernel-%s.json' % ident)
261 cf = os.path.join(self.profile_dir.security_dir, 'kernel-%s.json' % ident)
274 # only keep if it's actually new. Protect against unlikely collision
262 # only keep if it's actually new. Protect against unlikely collision
275 # in 48b random search space
263 # in 48b random search space
276 cf = cf if not os.path.exists(cf) else ''
264 cf = cf if not os.path.exists(cf) else ''
277 return cf
265 return cf
278
266
279 def init_kernel_manager(self):
267 def init_kernel_manager(self):
280 # Don't let Qt or ZMQ swallow KeyboardInterupts.
268 # Don't let Qt or ZMQ swallow KeyboardInterupts.
281 if self.existing:
269 if self.existing:
282 self.kernel_manager = None
270 self.kernel_manager = None
283 return
271 return
284 signal.signal(signal.SIGINT, signal.SIG_DFL)
272 signal.signal(signal.SIGINT, signal.SIG_DFL)
285
273
286 # Create a KernelManager and start a kernel.
274 # Create a KernelManager and start a kernel.
287 try:
275 try:
288 self.kernel_manager = self.kernel_manager_class(
276 self.kernel_manager = self.kernel_manager_class(
289 ip=self.ip,
277 ip=self.ip,
290 session=self.session,
278 session=self.session,
291 transport=self.transport,
279 transport=self.transport,
292 shell_port=self.shell_port,
280 shell_port=self.shell_port,
293 iopub_port=self.iopub_port,
281 iopub_port=self.iopub_port,
294 stdin_port=self.stdin_port,
282 stdin_port=self.stdin_port,
295 hb_port=self.hb_port,
283 hb_port=self.hb_port,
296 connection_file=self.connection_file,
284 connection_file=self.connection_file,
297 kernel_name=self.kernel_name,
285 kernel_name=self.kernel_name,
298 parent=self,
286 parent=self,
299 ipython_dir=self.ipython_dir,
287 ipython_dir=self.ipython_dir,
300 )
288 )
301 except NoSuchKernel:
289 except NoSuchKernel:
302 self.log.critical("Could not find kernel %s", self.kernel_name)
290 self.log.critical("Could not find kernel %s", self.kernel_name)
303 self.exit(1)
291 self.exit(1)
304
292
305 self.kernel_manager.client_factory = self.kernel_client_class
293 self.kernel_manager.client_factory = self.kernel_client_class
306 self.kernel_manager.start_kernel(extra_arguments=self.kernel_argv)
294 # FIXME: remove special treatment of IPython kernels
295 kwargs = {}
296 if self.kernel_manager.ipython_kernel:
297 kwargs['extra_arguments'] = self.kernel_argv
298 self.kernel_manager.start_kernel(**kwargs)
307 atexit.register(self.kernel_manager.cleanup_ipc_files)
299 atexit.register(self.kernel_manager.cleanup_ipc_files)
308
300
309 if self.sshserver:
301 if self.sshserver:
310 # ssh, write new connection file
302 # ssh, write new connection file
311 self.kernel_manager.write_connection_file()
303 self.kernel_manager.write_connection_file()
312
304
313 # in case KM defaults / ssh writing changes things:
305 # in case KM defaults / ssh writing changes things:
314 km = self.kernel_manager
306 km = self.kernel_manager
315 self.shell_port=km.shell_port
307 self.shell_port=km.shell_port
316 self.iopub_port=km.iopub_port
308 self.iopub_port=km.iopub_port
317 self.stdin_port=km.stdin_port
309 self.stdin_port=km.stdin_port
318 self.hb_port=km.hb_port
310 self.hb_port=km.hb_port
319 self.connection_file = km.connection_file
311 self.connection_file = km.connection_file
320
312
321 atexit.register(self.kernel_manager.cleanup_connection_file)
313 atexit.register(self.kernel_manager.cleanup_connection_file)
322
314
323 def init_kernel_client(self):
315 def init_kernel_client(self):
324 if self.kernel_manager is not None:
316 if self.kernel_manager is not None:
325 self.kernel_client = self.kernel_manager.client()
317 self.kernel_client = self.kernel_manager.client()
326 else:
318 else:
327 self.kernel_client = self.kernel_client_class(
319 self.kernel_client = self.kernel_client_class(
328 session=self.session,
320 session=self.session,
329 ip=self.ip,
321 ip=self.ip,
330 transport=self.transport,
322 transport=self.transport,
331 shell_port=self.shell_port,
323 shell_port=self.shell_port,
332 iopub_port=self.iopub_port,
324 iopub_port=self.iopub_port,
333 stdin_port=self.stdin_port,
325 stdin_port=self.stdin_port,
334 hb_port=self.hb_port,
326 hb_port=self.hb_port,
335 connection_file=self.connection_file,
327 connection_file=self.connection_file,
336 parent=self,
328 parent=self,
337 )
329 )
338
330
339 self.kernel_client.start_channels()
331 self.kernel_client.start_channels()
340
332
341
333
342
334
343 def initialize(self, argv=None):
335 def initialize(self, argv=None):
344 """
336 """
345 Classes which mix this class in should call:
337 Classes which mix this class in should call:
346 IPythonConsoleApp.initialize(self,argv)
338 IPythonConsoleApp.initialize(self,argv)
347 """
339 """
348 self.init_connection_file()
340 self.init_connection_file()
349 default_secure(self.config)
341 default_secure(self.config)
350 self.init_ssh()
342 self.init_ssh()
351 self.init_kernel_manager()
343 self.init_kernel_manager()
352 self.init_kernel_client()
344 self.init_kernel_client()
353
345
@@ -1,238 +1,253 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 System command aliases.
3 System command aliases.
4
4
5 Authors:
5 Authors:
6
6
7 * Fernando Perez
7 * Fernando Perez
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2011 The IPython Development Team
12 # Copyright (C) 2008-2011 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License.
14 # Distributed under the terms of the BSD License.
15 #
15 #
16 # The full license is in the file COPYING.txt, distributed with this software.
16 # The full license is in the file COPYING.txt, distributed with this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import os
23 import os
24 import re
24 import re
25 import sys
25 import sys
26
26
27 from IPython.config.configurable import Configurable
27 from IPython.config.configurable import Configurable
28 from IPython.core.error import UsageError
28 from IPython.core.error import UsageError
29
29
30 from IPython.utils.py3compat import string_types
30 from IPython.utils.py3compat import string_types
31 from IPython.utils.traitlets import List, Instance
31 from IPython.utils.traitlets import List, Instance
32 from IPython.utils.warn import error
32 from IPython.utils.warn import error
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Utilities
35 # Utilities
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 # This is used as the pattern for calls to split_user_input.
38 # This is used as the pattern for calls to split_user_input.
39 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
39 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
40
40
41 def default_aliases():
41 def default_aliases():
42 """Return list of shell aliases to auto-define.
42 """Return list of shell aliases to auto-define.
43 """
43 """
44 # Note: the aliases defined here should be safe to use on a kernel
44 # Note: the aliases defined here should be safe to use on a kernel
45 # regardless of what frontend it is attached to. Frontends that use a
45 # regardless of what frontend it is attached to. Frontends that use a
46 # kernel in-process can define additional aliases that will only work in
46 # kernel in-process can define additional aliases that will only work in
47 # their case. For example, things like 'less' or 'clear' that manipulate
47 # their case. For example, things like 'less' or 'clear' that manipulate
48 # the terminal should NOT be declared here, as they will only work if the
48 # the terminal should NOT be declared here, as they will only work if the
49 # kernel is running inside a true terminal, and not over the network.
49 # kernel is running inside a true terminal, and not over the network.
50
50
51 if os.name == 'posix':
51 if os.name == 'posix':
52 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
52 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
53 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
53 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
54 ('cat', 'cat'),
54 ('cat', 'cat'),
55 ]
55 ]
56 # Useful set of ls aliases. The GNU and BSD options are a little
56 # Useful set of ls aliases. The GNU and BSD options are a little
57 # different, so we make aliases that provide as similar as possible
57 # different, so we make aliases that provide as similar as possible
58 # behavior in ipython, by passing the right flags for each platform
58 # behavior in ipython, by passing the right flags for each platform
59 if sys.platform.startswith('linux'):
59 if sys.platform.startswith('linux'):
60 ls_aliases = [('ls', 'ls -F --color'),
60 ls_aliases = [('ls', 'ls -F --color'),
61 # long ls
61 # long ls
62 ('ll', 'ls -F -o --color'),
62 ('ll', 'ls -F -o --color'),
63 # ls normal files only
63 # ls normal files only
64 ('lf', 'ls -F -o --color %l | grep ^-'),
64 ('lf', 'ls -F -o --color %l | grep ^-'),
65 # ls symbolic links
65 # ls symbolic links
66 ('lk', 'ls -F -o --color %l | grep ^l'),
66 ('lk', 'ls -F -o --color %l | grep ^l'),
67 # directories or links to directories,
67 # directories or links to directories,
68 ('ldir', 'ls -F -o --color %l | grep /$'),
68 ('ldir', 'ls -F -o --color %l | grep /$'),
69 # things which are executable
69 # things which are executable
70 ('lx', 'ls -F -o --color %l | grep ^-..x'),
70 ('lx', 'ls -F -o --color %l | grep ^-..x'),
71 ]
71 ]
72 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
73 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
74 # the -G switch and lack the ability to use colorized output.
75 ls_aliases = [('ls', 'ls -F'),
76 # long ls
77 ('ll', 'ls -F -l'),
78 # ls normal files only
79 ('lf', 'ls -F -l %l | grep ^-'),
80 # ls symbolic links
81 ('lk', 'ls -F -l %l | grep ^l'),
82 # directories or links to directories,
83 ('ldir', 'ls -F -l %l | grep /$'),
84 # things which are executable
85 ('lx', 'ls -F -l %l | grep ^-..x'),
86 ]
72 else:
87 else:
73 # BSD, OSX, etc.
88 # BSD, OSX, etc.
74 ls_aliases = [('ls', 'ls -F -G'),
89 ls_aliases = [('ls', 'ls -F -G'),
75 # long ls
90 # long ls
76 ('ll', 'ls -F -l -G'),
91 ('ll', 'ls -F -l -G'),
77 # ls normal files only
92 # ls normal files only
78 ('lf', 'ls -F -l -G %l | grep ^-'),
93 ('lf', 'ls -F -l -G %l | grep ^-'),
79 # ls symbolic links
94 # ls symbolic links
80 ('lk', 'ls -F -l -G %l | grep ^l'),
95 ('lk', 'ls -F -l -G %l | grep ^l'),
81 # directories or links to directories,
96 # directories or links to directories,
82 ('ldir', 'ls -F -G -l %l | grep /$'),
97 ('ldir', 'ls -F -G -l %l | grep /$'),
83 # things which are executable
98 # things which are executable
84 ('lx', 'ls -F -l -G %l | grep ^-..x'),
99 ('lx', 'ls -F -l -G %l | grep ^-..x'),
85 ]
100 ]
86 default_aliases = default_aliases + ls_aliases
101 default_aliases = default_aliases + ls_aliases
87 elif os.name in ['nt', 'dos']:
102 elif os.name in ['nt', 'dos']:
88 default_aliases = [('ls', 'dir /on'),
103 default_aliases = [('ls', 'dir /on'),
89 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
104 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
90 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
105 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
91 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
106 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
92 ]
107 ]
93 else:
108 else:
94 default_aliases = []
109 default_aliases = []
95
110
96 return default_aliases
111 return default_aliases
97
112
98
113
99 class AliasError(Exception):
114 class AliasError(Exception):
100 pass
115 pass
101
116
102
117
103 class InvalidAliasError(AliasError):
118 class InvalidAliasError(AliasError):
104 pass
119 pass
105
120
106 class Alias(object):
121 class Alias(object):
107 """Callable object storing the details of one alias.
122 """Callable object storing the details of one alias.
108
123
109 Instances are registered as magic functions to allow use of aliases.
124 Instances are registered as magic functions to allow use of aliases.
110 """
125 """
111
126
112 # Prepare blacklist
127 # Prepare blacklist
113 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
128 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
114
129
115 def __init__(self, shell, name, cmd):
130 def __init__(self, shell, name, cmd):
116 self.shell = shell
131 self.shell = shell
117 self.name = name
132 self.name = name
118 self.cmd = cmd
133 self.cmd = cmd
119 self.nargs = self.validate()
134 self.nargs = self.validate()
120
135
121 def validate(self):
136 def validate(self):
122 """Validate the alias, and return the number of arguments."""
137 """Validate the alias, and return the number of arguments."""
123 if self.name in self.blacklist:
138 if self.name in self.blacklist:
124 raise InvalidAliasError("The name %s can't be aliased "
139 raise InvalidAliasError("The name %s can't be aliased "
125 "because it is a keyword or builtin." % self.name)
140 "because it is a keyword or builtin." % self.name)
126 try:
141 try:
127 caller = self.shell.magics_manager.magics['line'][self.name]
142 caller = self.shell.magics_manager.magics['line'][self.name]
128 except KeyError:
143 except KeyError:
129 pass
144 pass
130 else:
145 else:
131 if not isinstance(caller, Alias):
146 if not isinstance(caller, Alias):
132 raise InvalidAliasError("The name %s can't be aliased "
147 raise InvalidAliasError("The name %s can't be aliased "
133 "because it is another magic command." % self.name)
148 "because it is another magic command." % self.name)
134
149
135 if not (isinstance(self.cmd, string_types)):
150 if not (isinstance(self.cmd, string_types)):
136 raise InvalidAliasError("An alias command must be a string, "
151 raise InvalidAliasError("An alias command must be a string, "
137 "got: %r" % self.cmd)
152 "got: %r" % self.cmd)
138
153
139 nargs = self.cmd.count('%s')
154 nargs = self.cmd.count('%s')
140
155
141 if (nargs > 0) and (self.cmd.find('%l') >= 0):
156 if (nargs > 0) and (self.cmd.find('%l') >= 0):
142 raise InvalidAliasError('The %s and %l specifiers are mutually '
157 raise InvalidAliasError('The %s and %l specifiers are mutually '
143 'exclusive in alias definitions.')
158 'exclusive in alias definitions.')
144
159
145 return nargs
160 return nargs
146
161
147 def __repr__(self):
162 def __repr__(self):
148 return "<alias {} for {!r}>".format(self.name, self.cmd)
163 return "<alias {} for {!r}>".format(self.name, self.cmd)
149
164
150 def __call__(self, rest=''):
165 def __call__(self, rest=''):
151 cmd = self.cmd
166 cmd = self.cmd
152 nargs = self.nargs
167 nargs = self.nargs
153 # Expand the %l special to be the user's input line
168 # Expand the %l special to be the user's input line
154 if cmd.find('%l') >= 0:
169 if cmd.find('%l') >= 0:
155 cmd = cmd.replace('%l', rest)
170 cmd = cmd.replace('%l', rest)
156 rest = ''
171 rest = ''
157 if nargs==0:
172 if nargs==0:
158 # Simple, argument-less aliases
173 # Simple, argument-less aliases
159 cmd = '%s %s' % (cmd, rest)
174 cmd = '%s %s' % (cmd, rest)
160 else:
175 else:
161 # Handle aliases with positional arguments
176 # Handle aliases with positional arguments
162 args = rest.split(None, nargs)
177 args = rest.split(None, nargs)
163 if len(args) < nargs:
178 if len(args) < nargs:
164 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
179 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
165 (self.name, nargs, len(args)))
180 (self.name, nargs, len(args)))
166 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
181 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
167
182
168 self.shell.system(cmd)
183 self.shell.system(cmd)
169
184
170 #-----------------------------------------------------------------------------
185 #-----------------------------------------------------------------------------
171 # Main AliasManager class
186 # Main AliasManager class
172 #-----------------------------------------------------------------------------
187 #-----------------------------------------------------------------------------
173
188
174 class AliasManager(Configurable):
189 class AliasManager(Configurable):
175
190
176 default_aliases = List(default_aliases(), config=True)
191 default_aliases = List(default_aliases(), config=True)
177 user_aliases = List(default_value=[], config=True)
192 user_aliases = List(default_value=[], config=True)
178 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
193 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
179
194
180 def __init__(self, shell=None, **kwargs):
195 def __init__(self, shell=None, **kwargs):
181 super(AliasManager, self).__init__(shell=shell, **kwargs)
196 super(AliasManager, self).__init__(shell=shell, **kwargs)
182 # For convenient access
197 # For convenient access
183 self.linemagics = self.shell.magics_manager.magics['line']
198 self.linemagics = self.shell.magics_manager.magics['line']
184 self.init_aliases()
199 self.init_aliases()
185
200
186 def init_aliases(self):
201 def init_aliases(self):
187 # Load default & user aliases
202 # Load default & user aliases
188 for name, cmd in self.default_aliases + self.user_aliases:
203 for name, cmd in self.default_aliases + self.user_aliases:
189 self.soft_define_alias(name, cmd)
204 self.soft_define_alias(name, cmd)
190
205
191 @property
206 @property
192 def aliases(self):
207 def aliases(self):
193 return [(n, func.cmd) for (n, func) in self.linemagics.items()
208 return [(n, func.cmd) for (n, func) in self.linemagics.items()
194 if isinstance(func, Alias)]
209 if isinstance(func, Alias)]
195
210
196 def soft_define_alias(self, name, cmd):
211 def soft_define_alias(self, name, cmd):
197 """Define an alias, but don't raise on an AliasError."""
212 """Define an alias, but don't raise on an AliasError."""
198 try:
213 try:
199 self.define_alias(name, cmd)
214 self.define_alias(name, cmd)
200 except AliasError as e:
215 except AliasError as e:
201 error("Invalid alias: %s" % e)
216 error("Invalid alias: %s" % e)
202
217
203 def define_alias(self, name, cmd):
218 def define_alias(self, name, cmd):
204 """Define a new alias after validating it.
219 """Define a new alias after validating it.
205
220
206 This will raise an :exc:`AliasError` if there are validation
221 This will raise an :exc:`AliasError` if there are validation
207 problems.
222 problems.
208 """
223 """
209 caller = Alias(shell=self.shell, name=name, cmd=cmd)
224 caller = Alias(shell=self.shell, name=name, cmd=cmd)
210 self.shell.magics_manager.register_function(caller, magic_kind='line',
225 self.shell.magics_manager.register_function(caller, magic_kind='line',
211 magic_name=name)
226 magic_name=name)
212
227
213 def get_alias(self, name):
228 def get_alias(self, name):
214 """Return an alias, or None if no alias by that name exists."""
229 """Return an alias, or None if no alias by that name exists."""
215 aname = self.linemagics.get(name, None)
230 aname = self.linemagics.get(name, None)
216 return aname if isinstance(aname, Alias) else None
231 return aname if isinstance(aname, Alias) else None
217
232
218 def is_alias(self, name):
233 def is_alias(self, name):
219 """Return whether or not a given name has been defined as an alias"""
234 """Return whether or not a given name has been defined as an alias"""
220 return self.get_alias(name) is not None
235 return self.get_alias(name) is not None
221
236
222 def undefine_alias(self, name):
237 def undefine_alias(self, name):
223 if self.is_alias(name):
238 if self.is_alias(name):
224 del self.linemagics[name]
239 del self.linemagics[name]
225 else:
240 else:
226 raise ValueError('%s is not an alias' % name)
241 raise ValueError('%s is not an alias' % name)
227
242
228 def clear_aliases(self):
243 def clear_aliases(self):
229 for name, cmd in self.aliases:
244 for name, cmd in self.aliases:
230 self.undefine_alias(name)
245 self.undefine_alias(name)
231
246
232 def retrieve_alias(self, name):
247 def retrieve_alias(self, name):
233 """Retrieve the command to which an alias expands."""
248 """Retrieve the command to which an alias expands."""
234 caller = self.get_alias(name)
249 caller = self.get_alias(name)
235 if caller:
250 if caller:
236 return caller.cmd
251 return caller.cmd
237 else:
252 else:
238 raise ValueError('%s is not an alias' % name)
253 raise ValueError('%s is not an alias' % name)
@@ -1,389 +1,380 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for IPython.
3 An application for IPython.
4
4
5 All top-level applications should use the classes in this module for
5 All top-level applications should use the classes in this module for
6 handling configuration and creating configurables.
6 handling configuration and creating configurables.
7
7
8 The job of an :class:`Application` is to create the master configuration
8 The job of an :class:`Application` is to create the master configuration
9 object and then create the configurable objects, passing the config to them.
9 object and then create the configurable objects, passing the config to them.
10
11 Authors:
12
13 * Brian Granger
14 * Fernando Perez
15 * Min RK
16
17 """
10 """
18
11
19 #-----------------------------------------------------------------------------
12 # Copyright (c) IPython Development Team.
20 # Copyright (C) 2008 The IPython Development Team
13 # Distributed under the terms of the Modified BSD License.
21 #
22 # Distributed under the terms of the BSD License. The full license is in
23 # the file COPYING, distributed as part of this software.
24 #-----------------------------------------------------------------------------
25
26 #-----------------------------------------------------------------------------
27 # Imports
28 #-----------------------------------------------------------------------------
29
14
30 import atexit
15 import atexit
31 import glob
16 import glob
32 import logging
17 import logging
33 import os
18 import os
34 import shutil
19 import shutil
35 import sys
20 import sys
36
21
37 from IPython.config.application import Application, catch_config_error
22 from IPython.config.application import Application, catch_config_error
38 from IPython.config.loader import ConfigFileNotFound
23 from IPython.config.loader import ConfigFileNotFound
39 from IPython.core import release, crashhandler
24 from IPython.core import release, crashhandler
40 from IPython.core.profiledir import ProfileDir, ProfileDirError
25 from IPython.core.profiledir import ProfileDir, ProfileDirError
41 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir, ensure_dir_exists
26 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir, ensure_dir_exists
42 from IPython.utils import py3compat
27 from IPython.utils import py3compat
43 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict, Set, Instance
28 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict, Set, Instance
44
29
45 #-----------------------------------------------------------------------------
30 if os.name == 'nt':
46 # Classes and functions
31 programdata = os.environ.get('PROGRAMDATA', None)
47 #-----------------------------------------------------------------------------
32 if programdata:
48
33 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
34 else: # PROGRAMDATA is not defined by default on XP.
35 SYSTEM_CONFIG_DIRS = []
36 else:
37 SYSTEM_CONFIG_DIRS = [
38 "/usr/local/etc/ipython",
39 "/etc/ipython",
40 ]
49
41
50 #-----------------------------------------------------------------------------
51 # Base Application Class
52 #-----------------------------------------------------------------------------
53
42
54 # aliases and flags
43 # aliases and flags
55
44
56 base_aliases = {
45 base_aliases = {
57 'profile-dir' : 'ProfileDir.location',
46 'profile-dir' : 'ProfileDir.location',
58 'profile' : 'BaseIPythonApplication.profile',
47 'profile' : 'BaseIPythonApplication.profile',
59 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
48 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
60 'log-level' : 'Application.log_level',
49 'log-level' : 'Application.log_level',
61 'config' : 'BaseIPythonApplication.extra_config_file',
50 'config' : 'BaseIPythonApplication.extra_config_file',
62 }
51 }
63
52
64 base_flags = dict(
53 base_flags = dict(
65 debug = ({'Application' : {'log_level' : logging.DEBUG}},
54 debug = ({'Application' : {'log_level' : logging.DEBUG}},
66 "set log level to logging.DEBUG (maximize logging output)"),
55 "set log level to logging.DEBUG (maximize logging output)"),
67 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
56 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
68 "set log level to logging.CRITICAL (minimize logging output)"),
57 "set log level to logging.CRITICAL (minimize logging output)"),
69 init = ({'BaseIPythonApplication' : {
58 init = ({'BaseIPythonApplication' : {
70 'copy_config_files' : True,
59 'copy_config_files' : True,
71 'auto_create' : True}
60 'auto_create' : True}
72 }, """Initialize profile with default config files. This is equivalent
61 }, """Initialize profile with default config files. This is equivalent
73 to running `ipython profile create <profile>` prior to startup.
62 to running `ipython profile create <profile>` prior to startup.
74 """)
63 """)
75 )
64 )
76
65
77
66
78 class BaseIPythonApplication(Application):
67 class BaseIPythonApplication(Application):
79
68
80 name = Unicode(u'ipython')
69 name = Unicode(u'ipython')
81 description = Unicode(u'IPython: an enhanced interactive Python shell.')
70 description = Unicode(u'IPython: an enhanced interactive Python shell.')
82 version = Unicode(release.version)
71 version = Unicode(release.version)
83
72
84 aliases = Dict(base_aliases)
73 aliases = Dict(base_aliases)
85 flags = Dict(base_flags)
74 flags = Dict(base_flags)
86 classes = List([ProfileDir])
75 classes = List([ProfileDir])
87
76
88 # Track whether the config_file has changed,
77 # Track whether the config_file has changed,
89 # because some logic happens only if we aren't using the default.
78 # because some logic happens only if we aren't using the default.
90 config_file_specified = Set()
79 config_file_specified = Set()
91
80
92 config_file_name = Unicode()
81 config_file_name = Unicode()
93 def _config_file_name_default(self):
82 def _config_file_name_default(self):
94 return self.name.replace('-','_') + u'_config.py'
83 return self.name.replace('-','_') + u'_config.py'
95 def _config_file_name_changed(self, name, old, new):
84 def _config_file_name_changed(self, name, old, new):
96 if new != old:
85 if new != old:
97 self.config_file_specified.add(new)
86 self.config_file_specified.add(new)
98
87
99 # The directory that contains IPython's builtin profiles.
88 # The directory that contains IPython's builtin profiles.
100 builtin_profile_dir = Unicode(
89 builtin_profile_dir = Unicode(
101 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
90 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
102 )
91 )
103
92
104 config_file_paths = List(Unicode)
93 config_file_paths = List(Unicode)
105 def _config_file_paths_default(self):
94 def _config_file_paths_default(self):
106 return [py3compat.getcwd()]
95 return [py3compat.getcwd()]
107
96
108 extra_config_file = Unicode(config=True,
97 extra_config_file = Unicode(config=True,
109 help="""Path to an extra config file to load.
98 help="""Path to an extra config file to load.
110
99
111 If specified, load this config file in addition to any other IPython config.
100 If specified, load this config file in addition to any other IPython config.
112 """)
101 """)
113 def _extra_config_file_changed(self, name, old, new):
102 def _extra_config_file_changed(self, name, old, new):
114 try:
103 try:
115 self.config_files.remove(old)
104 self.config_files.remove(old)
116 except ValueError:
105 except ValueError:
117 pass
106 pass
118 self.config_file_specified.add(new)
107 self.config_file_specified.add(new)
119 self.config_files.append(new)
108 self.config_files.append(new)
120
109
121 profile = Unicode(u'default', config=True,
110 profile = Unicode(u'default', config=True,
122 help="""The IPython profile to use."""
111 help="""The IPython profile to use."""
123 )
112 )
124
113
125 def _profile_changed(self, name, old, new):
114 def _profile_changed(self, name, old, new):
126 self.builtin_profile_dir = os.path.join(
115 self.builtin_profile_dir = os.path.join(
127 get_ipython_package_dir(), u'config', u'profile', new
116 get_ipython_package_dir(), u'config', u'profile', new
128 )
117 )
129
118
130 ipython_dir = Unicode(config=True,
119 ipython_dir = Unicode(config=True,
131 help="""
120 help="""
132 The name of the IPython directory. This directory is used for logging
121 The name of the IPython directory. This directory is used for logging
133 configuration (through profiles), history storage, etc. The default
122 configuration (through profiles), history storage, etc. The default
134 is usually $HOME/.ipython. This option can also be specified through
123 is usually $HOME/.ipython. This option can also be specified through
135 the environment variable IPYTHONDIR.
124 the environment variable IPYTHONDIR.
136 """
125 """
137 )
126 )
138 def _ipython_dir_default(self):
127 def _ipython_dir_default(self):
139 d = get_ipython_dir()
128 d = get_ipython_dir()
140 self._ipython_dir_changed('ipython_dir', d, d)
129 self._ipython_dir_changed('ipython_dir', d, d)
141 return d
130 return d
142
131
143 _in_init_profile_dir = False
132 _in_init_profile_dir = False
144 profile_dir = Instance(ProfileDir)
133 profile_dir = Instance(ProfileDir)
145 def _profile_dir_default(self):
134 def _profile_dir_default(self):
146 # avoid recursion
135 # avoid recursion
147 if self._in_init_profile_dir:
136 if self._in_init_profile_dir:
148 return
137 return
149 # profile_dir requested early, force initialization
138 # profile_dir requested early, force initialization
150 self.init_profile_dir()
139 self.init_profile_dir()
151 return self.profile_dir
140 return self.profile_dir
152
141
153 overwrite = Bool(False, config=True,
142 overwrite = Bool(False, config=True,
154 help="""Whether to overwrite existing config files when copying""")
143 help="""Whether to overwrite existing config files when copying""")
155 auto_create = Bool(False, config=True,
144 auto_create = Bool(False, config=True,
156 help="""Whether to create profile dir if it doesn't exist""")
145 help="""Whether to create profile dir if it doesn't exist""")
157
146
158 config_files = List(Unicode)
147 config_files = List(Unicode)
159 def _config_files_default(self):
148 def _config_files_default(self):
160 return [self.config_file_name]
149 return [self.config_file_name]
161
150
162 copy_config_files = Bool(False, config=True,
151 copy_config_files = Bool(False, config=True,
163 help="""Whether to install the default config files into the profile dir.
152 help="""Whether to install the default config files into the profile dir.
164 If a new profile is being created, and IPython contains config files for that
153 If a new profile is being created, and IPython contains config files for that
165 profile, then they will be staged into the new directory. Otherwise,
154 profile, then they will be staged into the new directory. Otherwise,
166 default config files will be automatically generated.
155 default config files will be automatically generated.
167 """)
156 """)
168
157
169 verbose_crash = Bool(False, config=True,
158 verbose_crash = Bool(False, config=True,
170 help="""Create a massive crash report when IPython encounters what may be an
159 help="""Create a massive crash report when IPython encounters what may be an
171 internal error. The default is to append a short message to the
160 internal error. The default is to append a short message to the
172 usual traceback""")
161 usual traceback""")
173
162
174 # The class to use as the crash handler.
163 # The class to use as the crash handler.
175 crash_handler_class = Type(crashhandler.CrashHandler)
164 crash_handler_class = Type(crashhandler.CrashHandler)
176
165
177 @catch_config_error
166 @catch_config_error
178 def __init__(self, **kwargs):
167 def __init__(self, **kwargs):
179 super(BaseIPythonApplication, self).__init__(**kwargs)
168 super(BaseIPythonApplication, self).__init__(**kwargs)
180 # ensure current working directory exists
169 # ensure current working directory exists
181 try:
170 try:
182 directory = py3compat.getcwd()
171 directory = py3compat.getcwd()
183 except:
172 except:
184 # raise exception
173 # raise exception
185 self.log.error("Current working directory doesn't exist.")
174 self.log.error("Current working directory doesn't exist.")
186 raise
175 raise
187
176
188 #-------------------------------------------------------------------------
177 #-------------------------------------------------------------------------
189 # Various stages of Application creation
178 # Various stages of Application creation
190 #-------------------------------------------------------------------------
179 #-------------------------------------------------------------------------
191
180
192 def init_crash_handler(self):
181 def init_crash_handler(self):
193 """Create a crash handler, typically setting sys.excepthook to it."""
182 """Create a crash handler, typically setting sys.excepthook to it."""
194 self.crash_handler = self.crash_handler_class(self)
183 self.crash_handler = self.crash_handler_class(self)
195 sys.excepthook = self.excepthook
184 sys.excepthook = self.excepthook
196 def unset_crashhandler():
185 def unset_crashhandler():
197 sys.excepthook = sys.__excepthook__
186 sys.excepthook = sys.__excepthook__
198 atexit.register(unset_crashhandler)
187 atexit.register(unset_crashhandler)
199
188
200 def excepthook(self, etype, evalue, tb):
189 def excepthook(self, etype, evalue, tb):
201 """this is sys.excepthook after init_crashhandler
190 """this is sys.excepthook after init_crashhandler
202
191
203 set self.verbose_crash=True to use our full crashhandler, instead of
192 set self.verbose_crash=True to use our full crashhandler, instead of
204 a regular traceback with a short message (crash_handler_lite)
193 a regular traceback with a short message (crash_handler_lite)
205 """
194 """
206
195
207 if self.verbose_crash:
196 if self.verbose_crash:
208 return self.crash_handler(etype, evalue, tb)
197 return self.crash_handler(etype, evalue, tb)
209 else:
198 else:
210 return crashhandler.crash_handler_lite(etype, evalue, tb)
199 return crashhandler.crash_handler_lite(etype, evalue, tb)
211
200
212 def _ipython_dir_changed(self, name, old, new):
201 def _ipython_dir_changed(self, name, old, new):
213 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
202 if old is not None:
214 sys.getfilesystemencoding()
203 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
215 )
204 sys.getfilesystemencoding()
216 if str_old in sys.path:
205 )
217 sys.path.remove(str_old)
206 if str_old in sys.path:
207 sys.path.remove(str_old)
218 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
208 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
219 sys.getfilesystemencoding()
209 sys.getfilesystemencoding()
220 )
210 )
221 sys.path.append(str_path)
211 sys.path.append(str_path)
222 ensure_dir_exists(new)
212 ensure_dir_exists(new)
223 readme = os.path.join(new, 'README')
213 readme = os.path.join(new, 'README')
224 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
214 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
225 if not os.path.exists(readme) and os.path.exists(readme_src):
215 if not os.path.exists(readme) and os.path.exists(readme_src):
226 shutil.copy(readme_src, readme)
216 shutil.copy(readme_src, readme)
227 for d in ('extensions', 'nbextensions'):
217 for d in ('extensions', 'nbextensions'):
228 path = os.path.join(new, d)
218 path = os.path.join(new, d)
229 try:
219 try:
230 ensure_dir_exists(path)
220 ensure_dir_exists(path)
231 except OSError:
221 except OSError:
232 # this will not be EEXIST
222 # this will not be EEXIST
233 self.log.error("couldn't create path %s: %s", path, e)
223 self.log.error("couldn't create path %s: %s", path, e)
234 self.log.debug("IPYTHONDIR set to: %s" % new)
224 self.log.debug("IPYTHONDIR set to: %s" % new)
235
225
236 def load_config_file(self, suppress_errors=True):
226 def load_config_file(self, suppress_errors=True):
237 """Load the config file.
227 """Load the config file.
238
228
239 By default, errors in loading config are handled, and a warning
229 By default, errors in loading config are handled, and a warning
240 printed on screen. For testing, the suppress_errors option is set
230 printed on screen. For testing, the suppress_errors option is set
241 to False, so errors will make tests fail.
231 to False, so errors will make tests fail.
242 """
232 """
243 self.log.debug("Searching path %s for config files", self.config_file_paths)
233 self.log.debug("Searching path %s for config files", self.config_file_paths)
244 base_config = 'ipython_config.py'
234 base_config = 'ipython_config.py'
245 self.log.debug("Attempting to load config file: %s" %
235 self.log.debug("Attempting to load config file: %s" %
246 base_config)
236 base_config)
247 try:
237 try:
248 Application.load_config_file(
238 Application.load_config_file(
249 self,
239 self,
250 base_config,
240 base_config,
251 path=self.config_file_paths
241 path=self.config_file_paths
252 )
242 )
253 except ConfigFileNotFound:
243 except ConfigFileNotFound:
254 # ignore errors loading parent
244 # ignore errors loading parent
255 self.log.debug("Config file %s not found", base_config)
245 self.log.debug("Config file %s not found", base_config)
256 pass
246 pass
257
247
258 for config_file_name in self.config_files:
248 for config_file_name in self.config_files:
259 if not config_file_name or config_file_name == base_config:
249 if not config_file_name or config_file_name == base_config:
260 continue
250 continue
261 self.log.debug("Attempting to load config file: %s" %
251 self.log.debug("Attempting to load config file: %s" %
262 self.config_file_name)
252 self.config_file_name)
263 try:
253 try:
264 Application.load_config_file(
254 Application.load_config_file(
265 self,
255 self,
266 config_file_name,
256 config_file_name,
267 path=self.config_file_paths
257 path=self.config_file_paths
268 )
258 )
269 except ConfigFileNotFound:
259 except ConfigFileNotFound:
270 # Only warn if the default config file was NOT being used.
260 # Only warn if the default config file was NOT being used.
271 if config_file_name in self.config_file_specified:
261 if config_file_name in self.config_file_specified:
272 msg = self.log.warn
262 msg = self.log.warn
273 else:
263 else:
274 msg = self.log.debug
264 msg = self.log.debug
275 msg("Config file not found, skipping: %s", config_file_name)
265 msg("Config file not found, skipping: %s", config_file_name)
276 except:
266 except:
277 # For testing purposes.
267 # For testing purposes.
278 if not suppress_errors:
268 if not suppress_errors:
279 raise
269 raise
280 self.log.warn("Error loading config file: %s" %
270 self.log.warn("Error loading config file: %s" %
281 self.config_file_name, exc_info=True)
271 self.config_file_name, exc_info=True)
282
272
283 def init_profile_dir(self):
273 def init_profile_dir(self):
284 """initialize the profile dir"""
274 """initialize the profile dir"""
285 self._in_init_profile_dir = True
275 self._in_init_profile_dir = True
286 if self.profile_dir is not None:
276 if self.profile_dir is not None:
287 # already ran
277 # already ran
288 return
278 return
289 if 'ProfileDir.location' not in self.config:
279 if 'ProfileDir.location' not in self.config:
290 # location not specified, find by profile name
280 # location not specified, find by profile name
291 try:
281 try:
292 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
282 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
293 except ProfileDirError:
283 except ProfileDirError:
294 # not found, maybe create it (always create default profile)
284 # not found, maybe create it (always create default profile)
295 if self.auto_create or self.profile == 'default':
285 if self.auto_create or self.profile == 'default':
296 try:
286 try:
297 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
287 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
298 except ProfileDirError:
288 except ProfileDirError:
299 self.log.fatal("Could not create profile: %r"%self.profile)
289 self.log.fatal("Could not create profile: %r"%self.profile)
300 self.exit(1)
290 self.exit(1)
301 else:
291 else:
302 self.log.info("Created profile dir: %r"%p.location)
292 self.log.info("Created profile dir: %r"%p.location)
303 else:
293 else:
304 self.log.fatal("Profile %r not found."%self.profile)
294 self.log.fatal("Profile %r not found."%self.profile)
305 self.exit(1)
295 self.exit(1)
306 else:
296 else:
307 self.log.info("Using existing profile dir: %r"%p.location)
297 self.log.info("Using existing profile dir: %r"%p.location)
308 else:
298 else:
309 location = self.config.ProfileDir.location
299 location = self.config.ProfileDir.location
310 # location is fully specified
300 # location is fully specified
311 try:
301 try:
312 p = ProfileDir.find_profile_dir(location, self.config)
302 p = ProfileDir.find_profile_dir(location, self.config)
313 except ProfileDirError:
303 except ProfileDirError:
314 # not found, maybe create it
304 # not found, maybe create it
315 if self.auto_create:
305 if self.auto_create:
316 try:
306 try:
317 p = ProfileDir.create_profile_dir(location, self.config)
307 p = ProfileDir.create_profile_dir(location, self.config)
318 except ProfileDirError:
308 except ProfileDirError:
319 self.log.fatal("Could not create profile directory: %r"%location)
309 self.log.fatal("Could not create profile directory: %r"%location)
320 self.exit(1)
310 self.exit(1)
321 else:
311 else:
322 self.log.info("Creating new profile dir: %r"%location)
312 self.log.info("Creating new profile dir: %r"%location)
323 else:
313 else:
324 self.log.fatal("Profile directory %r not found."%location)
314 self.log.fatal("Profile directory %r not found."%location)
325 self.exit(1)
315 self.exit(1)
326 else:
316 else:
327 self.log.info("Using existing profile dir: %r"%location)
317 self.log.info("Using existing profile dir: %r"%location)
328 # if profile_dir is specified explicitly, set profile name
318 # if profile_dir is specified explicitly, set profile name
329 dir_name = os.path.basename(p.location)
319 dir_name = os.path.basename(p.location)
330 if dir_name.startswith('profile_'):
320 if dir_name.startswith('profile_'):
331 self.profile = dir_name[8:]
321 self.profile = dir_name[8:]
332
322
333 self.profile_dir = p
323 self.profile_dir = p
334 self.config_file_paths.append(p.location)
324 self.config_file_paths.append(p.location)
335 self._in_init_profile_dir = False
325 self._in_init_profile_dir = False
336
326
337 def init_config_files(self):
327 def init_config_files(self):
338 """[optionally] copy default config files into profile dir."""
328 """[optionally] copy default config files into profile dir."""
329 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
339 # copy config files
330 # copy config files
340 path = self.builtin_profile_dir
331 path = self.builtin_profile_dir
341 if self.copy_config_files:
332 if self.copy_config_files:
342 src = self.profile
333 src = self.profile
343
334
344 cfg = self.config_file_name
335 cfg = self.config_file_name
345 if path and os.path.exists(os.path.join(path, cfg)):
336 if path and os.path.exists(os.path.join(path, cfg)):
346 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
337 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
347 cfg, src, self.profile_dir.location, self.overwrite)
338 cfg, src, self.profile_dir.location, self.overwrite)
348 )
339 )
349 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
340 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
350 else:
341 else:
351 self.stage_default_config_file()
342 self.stage_default_config_file()
352 else:
343 else:
353 # Still stage *bundled* config files, but not generated ones
344 # Still stage *bundled* config files, but not generated ones
354 # This is necessary for `ipython profile=sympy` to load the profile
345 # This is necessary for `ipython profile=sympy` to load the profile
355 # on the first go
346 # on the first go
356 files = glob.glob(os.path.join(path, '*.py'))
347 files = glob.glob(os.path.join(path, '*.py'))
357 for fullpath in files:
348 for fullpath in files:
358 cfg = os.path.basename(fullpath)
349 cfg = os.path.basename(fullpath)
359 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
350 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
360 # file was copied
351 # file was copied
361 self.log.warn("Staging bundled %s from %s into %r"%(
352 self.log.warn("Staging bundled %s from %s into %r"%(
362 cfg, self.profile, self.profile_dir.location)
353 cfg, self.profile, self.profile_dir.location)
363 )
354 )
364
355
365
356
366 def stage_default_config_file(self):
357 def stage_default_config_file(self):
367 """auto generate default config file, and stage it into the profile."""
358 """auto generate default config file, and stage it into the profile."""
368 s = self.generate_config_file()
359 s = self.generate_config_file()
369 fname = os.path.join(self.profile_dir.location, self.config_file_name)
360 fname = os.path.join(self.profile_dir.location, self.config_file_name)
370 if self.overwrite or not os.path.exists(fname):
361 if self.overwrite or not os.path.exists(fname):
371 self.log.warn("Generating default config file: %r"%(fname))
362 self.log.warn("Generating default config file: %r"%(fname))
372 with open(fname, 'w') as f:
363 with open(fname, 'w') as f:
373 f.write(s)
364 f.write(s)
374
365
375 @catch_config_error
366 @catch_config_error
376 def initialize(self, argv=None):
367 def initialize(self, argv=None):
377 # don't hook up crash handler before parsing command-line
368 # don't hook up crash handler before parsing command-line
378 self.parse_command_line(argv)
369 self.parse_command_line(argv)
379 self.init_crash_handler()
370 self.init_crash_handler()
380 if self.subapp is not None:
371 if self.subapp is not None:
381 # stop here if subapp is taking over
372 # stop here if subapp is taking over
382 return
373 return
383 cl_config = self.config
374 cl_config = self.config
384 self.init_profile_dir()
375 self.init_profile_dir()
385 self.init_config_files()
376 self.init_config_files()
386 self.load_config_file()
377 self.load_config_file()
387 # enforce cl-opts override configfile opts:
378 # enforce cl-opts override configfile opts:
388 self.update_config(cl_config)
379 self.update_config(cl_config)
389
380
@@ -1,591 +1,591 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Pdb debugger class.
3 Pdb debugger class.
4
4
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 the command line completion of other programs which include this isn't
6 the command line completion of other programs which include this isn't
7 damaged.
7 damaged.
8
8
9 In the future, this class will be expanded with improvements over the standard
9 In the future, this class will be expanded with improvements over the standard
10 pdb.
10 pdb.
11
11
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 changes. Licensing should therefore be under the standard Python terms. For
13 changes. Licensing should therefore be under the standard Python terms. For
14 details on the PSF (Python Software Foundation) standard license, see:
14 details on the PSF (Python Software Foundation) standard license, see:
15
15
16 http://www.python.org/2.2.3/license.html"""
16 http://www.python.org/2.2.3/license.html"""
17
17
18 #*****************************************************************************
18 #*****************************************************************************
19 #
19 #
20 # This file is licensed under the PSF license.
20 # This file is licensed under the PSF license.
21 #
21 #
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 #
24 #
25 #
25 #
26 #*****************************************************************************
26 #*****************************************************************************
27 from __future__ import print_function
27 from __future__ import print_function
28
28
29 import bdb
29 import bdb
30 import functools
30 import functools
31 import linecache
31 import linecache
32 import sys
32 import sys
33
33
34 from IPython import get_ipython
34 from IPython import get_ipython
35 from IPython.utils import PyColorize, ulinecache
35 from IPython.utils import PyColorize, ulinecache
36 from IPython.utils import coloransi, io, py3compat
36 from IPython.utils import coloransi, io, py3compat
37 from IPython.core.excolors import exception_colors
37 from IPython.core.excolors import exception_colors
38 from IPython.testing.skipdoctest import skip_doctest
38 from IPython.testing.skipdoctest import skip_doctest
39
39
40 # See if we can use pydb.
40 # See if we can use pydb.
41 has_pydb = False
41 has_pydb = False
42 prompt = 'ipdb> '
42 prompt = 'ipdb> '
43 #We have to check this directly from sys.argv, config struct not yet available
43 #We have to check this directly from sys.argv, config struct not yet available
44 if '--pydb' in sys.argv:
44 if '--pydb' in sys.argv:
45 try:
45 try:
46 import pydb
46 import pydb
47 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
47 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
48 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
48 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
49 # better protect against it.
49 # better protect against it.
50 has_pydb = True
50 has_pydb = True
51 except ImportError:
51 except ImportError:
52 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
52 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
53
53
54 if has_pydb:
54 if has_pydb:
55 from pydb import Pdb as OldPdb
55 from pydb import Pdb as OldPdb
56 #print "Using pydb for %run -d and post-mortem" #dbg
56 #print "Using pydb for %run -d and post-mortem" #dbg
57 prompt = 'ipydb> '
57 prompt = 'ipydb> '
58 else:
58 else:
59 from pdb import Pdb as OldPdb
59 from pdb import Pdb as OldPdb
60
60
61 # Allow the set_trace code to operate outside of an ipython instance, even if
61 # Allow the set_trace code to operate outside of an ipython instance, even if
62 # it does so with some limitations. The rest of this support is implemented in
62 # it does so with some limitations. The rest of this support is implemented in
63 # the Tracer constructor.
63 # the Tracer constructor.
64 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
64 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
65 """Exception hook which handles `BdbQuit` exceptions.
65 """Exception hook which handles `BdbQuit` exceptions.
66
66
67 All other exceptions are processed using the `excepthook`
67 All other exceptions are processed using the `excepthook`
68 parameter.
68 parameter.
69 """
69 """
70 if et==bdb.BdbQuit:
70 if et==bdb.BdbQuit:
71 print('Exiting Debugger.')
71 print('Exiting Debugger.')
72 elif excepthook is not None:
72 elif excepthook is not None:
73 excepthook(et, ev, tb)
73 excepthook(et, ev, tb)
74 else:
74 else:
75 # Backwards compatibility. Raise deprecation warning?
75 # Backwards compatibility. Raise deprecation warning?
76 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
76 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
77
77
78 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
78 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
79 print('Exiting Debugger.')
79 print('Exiting Debugger.')
80
80
81
81
82 class Tracer(object):
82 class Tracer(object):
83 """Class for local debugging, similar to pdb.set_trace.
83 """Class for local debugging, similar to pdb.set_trace.
84
84
85 Instances of this class, when called, behave like pdb.set_trace, but
85 Instances of this class, when called, behave like pdb.set_trace, but
86 providing IPython's enhanced capabilities.
86 providing IPython's enhanced capabilities.
87
87
88 This is implemented as a class which must be initialized in your own code
88 This is implemented as a class which must be initialized in your own code
89 and not as a standalone function because we need to detect at runtime
89 and not as a standalone function because we need to detect at runtime
90 whether IPython is already active or not. That detection is done in the
90 whether IPython is already active or not. That detection is done in the
91 constructor, ensuring that this code plays nicely with a running IPython,
91 constructor, ensuring that this code plays nicely with a running IPython,
92 while functioning acceptably (though with limitations) if outside of it.
92 while functioning acceptably (though with limitations) if outside of it.
93 """
93 """
94
94
95 @skip_doctest
95 @skip_doctest
96 def __init__(self,colors=None):
96 def __init__(self,colors=None):
97 """Create a local debugger instance.
97 """Create a local debugger instance.
98
98
99 Parameters
99 Parameters
100 ----------
100 ----------
101
101
102 colors : str, optional
102 colors : str, optional
103 The name of the color scheme to use, it must be one of IPython's
103 The name of the color scheme to use, it must be one of IPython's
104 valid color schemes. If not given, the function will default to
104 valid color schemes. If not given, the function will default to
105 the current IPython scheme when running inside IPython, and to
105 the current IPython scheme when running inside IPython, and to
106 'NoColor' otherwise.
106 'NoColor' otherwise.
107
107
108 Examples
108 Examples
109 --------
109 --------
110 ::
110 ::
111
111
112 from IPython.core.debugger import Tracer; debug_here = Tracer()
112 from IPython.core.debugger import Tracer; debug_here = Tracer()
113
113
114 Later in your code::
114 Later in your code::
115
115
116 debug_here() # -> will open up the debugger at that point.
116 debug_here() # -> will open up the debugger at that point.
117
117
118 Once the debugger activates, you can use all of its regular commands to
118 Once the debugger activates, you can use all of its regular commands to
119 step through code, set breakpoints, etc. See the pdb documentation
119 step through code, set breakpoints, etc. See the pdb documentation
120 from the Python standard library for usage details.
120 from the Python standard library for usage details.
121 """
121 """
122
122
123 ip = get_ipython()
123 ip = get_ipython()
124 if ip is None:
124 if ip is None:
125 # Outside of ipython, we set our own exception hook manually
125 # Outside of ipython, we set our own exception hook manually
126 sys.excepthook = functools.partial(BdbQuit_excepthook,
126 sys.excepthook = functools.partial(BdbQuit_excepthook,
127 excepthook=sys.excepthook)
127 excepthook=sys.excepthook)
128 def_colors = 'NoColor'
128 def_colors = 'NoColor'
129 try:
129 try:
130 # Limited tab completion support
130 # Limited tab completion support
131 import readline
131 import readline
132 readline.parse_and_bind('tab: complete')
132 readline.parse_and_bind('tab: complete')
133 except ImportError:
133 except ImportError:
134 pass
134 pass
135 else:
135 else:
136 # In ipython, we use its custom exception handler mechanism
136 # In ipython, we use its custom exception handler mechanism
137 def_colors = ip.colors
137 def_colors = ip.colors
138 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
138 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
139
139
140 if colors is None:
140 if colors is None:
141 colors = def_colors
141 colors = def_colors
142
142
143 # The stdlib debugger internally uses a modified repr from the `repr`
143 # The stdlib debugger internally uses a modified repr from the `repr`
144 # module, that limits the length of printed strings to a hardcoded
144 # module, that limits the length of printed strings to a hardcoded
145 # limit of 30 characters. That much trimming is too aggressive, let's
145 # limit of 30 characters. That much trimming is too aggressive, let's
146 # at least raise that limit to 80 chars, which should be enough for
146 # at least raise that limit to 80 chars, which should be enough for
147 # most interactive uses.
147 # most interactive uses.
148 try:
148 try:
149 try:
149 try:
150 from reprlib import aRepr # Py 3
150 from reprlib import aRepr # Py 3
151 except ImportError:
151 except ImportError:
152 from repr import aRepr # Py 2
152 from repr import aRepr # Py 2
153 aRepr.maxstring = 80
153 aRepr.maxstring = 80
154 except:
154 except:
155 # This is only a user-facing convenience, so any error we encounter
155 # This is only a user-facing convenience, so any error we encounter
156 # here can be warned about but can be otherwise ignored. These
156 # here can be warned about but can be otherwise ignored. These
157 # printouts will tell us about problems if this API changes
157 # printouts will tell us about problems if this API changes
158 import traceback
158 import traceback
159 traceback.print_exc()
159 traceback.print_exc()
160
160
161 self.debugger = Pdb(colors)
161 self.debugger = Pdb(colors)
162
162
163 def __call__(self):
163 def __call__(self):
164 """Starts an interactive debugger at the point where called.
164 """Starts an interactive debugger at the point where called.
165
165
166 This is similar to the pdb.set_trace() function from the std lib, but
166 This is similar to the pdb.set_trace() function from the std lib, but
167 using IPython's enhanced debugger."""
167 using IPython's enhanced debugger."""
168
168
169 self.debugger.set_trace(sys._getframe().f_back)
169 self.debugger.set_trace(sys._getframe().f_back)
170
170
171
171
172 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
172 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
173 """Make new_fn have old_fn's doc string. This is particularly useful
173 """Make new_fn have old_fn's doc string. This is particularly useful
174 for the ``do_...`` commands that hook into the help system.
174 for the ``do_...`` commands that hook into the help system.
175 Adapted from from a comp.lang.python posting
175 Adapted from from a comp.lang.python posting
176 by Duncan Booth."""
176 by Duncan Booth."""
177 def wrapper(*args, **kw):
177 def wrapper(*args, **kw):
178 return new_fn(*args, **kw)
178 return new_fn(*args, **kw)
179 if old_fn.__doc__:
179 if old_fn.__doc__:
180 wrapper.__doc__ = old_fn.__doc__ + additional_text
180 wrapper.__doc__ = old_fn.__doc__ + additional_text
181 return wrapper
181 return wrapper
182
182
183
183
184 def _file_lines(fname):
184 def _file_lines(fname):
185 """Return the contents of a named file as a list of lines.
185 """Return the contents of a named file as a list of lines.
186
186
187 This function never raises an IOError exception: if the file can't be
187 This function never raises an IOError exception: if the file can't be
188 read, it simply returns an empty list."""
188 read, it simply returns an empty list."""
189
189
190 try:
190 try:
191 outfile = open(fname)
191 outfile = open(fname)
192 except IOError:
192 except IOError:
193 return []
193 return []
194 else:
194 else:
195 out = outfile.readlines()
195 out = outfile.readlines()
196 outfile.close()
196 outfile.close()
197 return out
197 return out
198
198
199
199
200 class Pdb(OldPdb):
200 class Pdb(OldPdb):
201 """Modified Pdb class, does not load readline."""
201 """Modified Pdb class, does not load readline."""
202
202
203 def __init__(self,color_scheme='NoColor',completekey=None,
203 def __init__(self,color_scheme='NoColor',completekey=None,
204 stdin=None, stdout=None):
204 stdin=None, stdout=None):
205
205
206 # Parent constructor:
206 # Parent constructor:
207 if has_pydb and completekey is None:
207 if has_pydb and completekey is None:
208 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
208 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
209 else:
209 else:
210 OldPdb.__init__(self,completekey,stdin,stdout)
210 OldPdb.__init__(self,completekey,stdin,stdout)
211
211
212 self.prompt = prompt # The default prompt is '(Pdb)'
212 self.prompt = prompt # The default prompt is '(Pdb)'
213
213
214 # IPython changes...
214 # IPython changes...
215 self.is_pydb = has_pydb
215 self.is_pydb = has_pydb
216
216
217 self.shell = get_ipython()
217 self.shell = get_ipython()
218
218
219 if self.shell is None:
219 if self.shell is None:
220 # No IPython instance running, we must create one
220 # No IPython instance running, we must create one
221 from IPython.terminal.interactiveshell import \
221 from IPython.terminal.interactiveshell import \
222 TerminalInteractiveShell
222 TerminalInteractiveShell
223 self.shell = TerminalInteractiveShell.instance()
223 self.shell = TerminalInteractiveShell.instance()
224
224
225 if self.is_pydb:
225 if self.is_pydb:
226
226
227 # interactiveshell.py's ipalias seems to want pdb's checkline
227 # interactiveshell.py's ipalias seems to want pdb's checkline
228 # which located in pydb.fn
228 # which located in pydb.fn
229 import pydb.fns
229 import pydb.fns
230 self.checkline = lambda filename, lineno: \
230 self.checkline = lambda filename, lineno: \
231 pydb.fns.checkline(self, filename, lineno)
231 pydb.fns.checkline(self, filename, lineno)
232
232
233 self.curframe = None
233 self.curframe = None
234 self.do_restart = self.new_do_restart
234 self.do_restart = self.new_do_restart
235
235
236 self.old_all_completions = self.shell.Completer.all_completions
236 self.old_all_completions = self.shell.Completer.all_completions
237 self.shell.Completer.all_completions=self.all_completions
237 self.shell.Completer.all_completions=self.all_completions
238
238
239 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
239 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
240 OldPdb.do_list)
240 OldPdb.do_list)
241 self.do_l = self.do_list
241 self.do_l = self.do_list
242 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
242 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
243 OldPdb.do_frame)
243 OldPdb.do_frame)
244
244
245 self.aliases = {}
245 self.aliases = {}
246
246
247 # Create color table: we copy the default one from the traceback
247 # Create color table: we copy the default one from the traceback
248 # module and add a few attributes needed for debugging
248 # module and add a few attributes needed for debugging
249 self.color_scheme_table = exception_colors()
249 self.color_scheme_table = exception_colors()
250
250
251 # shorthands
251 # shorthands
252 C = coloransi.TermColors
252 C = coloransi.TermColors
253 cst = self.color_scheme_table
253 cst = self.color_scheme_table
254
254
255 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
255 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
256 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
256 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
257
257
258 cst['Linux'].colors.breakpoint_enabled = C.LightRed
258 cst['Linux'].colors.breakpoint_enabled = C.LightRed
259 cst['Linux'].colors.breakpoint_disabled = C.Red
259 cst['Linux'].colors.breakpoint_disabled = C.Red
260
260
261 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
261 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
262 cst['LightBG'].colors.breakpoint_disabled = C.Red
262 cst['LightBG'].colors.breakpoint_disabled = C.Red
263
263
264 self.set_colors(color_scheme)
264 self.set_colors(color_scheme)
265
265
266 # Add a python parser so we can syntax highlight source while
266 # Add a python parser so we can syntax highlight source while
267 # debugging.
267 # debugging.
268 self.parser = PyColorize.Parser()
268 self.parser = PyColorize.Parser()
269
269
270 def set_colors(self, scheme):
270 def set_colors(self, scheme):
271 """Shorthand access to the color table scheme selector method."""
271 """Shorthand access to the color table scheme selector method."""
272 self.color_scheme_table.set_active_scheme(scheme)
272 self.color_scheme_table.set_active_scheme(scheme)
273
273
274 def interaction(self, frame, traceback):
274 def interaction(self, frame, traceback):
275 self.shell.set_completer_frame(frame)
275 self.shell.set_completer_frame(frame)
276 while True:
276 while True:
277 try:
277 try:
278 OldPdb.interaction(self, frame, traceback)
278 OldPdb.interaction(self, frame, traceback)
279 except KeyboardInterrupt:
279 except KeyboardInterrupt:
280 self.shell.write("\nKeyboardInterrupt\n")
280 self.shell.write('\n' + self.shell.get_exception_only())
281 break
281 break
282 else:
282 else:
283 break
283 break
284
284
285 def new_do_up(self, arg):
285 def new_do_up(self, arg):
286 OldPdb.do_up(self, arg)
286 OldPdb.do_up(self, arg)
287 self.shell.set_completer_frame(self.curframe)
287 self.shell.set_completer_frame(self.curframe)
288 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
288 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
289
289
290 def new_do_down(self, arg):
290 def new_do_down(self, arg):
291 OldPdb.do_down(self, arg)
291 OldPdb.do_down(self, arg)
292 self.shell.set_completer_frame(self.curframe)
292 self.shell.set_completer_frame(self.curframe)
293
293
294 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
294 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
295
295
296 def new_do_frame(self, arg):
296 def new_do_frame(self, arg):
297 OldPdb.do_frame(self, arg)
297 OldPdb.do_frame(self, arg)
298 self.shell.set_completer_frame(self.curframe)
298 self.shell.set_completer_frame(self.curframe)
299
299
300 def new_do_quit(self, arg):
300 def new_do_quit(self, arg):
301
301
302 if hasattr(self, 'old_all_completions'):
302 if hasattr(self, 'old_all_completions'):
303 self.shell.Completer.all_completions=self.old_all_completions
303 self.shell.Completer.all_completions=self.old_all_completions
304
304
305
305
306 return OldPdb.do_quit(self, arg)
306 return OldPdb.do_quit(self, arg)
307
307
308 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
308 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
309
309
310 def new_do_restart(self, arg):
310 def new_do_restart(self, arg):
311 """Restart command. In the context of ipython this is exactly the same
311 """Restart command. In the context of ipython this is exactly the same
312 thing as 'quit'."""
312 thing as 'quit'."""
313 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
313 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
314 return self.do_quit(arg)
314 return self.do_quit(arg)
315
315
316 def postloop(self):
316 def postloop(self):
317 self.shell.set_completer_frame(None)
317 self.shell.set_completer_frame(None)
318
318
319 def print_stack_trace(self):
319 def print_stack_trace(self):
320 try:
320 try:
321 for frame_lineno in self.stack:
321 for frame_lineno in self.stack:
322 self.print_stack_entry(frame_lineno, context = 5)
322 self.print_stack_entry(frame_lineno, context = 5)
323 except KeyboardInterrupt:
323 except KeyboardInterrupt:
324 pass
324 pass
325
325
326 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
326 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
327 context = 3):
327 context = 3):
328 #frame, lineno = frame_lineno
328 #frame, lineno = frame_lineno
329 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
329 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
330
330
331 # vds: >>
331 # vds: >>
332 frame, lineno = frame_lineno
332 frame, lineno = frame_lineno
333 filename = frame.f_code.co_filename
333 filename = frame.f_code.co_filename
334 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
334 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
335 # vds: <<
335 # vds: <<
336
336
337 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
337 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
338 try:
338 try:
339 import reprlib # Py 3
339 import reprlib # Py 3
340 except ImportError:
340 except ImportError:
341 import repr as reprlib # Py 2
341 import repr as reprlib # Py 2
342
342
343 ret = []
343 ret = []
344
344
345 Colors = self.color_scheme_table.active_colors
345 Colors = self.color_scheme_table.active_colors
346 ColorsNormal = Colors.Normal
346 ColorsNormal = Colors.Normal
347 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
347 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
348 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
348 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
349 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
349 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
350 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
350 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
351 ColorsNormal)
351 ColorsNormal)
352
352
353 frame, lineno = frame_lineno
353 frame, lineno = frame_lineno
354
354
355 return_value = ''
355 return_value = ''
356 if '__return__' in frame.f_locals:
356 if '__return__' in frame.f_locals:
357 rv = frame.f_locals['__return__']
357 rv = frame.f_locals['__return__']
358 #return_value += '->'
358 #return_value += '->'
359 return_value += reprlib.repr(rv) + '\n'
359 return_value += reprlib.repr(rv) + '\n'
360 ret.append(return_value)
360 ret.append(return_value)
361
361
362 #s = filename + '(' + `lineno` + ')'
362 #s = filename + '(' + `lineno` + ')'
363 filename = self.canonic(frame.f_code.co_filename)
363 filename = self.canonic(frame.f_code.co_filename)
364 link = tpl_link % py3compat.cast_unicode(filename)
364 link = tpl_link % py3compat.cast_unicode(filename)
365
365
366 if frame.f_code.co_name:
366 if frame.f_code.co_name:
367 func = frame.f_code.co_name
367 func = frame.f_code.co_name
368 else:
368 else:
369 func = "<lambda>"
369 func = "<lambda>"
370
370
371 call = ''
371 call = ''
372 if func != '?':
372 if func != '?':
373 if '__args__' in frame.f_locals:
373 if '__args__' in frame.f_locals:
374 args = reprlib.repr(frame.f_locals['__args__'])
374 args = reprlib.repr(frame.f_locals['__args__'])
375 else:
375 else:
376 args = '()'
376 args = '()'
377 call = tpl_call % (func, args)
377 call = tpl_call % (func, args)
378
378
379 # The level info should be generated in the same format pdb uses, to
379 # The level info should be generated in the same format pdb uses, to
380 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
380 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
381 if frame is self.curframe:
381 if frame is self.curframe:
382 ret.append('> ')
382 ret.append('> ')
383 else:
383 else:
384 ret.append(' ')
384 ret.append(' ')
385 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
385 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
386
386
387 start = lineno - 1 - context//2
387 start = lineno - 1 - context//2
388 lines = ulinecache.getlines(filename)
388 lines = ulinecache.getlines(filename)
389 start = min(start, len(lines) - context)
389 start = min(start, len(lines) - context)
390 start = max(start, 0)
390 start = max(start, 0)
391 lines = lines[start : start + context]
391 lines = lines[start : start + context]
392
392
393 for i,line in enumerate(lines):
393 for i,line in enumerate(lines):
394 show_arrow = (start + 1 + i == lineno)
394 show_arrow = (start + 1 + i == lineno)
395 linetpl = (frame is self.curframe or show_arrow) \
395 linetpl = (frame is self.curframe or show_arrow) \
396 and tpl_line_em \
396 and tpl_line_em \
397 or tpl_line
397 or tpl_line
398 ret.append(self.__format_line(linetpl, filename,
398 ret.append(self.__format_line(linetpl, filename,
399 start + 1 + i, line,
399 start + 1 + i, line,
400 arrow = show_arrow) )
400 arrow = show_arrow) )
401 return ''.join(ret)
401 return ''.join(ret)
402
402
403 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
403 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
404 bp_mark = ""
404 bp_mark = ""
405 bp_mark_color = ""
405 bp_mark_color = ""
406
406
407 scheme = self.color_scheme_table.active_scheme_name
407 scheme = self.color_scheme_table.active_scheme_name
408 new_line, err = self.parser.format2(line, 'str', scheme)
408 new_line, err = self.parser.format2(line, 'str', scheme)
409 if not err: line = new_line
409 if not err: line = new_line
410
410
411 bp = None
411 bp = None
412 if lineno in self.get_file_breaks(filename):
412 if lineno in self.get_file_breaks(filename):
413 bps = self.get_breaks(filename, lineno)
413 bps = self.get_breaks(filename, lineno)
414 bp = bps[-1]
414 bp = bps[-1]
415
415
416 if bp:
416 if bp:
417 Colors = self.color_scheme_table.active_colors
417 Colors = self.color_scheme_table.active_colors
418 bp_mark = str(bp.number)
418 bp_mark = str(bp.number)
419 bp_mark_color = Colors.breakpoint_enabled
419 bp_mark_color = Colors.breakpoint_enabled
420 if not bp.enabled:
420 if not bp.enabled:
421 bp_mark_color = Colors.breakpoint_disabled
421 bp_mark_color = Colors.breakpoint_disabled
422
422
423 numbers_width = 7
423 numbers_width = 7
424 if arrow:
424 if arrow:
425 # This is the line with the error
425 # This is the line with the error
426 pad = numbers_width - len(str(lineno)) - len(bp_mark)
426 pad = numbers_width - len(str(lineno)) - len(bp_mark)
427 if pad >= 3:
427 if pad >= 3:
428 marker = '-'*(pad-3) + '-> '
428 marker = '-'*(pad-3) + '-> '
429 elif pad == 2:
429 elif pad == 2:
430 marker = '> '
430 marker = '> '
431 elif pad == 1:
431 elif pad == 1:
432 marker = '>'
432 marker = '>'
433 else:
433 else:
434 marker = ''
434 marker = ''
435 num = '%s%s' % (marker, str(lineno))
435 num = '%s%s' % (marker, str(lineno))
436 line = tpl_line % (bp_mark_color + bp_mark, num, line)
436 line = tpl_line % (bp_mark_color + bp_mark, num, line)
437 else:
437 else:
438 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
438 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
439 line = tpl_line % (bp_mark_color + bp_mark, num, line)
439 line = tpl_line % (bp_mark_color + bp_mark, num, line)
440
440
441 return line
441 return line
442
442
443 def list_command_pydb(self, arg):
443 def list_command_pydb(self, arg):
444 """List command to use if we have a newer pydb installed"""
444 """List command to use if we have a newer pydb installed"""
445 filename, first, last = OldPdb.parse_list_cmd(self, arg)
445 filename, first, last = OldPdb.parse_list_cmd(self, arg)
446 if filename is not None:
446 if filename is not None:
447 self.print_list_lines(filename, first, last)
447 self.print_list_lines(filename, first, last)
448
448
449 def print_list_lines(self, filename, first, last):
449 def print_list_lines(self, filename, first, last):
450 """The printing (as opposed to the parsing part of a 'list'
450 """The printing (as opposed to the parsing part of a 'list'
451 command."""
451 command."""
452 try:
452 try:
453 Colors = self.color_scheme_table.active_colors
453 Colors = self.color_scheme_table.active_colors
454 ColorsNormal = Colors.Normal
454 ColorsNormal = Colors.Normal
455 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
455 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
456 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
456 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
457 src = []
457 src = []
458 if filename == "<string>" and hasattr(self, "_exec_filename"):
458 if filename == "<string>" and hasattr(self, "_exec_filename"):
459 filename = self._exec_filename
459 filename = self._exec_filename
460
460
461 for lineno in range(first, last+1):
461 for lineno in range(first, last+1):
462 line = ulinecache.getline(filename, lineno)
462 line = ulinecache.getline(filename, lineno)
463 if not line:
463 if not line:
464 break
464 break
465
465
466 if lineno == self.curframe.f_lineno:
466 if lineno == self.curframe.f_lineno:
467 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
467 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
468 else:
468 else:
469 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
469 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
470
470
471 src.append(line)
471 src.append(line)
472 self.lineno = lineno
472 self.lineno = lineno
473
473
474 print(''.join(src), file=io.stdout)
474 print(''.join(src), file=io.stdout)
475
475
476 except KeyboardInterrupt:
476 except KeyboardInterrupt:
477 pass
477 pass
478
478
479 def do_list(self, arg):
479 def do_list(self, arg):
480 self.lastcmd = 'list'
480 self.lastcmd = 'list'
481 last = None
481 last = None
482 if arg:
482 if arg:
483 try:
483 try:
484 x = eval(arg, {}, {})
484 x = eval(arg, {}, {})
485 if type(x) == type(()):
485 if type(x) == type(()):
486 first, last = x
486 first, last = x
487 first = int(first)
487 first = int(first)
488 last = int(last)
488 last = int(last)
489 if last < first:
489 if last < first:
490 # Assume it's a count
490 # Assume it's a count
491 last = first + last
491 last = first + last
492 else:
492 else:
493 first = max(1, int(x) - 5)
493 first = max(1, int(x) - 5)
494 except:
494 except:
495 print('*** Error in argument:', repr(arg))
495 print('*** Error in argument:', repr(arg))
496 return
496 return
497 elif self.lineno is None:
497 elif self.lineno is None:
498 first = max(1, self.curframe.f_lineno - 5)
498 first = max(1, self.curframe.f_lineno - 5)
499 else:
499 else:
500 first = self.lineno + 1
500 first = self.lineno + 1
501 if last is None:
501 if last is None:
502 last = first + 10
502 last = first + 10
503 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
503 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
504
504
505 # vds: >>
505 # vds: >>
506 lineno = first
506 lineno = first
507 filename = self.curframe.f_code.co_filename
507 filename = self.curframe.f_code.co_filename
508 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
508 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
509 # vds: <<
509 # vds: <<
510
510
511 do_l = do_list
511 do_l = do_list
512
512
513 def do_pdef(self, arg):
513 def do_pdef(self, arg):
514 """Print the call signature for any callable object.
514 """Print the call signature for any callable object.
515
515
516 The debugger interface to %pdef"""
516 The debugger interface to %pdef"""
517 namespaces = [('Locals', self.curframe.f_locals),
517 namespaces = [('Locals', self.curframe.f_locals),
518 ('Globals', self.curframe.f_globals)]
518 ('Globals', self.curframe.f_globals)]
519 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
519 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
520
520
521 def do_pdoc(self, arg):
521 def do_pdoc(self, arg):
522 """Print the docstring for an object.
522 """Print the docstring for an object.
523
523
524 The debugger interface to %pdoc."""
524 The debugger interface to %pdoc."""
525 namespaces = [('Locals', self.curframe.f_locals),
525 namespaces = [('Locals', self.curframe.f_locals),
526 ('Globals', self.curframe.f_globals)]
526 ('Globals', self.curframe.f_globals)]
527 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
527 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
528
528
529 def do_pfile(self, arg):
529 def do_pfile(self, arg):
530 """Print (or run through pager) the file where an object is defined.
530 """Print (or run through pager) the file where an object is defined.
531
531
532 The debugger interface to %pfile.
532 The debugger interface to %pfile.
533 """
533 """
534 namespaces = [('Locals', self.curframe.f_locals),
534 namespaces = [('Locals', self.curframe.f_locals),
535 ('Globals', self.curframe.f_globals)]
535 ('Globals', self.curframe.f_globals)]
536 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
536 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
537
537
538 def do_pinfo(self, arg):
538 def do_pinfo(self, arg):
539 """Provide detailed information about an object.
539 """Provide detailed information about an object.
540
540
541 The debugger interface to %pinfo, i.e., obj?."""
541 The debugger interface to %pinfo, i.e., obj?."""
542 namespaces = [('Locals', self.curframe.f_locals),
542 namespaces = [('Locals', self.curframe.f_locals),
543 ('Globals', self.curframe.f_globals)]
543 ('Globals', self.curframe.f_globals)]
544 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
544 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
545
545
546 def do_pinfo2(self, arg):
546 def do_pinfo2(self, arg):
547 """Provide extra detailed information about an object.
547 """Provide extra detailed information about an object.
548
548
549 The debugger interface to %pinfo2, i.e., obj??."""
549 The debugger interface to %pinfo2, i.e., obj??."""
550 namespaces = [('Locals', self.curframe.f_locals),
550 namespaces = [('Locals', self.curframe.f_locals),
551 ('Globals', self.curframe.f_globals)]
551 ('Globals', self.curframe.f_globals)]
552 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
552 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
553
553
554 def do_psource(self, arg):
554 def do_psource(self, arg):
555 """Print (or run through pager) the source code for an object."""
555 """Print (or run through pager) the source code for an object."""
556 namespaces = [('Locals', self.curframe.f_locals),
556 namespaces = [('Locals', self.curframe.f_locals),
557 ('Globals', self.curframe.f_globals)]
557 ('Globals', self.curframe.f_globals)]
558 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
558 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
559
559
560 def checkline(self, filename, lineno):
560 def checkline(self, filename, lineno):
561 """Check whether specified line seems to be executable.
561 """Check whether specified line seems to be executable.
562
562
563 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
563 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
564 line or EOF). Warning: testing is not comprehensive.
564 line or EOF). Warning: testing is not comprehensive.
565 """
565 """
566 #######################################################################
566 #######################################################################
567 # XXX Hack! Use python-2.5 compatible code for this call, because with
567 # XXX Hack! Use python-2.5 compatible code for this call, because with
568 # all of our changes, we've drifted from the pdb api in 2.6. For now,
568 # all of our changes, we've drifted from the pdb api in 2.6. For now,
569 # changing:
569 # changing:
570 #
570 #
571 #line = linecache.getline(filename, lineno, self.curframe.f_globals)
571 #line = linecache.getline(filename, lineno, self.curframe.f_globals)
572 # to:
572 # to:
573 #
573 #
574 line = linecache.getline(filename, lineno)
574 line = linecache.getline(filename, lineno)
575 #
575 #
576 # does the trick. But in reality, we need to fix this by reconciling
576 # does the trick. But in reality, we need to fix this by reconciling
577 # our updates with the new Pdb APIs in Python 2.6.
577 # our updates with the new Pdb APIs in Python 2.6.
578 #
578 #
579 # End hack. The rest of this method is copied verbatim from 2.6 pdb.py
579 # End hack. The rest of this method is copied verbatim from 2.6 pdb.py
580 #######################################################################
580 #######################################################################
581
581
582 if not line:
582 if not line:
583 print('End of file', file=self.stdout)
583 print('End of file', file=self.stdout)
584 return 0
584 return 0
585 line = line.strip()
585 line = line.strip()
586 # Don't allow setting breakpoint at a blank line
586 # Don't allow setting breakpoint at a blank line
587 if (not line or (line[0] == '#') or
587 if (not line or (line[0] == '#') or
588 (line[:3] == '"""') or line[:3] == "'''"):
588 (line[:3] == '"""') or line[:3] == "'''"):
589 print('*** Blank or comment', file=self.stdout)
589 print('*** Blank or comment', file=self.stdout)
590 return 0
590 return 0
591 return lineno
591 return lineno
@@ -1,859 +1,944 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Top-level display functions for displaying object in different formats.
2 """Top-level display functions for displaying object in different formats.
3
3
4 Authors:
4 Authors:
5
5
6 * Brian Granger
6 * Brian Granger
7 """
7 """
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2013 The IPython Development Team
10 # Copyright (C) 2013 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 from __future__ import print_function
20 from __future__ import print_function
21
21
22 import os
22 import os
23 import struct
23 import struct
24 import mimetypes
24
25
25 from IPython.core.formatters import _safe_get_formatter_method
26 from IPython.core.formatters import _safe_get_formatter_method
26 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
27 from IPython.utils.py3compat import (string_types, cast_bytes_py2, cast_unicode,
27 unicode_type)
28 unicode_type)
28 from IPython.testing.skipdoctest import skip_doctest
29 from IPython.testing.skipdoctest import skip_doctest
29
30
30 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
31 __all__ = ['display', 'display_pretty', 'display_html', 'display_markdown',
31 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
32 'display_svg', 'display_png', 'display_jpeg', 'display_latex', 'display_json',
32 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
33 'display_javascript', 'display_pdf', 'DisplayObject', 'TextDisplayObject',
33 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
34 'Pretty', 'HTML', 'Markdown', 'Math', 'Latex', 'SVG', 'JSON', 'Javascript',
34 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
35 'Image', 'clear_output', 'set_matplotlib_formats', 'set_matplotlib_close',
35 'publish_display_data']
36 'publish_display_data']
36
37
37 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
38 # utility functions
39 # utility functions
39 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
40
41
41 def _safe_exists(path):
42 def _safe_exists(path):
42 """Check path, but don't let exceptions raise"""
43 """Check path, but don't let exceptions raise"""
43 try:
44 try:
44 return os.path.exists(path)
45 return os.path.exists(path)
45 except Exception:
46 except Exception:
46 return False
47 return False
47
48
48 def _merge(d1, d2):
49 def _merge(d1, d2):
49 """Like update, but merges sub-dicts instead of clobbering at the top level.
50 """Like update, but merges sub-dicts instead of clobbering at the top level.
50
51
51 Updates d1 in-place
52 Updates d1 in-place
52 """
53 """
53
54
54 if not isinstance(d2, dict) or not isinstance(d1, dict):
55 if not isinstance(d2, dict) or not isinstance(d1, dict):
55 return d2
56 return d2
56 for key, value in d2.items():
57 for key, value in d2.items():
57 d1[key] = _merge(d1.get(key), value)
58 d1[key] = _merge(d1.get(key), value)
58 return d1
59 return d1
59
60
60 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
61 def _display_mimetype(mimetype, objs, raw=False, metadata=None):
61 """internal implementation of all display_foo methods
62 """internal implementation of all display_foo methods
62
63
63 Parameters
64 Parameters
64 ----------
65 ----------
65 mimetype : str
66 mimetype : str
66 The mimetype to be published (e.g. 'image/png')
67 The mimetype to be published (e.g. 'image/png')
67 objs : tuple of objects
68 objs : tuple of objects
68 The Python objects to display, or if raw=True raw text data to
69 The Python objects to display, or if raw=True raw text data to
69 display.
70 display.
70 raw : bool
71 raw : bool
71 Are the data objects raw data or Python objects that need to be
72 Are the data objects raw data or Python objects that need to be
72 formatted before display? [default: False]
73 formatted before display? [default: False]
73 metadata : dict (optional)
74 metadata : dict (optional)
74 Metadata to be associated with the specific mimetype output.
75 Metadata to be associated with the specific mimetype output.
75 """
76 """
76 if metadata:
77 if metadata:
77 metadata = {mimetype: metadata}
78 metadata = {mimetype: metadata}
78 if raw:
79 if raw:
79 # turn list of pngdata into list of { 'image/png': pngdata }
80 # turn list of pngdata into list of { 'image/png': pngdata }
80 objs = [ {mimetype: obj} for obj in objs ]
81 objs = [ {mimetype: obj} for obj in objs ]
81 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
82 display(*objs, raw=raw, metadata=metadata, include=[mimetype])
82
83
83 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
84 # Main functions
85 # Main functions
85 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
86
87
87 def publish_display_data(data, metadata=None, source=None):
88 def publish_display_data(data, metadata=None, source=None):
88 """Publish data and metadata to all frontends.
89 """Publish data and metadata to all frontends.
89
90
90 See the ``display_data`` message in the messaging documentation for
91 See the ``display_data`` message in the messaging documentation for
91 more details about this message type.
92 more details about this message type.
92
93
93 The following MIME types are currently implemented:
94 The following MIME types are currently implemented:
94
95
95 * text/plain
96 * text/plain
96 * text/html
97 * text/html
97 * text/markdown
98 * text/markdown
98 * text/latex
99 * text/latex
99 * application/json
100 * application/json
100 * application/javascript
101 * application/javascript
101 * image/png
102 * image/png
102 * image/jpeg
103 * image/jpeg
103 * image/svg+xml
104 * image/svg+xml
104
105
105 Parameters
106 Parameters
106 ----------
107 ----------
107 data : dict
108 data : dict
108 A dictionary having keys that are valid MIME types (like
109 A dictionary having keys that are valid MIME types (like
109 'text/plain' or 'image/svg+xml') and values that are the data for
110 'text/plain' or 'image/svg+xml') and values that are the data for
110 that MIME type. The data itself must be a JSON'able data
111 that MIME type. The data itself must be a JSON'able data
111 structure. Minimally all data should have the 'text/plain' data,
112 structure. Minimally all data should have the 'text/plain' data,
112 which can be displayed by all frontends. If more than the plain
113 which can be displayed by all frontends. If more than the plain
113 text is given, it is up to the frontend to decide which
114 text is given, it is up to the frontend to decide which
114 representation to use.
115 representation to use.
115 metadata : dict
116 metadata : dict
116 A dictionary for metadata related to the data. This can contain
117 A dictionary for metadata related to the data. This can contain
117 arbitrary key, value pairs that frontends can use to interpret
118 arbitrary key, value pairs that frontends can use to interpret
118 the data. mime-type keys matching those in data can be used
119 the data. mime-type keys matching those in data can be used
119 to specify metadata about particular representations.
120 to specify metadata about particular representations.
120 source : str, deprecated
121 source : str, deprecated
121 Unused.
122 Unused.
122 """
123 """
123 from IPython.core.interactiveshell import InteractiveShell
124 from IPython.core.interactiveshell import InteractiveShell
124 InteractiveShell.instance().display_pub.publish(
125 InteractiveShell.instance().display_pub.publish(
125 data=data,
126 data=data,
126 metadata=metadata,
127 metadata=metadata,
127 )
128 )
128
129
129 def display(*objs, **kwargs):
130 def display(*objs, **kwargs):
130 """Display a Python object in all frontends.
131 """Display a Python object in all frontends.
131
132
132 By default all representations will be computed and sent to the frontends.
133 By default all representations will be computed and sent to the frontends.
133 Frontends can decide which representation is used and how.
134 Frontends can decide which representation is used and how.
134
135
135 Parameters
136 Parameters
136 ----------
137 ----------
137 objs : tuple of objects
138 objs : tuple of objects
138 The Python objects to display.
139 The Python objects to display.
139 raw : bool, optional
140 raw : bool, optional
140 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
141 Are the objects to be displayed already mimetype-keyed dicts of raw display data,
141 or Python objects that need to be formatted before display? [default: False]
142 or Python objects that need to be formatted before display? [default: False]
142 include : list or tuple, optional
143 include : list or tuple, optional
143 A list of format type strings (MIME types) to include in the
144 A list of format type strings (MIME types) to include in the
144 format data dict. If this is set *only* the format types included
145 format data dict. If this is set *only* the format types included
145 in this list will be computed.
146 in this list will be computed.
146 exclude : list or tuple, optional
147 exclude : list or tuple, optional
147 A list of format type strings (MIME types) to exclude in the format
148 A list of format type strings (MIME types) to exclude in the format
148 data dict. If this is set all format types will be computed,
149 data dict. If this is set all format types will be computed,
149 except for those included in this argument.
150 except for those included in this argument.
150 metadata : dict, optional
151 metadata : dict, optional
151 A dictionary of metadata to associate with the output.
152 A dictionary of metadata to associate with the output.
152 mime-type keys in this dictionary will be associated with the individual
153 mime-type keys in this dictionary will be associated with the individual
153 representation formats, if they exist.
154 representation formats, if they exist.
154 """
155 """
155 raw = kwargs.get('raw', False)
156 raw = kwargs.get('raw', False)
156 include = kwargs.get('include')
157 include = kwargs.get('include')
157 exclude = kwargs.get('exclude')
158 exclude = kwargs.get('exclude')
158 metadata = kwargs.get('metadata')
159 metadata = kwargs.get('metadata')
159
160
160 from IPython.core.interactiveshell import InteractiveShell
161 from IPython.core.interactiveshell import InteractiveShell
161
162
162 if not raw:
163 if not raw:
163 format = InteractiveShell.instance().display_formatter.format
164 format = InteractiveShell.instance().display_formatter.format
164
165
165 for obj in objs:
166 for obj in objs:
166
167
167 # If _ipython_display_ is defined, use that to display this object.
168 # If _ipython_display_ is defined, use that to display this object.
168 display_method = _safe_get_formatter_method(obj, '_ipython_display_')
169 display_method = _safe_get_formatter_method(obj, '_ipython_display_')
169 if display_method is not None:
170 if display_method is not None:
170 try:
171 try:
171 display_method(**kwargs)
172 display_method(**kwargs)
172 except NotImplementedError:
173 except NotImplementedError:
173 pass
174 pass
174 else:
175 else:
175 continue
176 continue
176 if raw:
177 if raw:
177 publish_display_data(data=obj, metadata=metadata)
178 publish_display_data(data=obj, metadata=metadata)
178 else:
179 else:
179 format_dict, md_dict = format(obj, include=include, exclude=exclude)
180 format_dict, md_dict = format(obj, include=include, exclude=exclude)
180 if metadata:
181 if metadata:
181 # kwarg-specified metadata gets precedence
182 # kwarg-specified metadata gets precedence
182 _merge(md_dict, metadata)
183 _merge(md_dict, metadata)
183 publish_display_data(data=format_dict, metadata=md_dict)
184 publish_display_data(data=format_dict, metadata=md_dict)
184
185
185
186
186 def display_pretty(*objs, **kwargs):
187 def display_pretty(*objs, **kwargs):
187 """Display the pretty (default) representation of an object.
188 """Display the pretty (default) representation of an object.
188
189
189 Parameters
190 Parameters
190 ----------
191 ----------
191 objs : tuple of objects
192 objs : tuple of objects
192 The Python objects to display, or if raw=True raw text data to
193 The Python objects to display, or if raw=True raw text data to
193 display.
194 display.
194 raw : bool
195 raw : bool
195 Are the data objects raw data or Python objects that need to be
196 Are the data objects raw data or Python objects that need to be
196 formatted before display? [default: False]
197 formatted before display? [default: False]
197 metadata : dict (optional)
198 metadata : dict (optional)
198 Metadata to be associated with the specific mimetype output.
199 Metadata to be associated with the specific mimetype output.
199 """
200 """
200 _display_mimetype('text/plain', objs, **kwargs)
201 _display_mimetype('text/plain', objs, **kwargs)
201
202
202
203
203 def display_html(*objs, **kwargs):
204 def display_html(*objs, **kwargs):
204 """Display the HTML representation of an object.
205 """Display the HTML representation of an object.
205
206
206 Parameters
207 Parameters
207 ----------
208 ----------
208 objs : tuple of objects
209 objs : tuple of objects
209 The Python objects to display, or if raw=True raw HTML data to
210 The Python objects to display, or if raw=True raw HTML data to
210 display.
211 display.
211 raw : bool
212 raw : bool
212 Are the data objects raw data or Python objects that need to be
213 Are the data objects raw data or Python objects that need to be
213 formatted before display? [default: False]
214 formatted before display? [default: False]
214 metadata : dict (optional)
215 metadata : dict (optional)
215 Metadata to be associated with the specific mimetype output.
216 Metadata to be associated with the specific mimetype output.
216 """
217 """
217 _display_mimetype('text/html', objs, **kwargs)
218 _display_mimetype('text/html', objs, **kwargs)
218
219
219
220
220 def display_markdown(*objs, **kwargs):
221 def display_markdown(*objs, **kwargs):
221 """Displays the Markdown representation of an object.
222 """Displays the Markdown representation of an object.
222
223
223 Parameters
224 Parameters
224 ----------
225 ----------
225 objs : tuple of objects
226 objs : tuple of objects
226 The Python objects to display, or if raw=True raw markdown data to
227 The Python objects to display, or if raw=True raw markdown data to
227 display.
228 display.
228 raw : bool
229 raw : bool
229 Are the data objects raw data or Python objects that need to be
230 Are the data objects raw data or Python objects that need to be
230 formatted before display? [default: False]
231 formatted before display? [default: False]
231 metadata : dict (optional)
232 metadata : dict (optional)
232 Metadata to be associated with the specific mimetype output.
233 Metadata to be associated with the specific mimetype output.
233 """
234 """
234
235
235 _display_mimetype('text/markdown', objs, **kwargs)
236 _display_mimetype('text/markdown', objs, **kwargs)
236
237
237
238
238 def display_svg(*objs, **kwargs):
239 def display_svg(*objs, **kwargs):
239 """Display the SVG representation of an object.
240 """Display the SVG representation of an object.
240
241
241 Parameters
242 Parameters
242 ----------
243 ----------
243 objs : tuple of objects
244 objs : tuple of objects
244 The Python objects to display, or if raw=True raw svg data to
245 The Python objects to display, or if raw=True raw svg data to
245 display.
246 display.
246 raw : bool
247 raw : bool
247 Are the data objects raw data or Python objects that need to be
248 Are the data objects raw data or Python objects that need to be
248 formatted before display? [default: False]
249 formatted before display? [default: False]
249 metadata : dict (optional)
250 metadata : dict (optional)
250 Metadata to be associated with the specific mimetype output.
251 Metadata to be associated with the specific mimetype output.
251 """
252 """
252 _display_mimetype('image/svg+xml', objs, **kwargs)
253 _display_mimetype('image/svg+xml', objs, **kwargs)
253
254
254
255
255 def display_png(*objs, **kwargs):
256 def display_png(*objs, **kwargs):
256 """Display the PNG representation of an object.
257 """Display the PNG representation of an object.
257
258
258 Parameters
259 Parameters
259 ----------
260 ----------
260 objs : tuple of objects
261 objs : tuple of objects
261 The Python objects to display, or if raw=True raw png data to
262 The Python objects to display, or if raw=True raw png data to
262 display.
263 display.
263 raw : bool
264 raw : bool
264 Are the data objects raw data or Python objects that need to be
265 Are the data objects raw data or Python objects that need to be
265 formatted before display? [default: False]
266 formatted before display? [default: False]
266 metadata : dict (optional)
267 metadata : dict (optional)
267 Metadata to be associated with the specific mimetype output.
268 Metadata to be associated with the specific mimetype output.
268 """
269 """
269 _display_mimetype('image/png', objs, **kwargs)
270 _display_mimetype('image/png', objs, **kwargs)
270
271
271
272
272 def display_jpeg(*objs, **kwargs):
273 def display_jpeg(*objs, **kwargs):
273 """Display the JPEG representation of an object.
274 """Display the JPEG representation of an object.
274
275
275 Parameters
276 Parameters
276 ----------
277 ----------
277 objs : tuple of objects
278 objs : tuple of objects
278 The Python objects to display, or if raw=True raw JPEG data to
279 The Python objects to display, or if raw=True raw JPEG data to
279 display.
280 display.
280 raw : bool
281 raw : bool
281 Are the data objects raw data or Python objects that need to be
282 Are the data objects raw data or Python objects that need to be
282 formatted before display? [default: False]
283 formatted before display? [default: False]
283 metadata : dict (optional)
284 metadata : dict (optional)
284 Metadata to be associated with the specific mimetype output.
285 Metadata to be associated with the specific mimetype output.
285 """
286 """
286 _display_mimetype('image/jpeg', objs, **kwargs)
287 _display_mimetype('image/jpeg', objs, **kwargs)
287
288
288
289
289 def display_latex(*objs, **kwargs):
290 def display_latex(*objs, **kwargs):
290 """Display the LaTeX representation of an object.
291 """Display the LaTeX representation of an object.
291
292
292 Parameters
293 Parameters
293 ----------
294 ----------
294 objs : tuple of objects
295 objs : tuple of objects
295 The Python objects to display, or if raw=True raw latex data to
296 The Python objects to display, or if raw=True raw latex data to
296 display.
297 display.
297 raw : bool
298 raw : bool
298 Are the data objects raw data or Python objects that need to be
299 Are the data objects raw data or Python objects that need to be
299 formatted before display? [default: False]
300 formatted before display? [default: False]
300 metadata : dict (optional)
301 metadata : dict (optional)
301 Metadata to be associated with the specific mimetype output.
302 Metadata to be associated with the specific mimetype output.
302 """
303 """
303 _display_mimetype('text/latex', objs, **kwargs)
304 _display_mimetype('text/latex', objs, **kwargs)
304
305
305
306
306 def display_json(*objs, **kwargs):
307 def display_json(*objs, **kwargs):
307 """Display the JSON representation of an object.
308 """Display the JSON representation of an object.
308
309
309 Note that not many frontends support displaying JSON.
310 Note that not many frontends support displaying JSON.
310
311
311 Parameters
312 Parameters
312 ----------
313 ----------
313 objs : tuple of objects
314 objs : tuple of objects
314 The Python objects to display, or if raw=True raw json data to
315 The Python objects to display, or if raw=True raw json data to
315 display.
316 display.
316 raw : bool
317 raw : bool
317 Are the data objects raw data or Python objects that need to be
318 Are the data objects raw data or Python objects that need to be
318 formatted before display? [default: False]
319 formatted before display? [default: False]
319 metadata : dict (optional)
320 metadata : dict (optional)
320 Metadata to be associated with the specific mimetype output.
321 Metadata to be associated with the specific mimetype output.
321 """
322 """
322 _display_mimetype('application/json', objs, **kwargs)
323 _display_mimetype('application/json', objs, **kwargs)
323
324
324
325
325 def display_javascript(*objs, **kwargs):
326 def display_javascript(*objs, **kwargs):
326 """Display the Javascript representation of an object.
327 """Display the Javascript representation of an object.
327
328
328 Parameters
329 Parameters
329 ----------
330 ----------
330 objs : tuple of objects
331 objs : tuple of objects
331 The Python objects to display, or if raw=True raw javascript data to
332 The Python objects to display, or if raw=True raw javascript data to
332 display.
333 display.
333 raw : bool
334 raw : bool
334 Are the data objects raw data or Python objects that need to be
335 Are the data objects raw data or Python objects that need to be
335 formatted before display? [default: False]
336 formatted before display? [default: False]
336 metadata : dict (optional)
337 metadata : dict (optional)
337 Metadata to be associated with the specific mimetype output.
338 Metadata to be associated with the specific mimetype output.
338 """
339 """
339 _display_mimetype('application/javascript', objs, **kwargs)
340 _display_mimetype('application/javascript', objs, **kwargs)
340
341
341
342
342 def display_pdf(*objs, **kwargs):
343 def display_pdf(*objs, **kwargs):
343 """Display the PDF representation of an object.
344 """Display the PDF representation of an object.
344
345
345 Parameters
346 Parameters
346 ----------
347 ----------
347 objs : tuple of objects
348 objs : tuple of objects
348 The Python objects to display, or if raw=True raw javascript data to
349 The Python objects to display, or if raw=True raw javascript data to
349 display.
350 display.
350 raw : bool
351 raw : bool
351 Are the data objects raw data or Python objects that need to be
352 Are the data objects raw data or Python objects that need to be
352 formatted before display? [default: False]
353 formatted before display? [default: False]
353 metadata : dict (optional)
354 metadata : dict (optional)
354 Metadata to be associated with the specific mimetype output.
355 Metadata to be associated with the specific mimetype output.
355 """
356 """
356 _display_mimetype('application/pdf', objs, **kwargs)
357 _display_mimetype('application/pdf', objs, **kwargs)
357
358
358
359
359 #-----------------------------------------------------------------------------
360 #-----------------------------------------------------------------------------
360 # Smart classes
361 # Smart classes
361 #-----------------------------------------------------------------------------
362 #-----------------------------------------------------------------------------
362
363
363
364
364 class DisplayObject(object):
365 class DisplayObject(object):
365 """An object that wraps data to be displayed."""
366 """An object that wraps data to be displayed."""
366
367
367 _read_flags = 'r'
368 _read_flags = 'r'
368 _show_mem_addr = False
369 _show_mem_addr = False
369
370
370 def __init__(self, data=None, url=None, filename=None):
371 def __init__(self, data=None, url=None, filename=None):
371 """Create a display object given raw data.
372 """Create a display object given raw data.
372
373
373 When this object is returned by an expression or passed to the
374 When this object is returned by an expression or passed to the
374 display function, it will result in the data being displayed
375 display function, it will result in the data being displayed
375 in the frontend. The MIME type of the data should match the
376 in the frontend. The MIME type of the data should match the
376 subclasses used, so the Png subclass should be used for 'image/png'
377 subclasses used, so the Png subclass should be used for 'image/png'
377 data. If the data is a URL, the data will first be downloaded
378 data. If the data is a URL, the data will first be downloaded
378 and then displayed. If
379 and then displayed. If
379
380
380 Parameters
381 Parameters
381 ----------
382 ----------
382 data : unicode, str or bytes
383 data : unicode, str or bytes
383 The raw data or a URL or file to load the data from
384 The raw data or a URL or file to load the data from
384 url : unicode
385 url : unicode
385 A URL to download the data from.
386 A URL to download the data from.
386 filename : unicode
387 filename : unicode
387 Path to a local file to load the data from.
388 Path to a local file to load the data from.
388 """
389 """
389 if data is not None and isinstance(data, string_types):
390 if data is not None and isinstance(data, string_types):
390 if data.startswith('http') and url is None:
391 if data.startswith('http') and url is None:
391 url = data
392 url = data
392 filename = None
393 filename = None
393 data = None
394 data = None
394 elif _safe_exists(data) and filename is None:
395 elif _safe_exists(data) and filename is None:
395 url = None
396 url = None
396 filename = data
397 filename = data
397 data = None
398 data = None
398
399
399 self.data = data
400 self.data = data
400 self.url = url
401 self.url = url
401 self.filename = None if filename is None else unicode_type(filename)
402 self.filename = None if filename is None else unicode_type(filename)
402
403
403 self.reload()
404 self.reload()
404 self._check_data()
405 self._check_data()
405
406
406 def __repr__(self):
407 def __repr__(self):
407 if not self._show_mem_addr:
408 if not self._show_mem_addr:
408 cls = self.__class__
409 cls = self.__class__
409 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
410 r = "<%s.%s object>" % (cls.__module__, cls.__name__)
410 else:
411 else:
411 r = super(DisplayObject, self).__repr__()
412 r = super(DisplayObject, self).__repr__()
412 return r
413 return r
413
414
414 def _check_data(self):
415 def _check_data(self):
415 """Override in subclasses if there's something to check."""
416 """Override in subclasses if there's something to check."""
416 pass
417 pass
417
418
418 def reload(self):
419 def reload(self):
419 """Reload the raw data from file or URL."""
420 """Reload the raw data from file or URL."""
420 if self.filename is not None:
421 if self.filename is not None:
421 with open(self.filename, self._read_flags) as f:
422 with open(self.filename, self._read_flags) as f:
422 self.data = f.read()
423 self.data = f.read()
423 elif self.url is not None:
424 elif self.url is not None:
424 try:
425 try:
425 try:
426 try:
426 from urllib.request import urlopen # Py3
427 from urllib.request import urlopen # Py3
427 except ImportError:
428 except ImportError:
428 from urllib2 import urlopen
429 from urllib2 import urlopen
429 response = urlopen(self.url)
430 response = urlopen(self.url)
430 self.data = response.read()
431 self.data = response.read()
431 # extract encoding from header, if there is one:
432 # extract encoding from header, if there is one:
432 encoding = None
433 encoding = None
433 for sub in response.headers['content-type'].split(';'):
434 for sub in response.headers['content-type'].split(';'):
434 sub = sub.strip()
435 sub = sub.strip()
435 if sub.startswith('charset'):
436 if sub.startswith('charset'):
436 encoding = sub.split('=')[-1].strip()
437 encoding = sub.split('=')[-1].strip()
437 break
438 break
438 # decode data, if an encoding was specified
439 # decode data, if an encoding was specified
439 if encoding:
440 if encoding:
440 self.data = self.data.decode(encoding, 'replace')
441 self.data = self.data.decode(encoding, 'replace')
441 except:
442 except:
442 self.data = None
443 self.data = None
443
444
444 class TextDisplayObject(DisplayObject):
445 class TextDisplayObject(DisplayObject):
445 """Validate that display data is text"""
446 """Validate that display data is text"""
446 def _check_data(self):
447 def _check_data(self):
447 if self.data is not None and not isinstance(self.data, string_types):
448 if self.data is not None and not isinstance(self.data, string_types):
448 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
449 raise TypeError("%s expects text, not %r" % (self.__class__.__name__, self.data))
449
450
450 class Pretty(TextDisplayObject):
451 class Pretty(TextDisplayObject):
451
452
452 def _repr_pretty_(self):
453 def _repr_pretty_(self):
453 return self.data
454 return self.data
454
455
455
456
456 class HTML(TextDisplayObject):
457 class HTML(TextDisplayObject):
457
458
458 def _repr_html_(self):
459 def _repr_html_(self):
459 return self.data
460 return self.data
460
461
461 def __html__(self):
462 def __html__(self):
462 """
463 """
463 This method exists to inform other HTML-using modules (e.g. Markupsafe,
464 This method exists to inform other HTML-using modules (e.g. Markupsafe,
464 htmltag, etc) that this object is HTML and does not need things like
465 htmltag, etc) that this object is HTML and does not need things like
465 special characters (<>&) escaped.
466 special characters (<>&) escaped.
466 """
467 """
467 return self._repr_html_()
468 return self._repr_html_()
468
469
469
470
470 class Markdown(TextDisplayObject):
471 class Markdown(TextDisplayObject):
471
472
472 def _repr_markdown_(self):
473 def _repr_markdown_(self):
473 return self.data
474 return self.data
474
475
475
476
476 class Math(TextDisplayObject):
477 class Math(TextDisplayObject):
477
478
478 def _repr_latex_(self):
479 def _repr_latex_(self):
479 s = self.data.strip('$')
480 s = self.data.strip('$')
480 return "$$%s$$" % s
481 return "$$%s$$" % s
481
482
482
483
483 class Latex(TextDisplayObject):
484 class Latex(TextDisplayObject):
484
485
485 def _repr_latex_(self):
486 def _repr_latex_(self):
486 return self.data
487 return self.data
487
488
488
489
489 class SVG(DisplayObject):
490 class SVG(DisplayObject):
490
491
491 # wrap data in a property, which extracts the <svg> tag, discarding
492 # wrap data in a property, which extracts the <svg> tag, discarding
492 # document headers
493 # document headers
493 _data = None
494 _data = None
494
495
495 @property
496 @property
496 def data(self):
497 def data(self):
497 return self._data
498 return self._data
498
499
499 @data.setter
500 @data.setter
500 def data(self, svg):
501 def data(self, svg):
501 if svg is None:
502 if svg is None:
502 self._data = None
503 self._data = None
503 return
504 return
504 # parse into dom object
505 # parse into dom object
505 from xml.dom import minidom
506 from xml.dom import minidom
506 svg = cast_bytes_py2(svg)
507 svg = cast_bytes_py2(svg)
507 x = minidom.parseString(svg)
508 x = minidom.parseString(svg)
508 # get svg tag (should be 1)
509 # get svg tag (should be 1)
509 found_svg = x.getElementsByTagName('svg')
510 found_svg = x.getElementsByTagName('svg')
510 if found_svg:
511 if found_svg:
511 svg = found_svg[0].toxml()
512 svg = found_svg[0].toxml()
512 else:
513 else:
513 # fallback on the input, trust the user
514 # fallback on the input, trust the user
514 # but this is probably an error.
515 # but this is probably an error.
515 pass
516 pass
516 svg = cast_unicode(svg)
517 svg = cast_unicode(svg)
517 self._data = svg
518 self._data = svg
518
519
519 def _repr_svg_(self):
520 def _repr_svg_(self):
520 return self.data
521 return self.data
521
522
522
523
523 class JSON(TextDisplayObject):
524 class JSON(TextDisplayObject):
524
525
525 def _repr_json_(self):
526 def _repr_json_(self):
526 return self.data
527 return self.data
527
528
528 css_t = """$("head").append($("<link/>").attr({
529 css_t = """$("head").append($("<link/>").attr({
529 rel: "stylesheet",
530 rel: "stylesheet",
530 type: "text/css",
531 type: "text/css",
531 href: "%s"
532 href: "%s"
532 }));
533 }));
533 """
534 """
534
535
535 lib_t1 = """$.getScript("%s", function () {
536 lib_t1 = """$.getScript("%s", function () {
536 """
537 """
537 lib_t2 = """});
538 lib_t2 = """});
538 """
539 """
539
540
540 class Javascript(TextDisplayObject):
541 class Javascript(TextDisplayObject):
541
542
542 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
543 def __init__(self, data=None, url=None, filename=None, lib=None, css=None):
543 """Create a Javascript display object given raw data.
544 """Create a Javascript display object given raw data.
544
545
545 When this object is returned by an expression or passed to the
546 When this object is returned by an expression or passed to the
546 display function, it will result in the data being displayed
547 display function, it will result in the data being displayed
547 in the frontend. If the data is a URL, the data will first be
548 in the frontend. If the data is a URL, the data will first be
548 downloaded and then displayed.
549 downloaded and then displayed.
549
550
550 In the Notebook, the containing element will be available as `element`,
551 In the Notebook, the containing element will be available as `element`,
551 and jQuery will be available. Content appended to `element` will be
552 and jQuery will be available. Content appended to `element` will be
552 visible in the output area.
553 visible in the output area.
553
554
554 Parameters
555 Parameters
555 ----------
556 ----------
556 data : unicode, str or bytes
557 data : unicode, str or bytes
557 The Javascript source code or a URL to download it from.
558 The Javascript source code or a URL to download it from.
558 url : unicode
559 url : unicode
559 A URL to download the data from.
560 A URL to download the data from.
560 filename : unicode
561 filename : unicode
561 Path to a local file to load the data from.
562 Path to a local file to load the data from.
562 lib : list or str
563 lib : list or str
563 A sequence of Javascript library URLs to load asynchronously before
564 A sequence of Javascript library URLs to load asynchronously before
564 running the source code. The full URLs of the libraries should
565 running the source code. The full URLs of the libraries should
565 be given. A single Javascript library URL can also be given as a
566 be given. A single Javascript library URL can also be given as a
566 string.
567 string.
567 css: : list or str
568 css: : list or str
568 A sequence of css files to load before running the source code.
569 A sequence of css files to load before running the source code.
569 The full URLs of the css files should be given. A single css URL
570 The full URLs of the css files should be given. A single css URL
570 can also be given as a string.
571 can also be given as a string.
571 """
572 """
572 if isinstance(lib, string_types):
573 if isinstance(lib, string_types):
573 lib = [lib]
574 lib = [lib]
574 elif lib is None:
575 elif lib is None:
575 lib = []
576 lib = []
576 if isinstance(css, string_types):
577 if isinstance(css, string_types):
577 css = [css]
578 css = [css]
578 elif css is None:
579 elif css is None:
579 css = []
580 css = []
580 if not isinstance(lib, (list,tuple)):
581 if not isinstance(lib, (list,tuple)):
581 raise TypeError('expected sequence, got: %r' % lib)
582 raise TypeError('expected sequence, got: %r' % lib)
582 if not isinstance(css, (list,tuple)):
583 if not isinstance(css, (list,tuple)):
583 raise TypeError('expected sequence, got: %r' % css)
584 raise TypeError('expected sequence, got: %r' % css)
584 self.lib = lib
585 self.lib = lib
585 self.css = css
586 self.css = css
586 super(Javascript, self).__init__(data=data, url=url, filename=filename)
587 super(Javascript, self).__init__(data=data, url=url, filename=filename)
587
588
588 def _repr_javascript_(self):
589 def _repr_javascript_(self):
589 r = ''
590 r = ''
590 for c in self.css:
591 for c in self.css:
591 r += css_t % c
592 r += css_t % c
592 for l in self.lib:
593 for l in self.lib:
593 r += lib_t1 % l
594 r += lib_t1 % l
594 r += self.data
595 r += self.data
595 r += lib_t2*len(self.lib)
596 r += lib_t2*len(self.lib)
596 return r
597 return r
597
598
598 # constants for identifying png/jpeg data
599 # constants for identifying png/jpeg data
599 _PNG = b'\x89PNG\r\n\x1a\n'
600 _PNG = b'\x89PNG\r\n\x1a\n'
600 _JPEG = b'\xff\xd8'
601 _JPEG = b'\xff\xd8'
601
602
602 def _pngxy(data):
603 def _pngxy(data):
603 """read the (width, height) from a PNG header"""
604 """read the (width, height) from a PNG header"""
604 ihdr = data.index(b'IHDR')
605 ihdr = data.index(b'IHDR')
605 # next 8 bytes are width/height
606 # next 8 bytes are width/height
606 w4h4 = data[ihdr+4:ihdr+12]
607 w4h4 = data[ihdr+4:ihdr+12]
607 return struct.unpack('>ii', w4h4)
608 return struct.unpack('>ii', w4h4)
608
609
609 def _jpegxy(data):
610 def _jpegxy(data):
610 """read the (width, height) from a JPEG header"""
611 """read the (width, height) from a JPEG header"""
611 # adapted from http://www.64lines.com/jpeg-width-height
612 # adapted from http://www.64lines.com/jpeg-width-height
612
613
613 idx = 4
614 idx = 4
614 while True:
615 while True:
615 block_size = struct.unpack('>H', data[idx:idx+2])[0]
616 block_size = struct.unpack('>H', data[idx:idx+2])[0]
616 idx = idx + block_size
617 idx = idx + block_size
617 if data[idx:idx+2] == b'\xFF\xC0':
618 if data[idx:idx+2] == b'\xFF\xC0':
618 # found Start of Frame
619 # found Start of Frame
619 iSOF = idx
620 iSOF = idx
620 break
621 break
621 else:
622 else:
622 # read another block
623 # read another block
623 idx += 2
624 idx += 2
624
625
625 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
626 h, w = struct.unpack('>HH', data[iSOF+5:iSOF+9])
626 return w, h
627 return w, h
627
628
628 class Image(DisplayObject):
629 class Image(DisplayObject):
629
630
630 _read_flags = 'rb'
631 _read_flags = 'rb'
631 _FMT_JPEG = u'jpeg'
632 _FMT_JPEG = u'jpeg'
632 _FMT_PNG = u'png'
633 _FMT_PNG = u'png'
633 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
634 _ACCEPTABLE_EMBEDDINGS = [_FMT_JPEG, _FMT_PNG]
634
635
635 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
636 def __init__(self, data=None, url=None, filename=None, format=u'png', embed=None, width=None, height=None, retina=False):
636 """Create a PNG/JPEG image object given raw data.
637 """Create a PNG/JPEG image object given raw data.
637
638
638 When this object is returned by an input cell or passed to the
639 When this object is returned by an input cell or passed to the
639 display function, it will result in the image being displayed
640 display function, it will result in the image being displayed
640 in the frontend.
641 in the frontend.
641
642
642 Parameters
643 Parameters
643 ----------
644 ----------
644 data : unicode, str or bytes
645 data : unicode, str or bytes
645 The raw image data or a URL or filename to load the data from.
646 The raw image data or a URL or filename to load the data from.
646 This always results in embedded image data.
647 This always results in embedded image data.
647 url : unicode
648 url : unicode
648 A URL to download the data from. If you specify `url=`,
649 A URL to download the data from. If you specify `url=`,
649 the image data will not be embedded unless you also specify `embed=True`.
650 the image data will not be embedded unless you also specify `embed=True`.
650 filename : unicode
651 filename : unicode
651 Path to a local file to load the data from.
652 Path to a local file to load the data from.
652 Images from a file are always embedded.
653 Images from a file are always embedded.
653 format : unicode
654 format : unicode
654 The format of the image data (png/jpeg/jpg). If a filename or URL is given
655 The format of the image data (png/jpeg/jpg). If a filename or URL is given
655 for format will be inferred from the filename extension.
656 for format will be inferred from the filename extension.
656 embed : bool
657 embed : bool
657 Should the image data be embedded using a data URI (True) or be
658 Should the image data be embedded using a data URI (True) or be
658 loaded using an <img> tag. Set this to True if you want the image
659 loaded using an <img> tag. Set this to True if you want the image
659 to be viewable later with no internet connection in the notebook.
660 to be viewable later with no internet connection in the notebook.
660
661
661 Default is `True`, unless the keyword argument `url` is set, then
662 Default is `True`, unless the keyword argument `url` is set, then
662 default value is `False`.
663 default value is `False`.
663
664
664 Note that QtConsole is not able to display images if `embed` is set to `False`
665 Note that QtConsole is not able to display images if `embed` is set to `False`
665 width : int
666 width : int
666 Width to which to constrain the image in html
667 Width to which to constrain the image in html
667 height : int
668 height : int
668 Height to which to constrain the image in html
669 Height to which to constrain the image in html
669 retina : bool
670 retina : bool
670 Automatically set the width and height to half of the measured
671 Automatically set the width and height to half of the measured
671 width and height.
672 width and height.
672 This only works for embedded images because it reads the width/height
673 This only works for embedded images because it reads the width/height
673 from image data.
674 from image data.
674 For non-embedded images, you can just set the desired display width
675 For non-embedded images, you can just set the desired display width
675 and height directly.
676 and height directly.
676
677
677 Examples
678 Examples
678 --------
679 --------
679 # embedded image data, works in qtconsole and notebook
680 # embedded image data, works in qtconsole and notebook
680 # when passed positionally, the first arg can be any of raw image data,
681 # when passed positionally, the first arg can be any of raw image data,
681 # a URL, or a filename from which to load image data.
682 # a URL, or a filename from which to load image data.
682 # The result is always embedding image data for inline images.
683 # The result is always embedding image data for inline images.
683 Image('http://www.google.fr/images/srpr/logo3w.png')
684 Image('http://www.google.fr/images/srpr/logo3w.png')
684 Image('/path/to/image.jpg')
685 Image('/path/to/image.jpg')
685 Image(b'RAW_PNG_DATA...')
686 Image(b'RAW_PNG_DATA...')
686
687
687 # Specifying Image(url=...) does not embed the image data,
688 # Specifying Image(url=...) does not embed the image data,
688 # it only generates `<img>` tag with a link to the source.
689 # it only generates `<img>` tag with a link to the source.
689 # This will not work in the qtconsole or offline.
690 # This will not work in the qtconsole or offline.
690 Image(url='http://www.google.fr/images/srpr/logo3w.png')
691 Image(url='http://www.google.fr/images/srpr/logo3w.png')
691
692
692 """
693 """
693 if filename is not None:
694 if filename is not None:
694 ext = self._find_ext(filename)
695 ext = self._find_ext(filename)
695 elif url is not None:
696 elif url is not None:
696 ext = self._find_ext(url)
697 ext = self._find_ext(url)
697 elif data is None:
698 elif data is None:
698 raise ValueError("No image data found. Expecting filename, url, or data.")
699 raise ValueError("No image data found. Expecting filename, url, or data.")
699 elif isinstance(data, string_types) and (
700 elif isinstance(data, string_types) and (
700 data.startswith('http') or _safe_exists(data)
701 data.startswith('http') or _safe_exists(data)
701 ):
702 ):
702 ext = self._find_ext(data)
703 ext = self._find_ext(data)
703 else:
704 else:
704 ext = None
705 ext = None
705
706
706 if ext is not None:
707 if ext is not None:
707 format = ext.lower()
708 format = ext.lower()
708 if ext == u'jpg' or ext == u'jpeg':
709 if ext == u'jpg' or ext == u'jpeg':
709 format = self._FMT_JPEG
710 format = self._FMT_JPEG
710 if ext == u'png':
711 if ext == u'png':
711 format = self._FMT_PNG
712 format = self._FMT_PNG
712 elif isinstance(data, bytes) and format == 'png':
713 elif isinstance(data, bytes) and format == 'png':
713 # infer image type from image data header,
714 # infer image type from image data header,
714 # only if format might not have been specified.
715 # only if format might not have been specified.
715 if data[:2] == _JPEG:
716 if data[:2] == _JPEG:
716 format = 'jpeg'
717 format = 'jpeg'
717
718
718 self.format = unicode_type(format).lower()
719 self.format = unicode_type(format).lower()
719 self.embed = embed if embed is not None else (url is None)
720 self.embed = embed if embed is not None else (url is None)
720
721
721 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
722 if self.embed and self.format not in self._ACCEPTABLE_EMBEDDINGS:
722 raise ValueError("Cannot embed the '%s' image format" % (self.format))
723 raise ValueError("Cannot embed the '%s' image format" % (self.format))
723 self.width = width
724 self.width = width
724 self.height = height
725 self.height = height
725 self.retina = retina
726 self.retina = retina
726 super(Image, self).__init__(data=data, url=url, filename=filename)
727 super(Image, self).__init__(data=data, url=url, filename=filename)
727
728
728 if retina:
729 if retina:
729 self._retina_shape()
730 self._retina_shape()
730
731
731 def _retina_shape(self):
732 def _retina_shape(self):
732 """load pixel-doubled width and height from image data"""
733 """load pixel-doubled width and height from image data"""
733 if not self.embed:
734 if not self.embed:
734 return
735 return
735 if self.format == 'png':
736 if self.format == 'png':
736 w, h = _pngxy(self.data)
737 w, h = _pngxy(self.data)
737 elif self.format == 'jpeg':
738 elif self.format == 'jpeg':
738 w, h = _jpegxy(self.data)
739 w, h = _jpegxy(self.data)
739 else:
740 else:
740 # retina only supports png
741 # retina only supports png
741 return
742 return
742 self.width = w // 2
743 self.width = w // 2
743 self.height = h // 2
744 self.height = h // 2
744
745
745 def reload(self):
746 def reload(self):
746 """Reload the raw data from file or URL."""
747 """Reload the raw data from file or URL."""
747 if self.embed:
748 if self.embed:
748 super(Image,self).reload()
749 super(Image,self).reload()
749 if self.retina:
750 if self.retina:
750 self._retina_shape()
751 self._retina_shape()
751
752
752 def _repr_html_(self):
753 def _repr_html_(self):
753 if not self.embed:
754 if not self.embed:
754 width = height = ''
755 width = height = ''
755 if self.width:
756 if self.width:
756 width = ' width="%d"' % self.width
757 width = ' width="%d"' % self.width
757 if self.height:
758 if self.height:
758 height = ' height="%d"' % self.height
759 height = ' height="%d"' % self.height
759 return u'<img src="%s"%s%s/>' % (self.url, width, height)
760 return u'<img src="%s"%s%s/>' % (self.url, width, height)
760
761
761 def _data_and_metadata(self):
762 def _data_and_metadata(self):
762 """shortcut for returning metadata with shape information, if defined"""
763 """shortcut for returning metadata with shape information, if defined"""
763 md = {}
764 md = {}
764 if self.width:
765 if self.width:
765 md['width'] = self.width
766 md['width'] = self.width
766 if self.height:
767 if self.height:
767 md['height'] = self.height
768 md['height'] = self.height
768 if md:
769 if md:
769 return self.data, md
770 return self.data, md
770 else:
771 else:
771 return self.data
772 return self.data
772
773
773 def _repr_png_(self):
774 def _repr_png_(self):
774 if self.embed and self.format == u'png':
775 if self.embed and self.format == u'png':
775 return self._data_and_metadata()
776 return self._data_and_metadata()
776
777
777 def _repr_jpeg_(self):
778 def _repr_jpeg_(self):
778 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
779 if self.embed and (self.format == u'jpeg' or self.format == u'jpg'):
779 return self._data_and_metadata()
780 return self._data_and_metadata()
780
781
781 def _find_ext(self, s):
782 def _find_ext(self, s):
782 return unicode_type(s.split('.')[-1].lower())
783 return unicode_type(s.split('.')[-1].lower())
783
784
785 class Video(DisplayObject):
786
787 def __init__(self, data=None, url=None, filename=None, embed=None, mimetype=None):
788 """Create a video object given raw data or an URL.
789
790 When this object is returned by an input cell or passed to the
791 display function, it will result in the video being displayed
792 in the frontend.
793
794 Parameters
795 ----------
796 data : unicode, str or bytes
797 The raw image data or a URL or filename to load the data from.
798 This always results in embedded image data.
799 url : unicode
800 A URL to download the data from. If you specify `url=`,
801 the image data will not be embedded unless you also specify `embed=True`.
802 filename : unicode
803 Path to a local file to load the data from.
804 Videos from a file are always embedded.
805 embed : bool
806 Should the image data be embedded using a data URI (True) or be
807 loaded using an <img> tag. Set this to True if you want the image
808 to be viewable later with no internet connection in the notebook.
809
810 Default is `True`, unless the keyword argument `url` is set, then
811 default value is `False`.
812
813 Note that QtConsole is not able to display images if `embed` is set to `False`
814 mimetype: unicode
815 Specify the mimetype in case you load in a encoded video.
816 Examples
817 --------
818 Video('https://archive.org/download/Sita_Sings_the_Blues/Sita_Sings_the_Blues_small.mp4')
819 Video('path/to/video.mp4')
820 Video('path/to/video.mp4', embed=False)
821 """
822 if url is None and (data.startswith('http') or data.startswith('https')):
823 url = data
824 data = None
825 embed = False
826 elif os.path.exists(data):
827 filename = data
828 data = None
829
830 self.mimetype = mimetype
831 self.embed = embed if embed is not None else (filename is not None)
832 super(Video, self).__init__(data=data, url=url, filename=filename)
833
834 def _repr_html_(self):
835 # External URLs and potentially local files are not embedded into the
836 # notebook output.
837 if not self.embed:
838 url = self.url if self.url is not None else self.filename
839 output = """<video src="{0}" controls>
840 Your browser does not support the <code>video</code> element.
841 </video>""".format(url)
842 return output
843 # Embedded videos uses base64 encoded videos.
844 if self.filename is not None:
845 mimetypes.init()
846 mimetype, encoding = mimetypes.guess_type(self.filename)
847
848 video = open(self.filename, 'rb').read()
849 video_encoded = video.encode('base64')
850 else:
851 video_encoded = self.data
852 mimetype = self.mimetype
853 output = """<video controls>
854 <source src="data:{0};base64,{1}" type="{0}">
855 Your browser does not support the video tag.
856 </video>""".format(mimetype, video_encoded)
857 return output
858
859 def reload(self):
860 # TODO
861 pass
862
863 def _repr_png_(self):
864 # TODO
865 pass
866 def _repr_jpeg_(self):
867 # TODO
868 pass
784
869
785 def clear_output(wait=False):
870 def clear_output(wait=False):
786 """Clear the output of the current cell receiving output.
871 """Clear the output of the current cell receiving output.
787
872
788 Parameters
873 Parameters
789 ----------
874 ----------
790 wait : bool [default: false]
875 wait : bool [default: false]
791 Wait to clear the output until new output is available to replace it."""
876 Wait to clear the output until new output is available to replace it."""
792 from IPython.core.interactiveshell import InteractiveShell
877 from IPython.core.interactiveshell import InteractiveShell
793 if InteractiveShell.initialized():
878 if InteractiveShell.initialized():
794 InteractiveShell.instance().display_pub.clear_output(wait)
879 InteractiveShell.instance().display_pub.clear_output(wait)
795 else:
880 else:
796 from IPython.utils import io
881 from IPython.utils import io
797 print('\033[2K\r', file=io.stdout, end='')
882 print('\033[2K\r', file=io.stdout, end='')
798 io.stdout.flush()
883 io.stdout.flush()
799 print('\033[2K\r', file=io.stderr, end='')
884 print('\033[2K\r', file=io.stderr, end='')
800 io.stderr.flush()
885 io.stderr.flush()
801
886
802
887
803 @skip_doctest
888 @skip_doctest
804 def set_matplotlib_formats(*formats, **kwargs):
889 def set_matplotlib_formats(*formats, **kwargs):
805 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
890 """Select figure formats for the inline backend. Optionally pass quality for JPEG.
806
891
807 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
892 For example, this enables PNG and JPEG output with a JPEG quality of 90%::
808
893
809 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
894 In [1]: set_matplotlib_formats('png', 'jpeg', quality=90)
810
895
811 To set this in your config files use the following::
896 To set this in your config files use the following::
812
897
813 c.InlineBackend.figure_formats = {'png', 'jpeg'}
898 c.InlineBackend.figure_formats = {'png', 'jpeg'}
814 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
899 c.InlineBackend.print_figure_kwargs.update({'quality' : 90})
815
900
816 Parameters
901 Parameters
817 ----------
902 ----------
818 *formats : strs
903 *formats : strs
819 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
904 One or more figure formats to enable: 'png', 'retina', 'jpeg', 'svg', 'pdf'.
820 **kwargs :
905 **kwargs :
821 Keyword args will be relayed to ``figure.canvas.print_figure``.
906 Keyword args will be relayed to ``figure.canvas.print_figure``.
822 """
907 """
823 from IPython.core.interactiveshell import InteractiveShell
908 from IPython.core.interactiveshell import InteractiveShell
824 from IPython.core.pylabtools import select_figure_formats
909 from IPython.core.pylabtools import select_figure_formats
825 from IPython.kernel.zmq.pylab.config import InlineBackend
910 from IPython.kernel.zmq.pylab.config import InlineBackend
826 # build kwargs, starting with InlineBackend config
911 # build kwargs, starting with InlineBackend config
827 kw = {}
912 kw = {}
828 cfg = InlineBackend.instance()
913 cfg = InlineBackend.instance()
829 kw.update(cfg.print_figure_kwargs)
914 kw.update(cfg.print_figure_kwargs)
830 kw.update(**kwargs)
915 kw.update(**kwargs)
831 shell = InteractiveShell.instance()
916 shell = InteractiveShell.instance()
832 select_figure_formats(shell, formats, **kw)
917 select_figure_formats(shell, formats, **kw)
833
918
834 @skip_doctest
919 @skip_doctest
835 def set_matplotlib_close(close=True):
920 def set_matplotlib_close(close=True):
836 """Set whether the inline backend closes all figures automatically or not.
921 """Set whether the inline backend closes all figures automatically or not.
837
922
838 By default, the inline backend used in the IPython Notebook will close all
923 By default, the inline backend used in the IPython Notebook will close all
839 matplotlib figures automatically after each cell is run. This means that
924 matplotlib figures automatically after each cell is run. This means that
840 plots in different cells won't interfere. Sometimes, you may want to make
925 plots in different cells won't interfere. Sometimes, you may want to make
841 a plot in one cell and then refine it in later cells. This can be accomplished
926 a plot in one cell and then refine it in later cells. This can be accomplished
842 by::
927 by::
843
928
844 In [1]: set_matplotlib_close(False)
929 In [1]: set_matplotlib_close(False)
845
930
846 To set this in your config files use the following::
931 To set this in your config files use the following::
847
932
848 c.InlineBackend.close_figures = False
933 c.InlineBackend.close_figures = False
849
934
850 Parameters
935 Parameters
851 ----------
936 ----------
852 close : bool
937 close : bool
853 Should all matplotlib figures be automatically closed after each cell is
938 Should all matplotlib figures be automatically closed after each cell is
854 run?
939 run?
855 """
940 """
856 from IPython.kernel.zmq.pylab.config import InlineBackend
941 from IPython.kernel.zmq.pylab.config import InlineBackend
857 cfg = InlineBackend.instance()
942 cfg = InlineBackend.instance()
858 cfg.close_figures = close
943 cfg.close_figures = close
859
944
@@ -1,285 +1,282 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Displayhook for IPython.
2 """Displayhook for IPython.
3
3
4 This defines a callable class that IPython uses for `sys.displayhook`.
4 This defines a callable class that IPython uses for `sys.displayhook`.
5
6 Authors:
7
8 * Fernando Perez
9 * Brian Granger
10 * Robert Kern
11 """
5 """
12
6
13 #-----------------------------------------------------------------------------
7 # Copyright (c) IPython Development Team.
14 # Copyright (C) 2008-2011 The IPython Development Team
8 # Distributed under the terms of the Modified BSD License.
15 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
9
16 #
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
20
21 #-----------------------------------------------------------------------------
22 # Imports
23 #-----------------------------------------------------------------------------
24 from __future__ import print_function
10 from __future__ import print_function
25
11
26 import sys
12 import sys
27
13
28 from IPython.core.formatters import _safe_get_formatter_method
14 from IPython.core.formatters import _safe_get_formatter_method
29 from IPython.config.configurable import Configurable
15 from IPython.config.configurable import Configurable
30 from IPython.utils import io
16 from IPython.utils import io
31 from IPython.utils.py3compat import builtin_mod
17 from IPython.utils.py3compat import builtin_mod
32 from IPython.utils.traitlets import Instance
18 from IPython.utils.traitlets import Instance, Float
33 from IPython.utils.warn import warn
19 from IPython.utils.warn import warn
34
20
35 #-----------------------------------------------------------------------------
36 # Main displayhook class
37 #-----------------------------------------------------------------------------
38
39 # TODO: Move the various attributes (cache_size, [others now moved]). Some
21 # TODO: Move the various attributes (cache_size, [others now moved]). Some
40 # of these are also attributes of InteractiveShell. They should be on ONE object
22 # of these are also attributes of InteractiveShell. They should be on ONE object
41 # only and the other objects should ask that one object for their values.
23 # only and the other objects should ask that one object for their values.
42
24
43 class DisplayHook(Configurable):
25 class DisplayHook(Configurable):
44 """The custom IPython displayhook to replace sys.displayhook.
26 """The custom IPython displayhook to replace sys.displayhook.
45
27
46 This class does many things, but the basic idea is that it is a callable
28 This class does many things, but the basic idea is that it is a callable
47 that gets called anytime user code returns a value.
29 that gets called anytime user code returns a value.
48 """
30 """
49
31
50 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
32 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
33 cull_fraction = Float(0.2)
51
34
52 def __init__(self, shell=None, cache_size=1000, **kwargs):
35 def __init__(self, shell=None, cache_size=1000, **kwargs):
53 super(DisplayHook, self).__init__(shell=shell, **kwargs)
36 super(DisplayHook, self).__init__(shell=shell, **kwargs)
54
55 cache_size_min = 3
37 cache_size_min = 3
56 if cache_size <= 0:
38 if cache_size <= 0:
57 self.do_full_cache = 0
39 self.do_full_cache = 0
58 cache_size = 0
40 cache_size = 0
59 elif cache_size < cache_size_min:
41 elif cache_size < cache_size_min:
60 self.do_full_cache = 0
42 self.do_full_cache = 0
61 cache_size = 0
43 cache_size = 0
62 warn('caching was disabled (min value for cache size is %s).' %
44 warn('caching was disabled (min value for cache size is %s).' %
63 cache_size_min,level=3)
45 cache_size_min,level=3)
64 else:
46 else:
65 self.do_full_cache = 1
47 self.do_full_cache = 1
66
48
67 self.cache_size = cache_size
49 self.cache_size = cache_size
68
50
69 # we need a reference to the user-level namespace
51 # we need a reference to the user-level namespace
70 self.shell = shell
52 self.shell = shell
71
53
72 self._,self.__,self.___ = '','',''
54 self._,self.__,self.___ = '','',''
73
55
74 # these are deliberately global:
56 # these are deliberately global:
75 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
57 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
76 self.shell.user_ns.update(to_user_ns)
58 self.shell.user_ns.update(to_user_ns)
77
59
78 @property
60 @property
79 def prompt_count(self):
61 def prompt_count(self):
80 return self.shell.execution_count
62 return self.shell.execution_count
81
63
82 #-------------------------------------------------------------------------
64 #-------------------------------------------------------------------------
83 # Methods used in __call__. Override these methods to modify the behavior
65 # Methods used in __call__. Override these methods to modify the behavior
84 # of the displayhook.
66 # of the displayhook.
85 #-------------------------------------------------------------------------
67 #-------------------------------------------------------------------------
86
68
87 def check_for_underscore(self):
69 def check_for_underscore(self):
88 """Check if the user has set the '_' variable by hand."""
70 """Check if the user has set the '_' variable by hand."""
89 # If something injected a '_' variable in __builtin__, delete
71 # If something injected a '_' variable in __builtin__, delete
90 # ipython's automatic one so we don't clobber that. gettext() in
72 # ipython's automatic one so we don't clobber that. gettext() in
91 # particular uses _, so we need to stay away from it.
73 # particular uses _, so we need to stay away from it.
92 if '_' in builtin_mod.__dict__:
74 if '_' in builtin_mod.__dict__:
93 try:
75 try:
94 del self.shell.user_ns['_']
76 del self.shell.user_ns['_']
95 except KeyError:
77 except KeyError:
96 pass
78 pass
97
79
98 def quiet(self):
80 def quiet(self):
99 """Should we silence the display hook because of ';'?"""
81 """Should we silence the display hook because of ';'?"""
100 # do not print output if input ends in ';'
82 # do not print output if input ends in ';'
101 try:
83 try:
102 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
84 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
103 return cell.rstrip().endswith(';')
85 return cell.rstrip().endswith(';')
104 except IndexError:
86 except IndexError:
105 # some uses of ipshellembed may fail here
87 # some uses of ipshellembed may fail here
106 return False
88 return False
107
89
108 def start_displayhook(self):
90 def start_displayhook(self):
109 """Start the displayhook, initializing resources."""
91 """Start the displayhook, initializing resources."""
110 pass
92 pass
111
93
112 def write_output_prompt(self):
94 def write_output_prompt(self):
113 """Write the output prompt.
95 """Write the output prompt.
114
96
115 The default implementation simply writes the prompt to
97 The default implementation simply writes the prompt to
116 ``io.stdout``.
98 ``io.stdout``.
117 """
99 """
118 # Use write, not print which adds an extra space.
100 # Use write, not print which adds an extra space.
119 io.stdout.write(self.shell.separate_out)
101 io.stdout.write(self.shell.separate_out)
120 outprompt = self.shell.prompt_manager.render('out')
102 outprompt = self.shell.prompt_manager.render('out')
121 if self.do_full_cache:
103 if self.do_full_cache:
122 io.stdout.write(outprompt)
104 io.stdout.write(outprompt)
123
105
124 def compute_format_data(self, result):
106 def compute_format_data(self, result):
125 """Compute format data of the object to be displayed.
107 """Compute format data of the object to be displayed.
126
108
127 The format data is a generalization of the :func:`repr` of an object.
109 The format data is a generalization of the :func:`repr` of an object.
128 In the default implementation the format data is a :class:`dict` of
110 In the default implementation the format data is a :class:`dict` of
129 key value pair where the keys are valid MIME types and the values
111 key value pair where the keys are valid MIME types and the values
130 are JSON'able data structure containing the raw data for that MIME
112 are JSON'able data structure containing the raw data for that MIME
131 type. It is up to frontends to determine pick a MIME to to use and
113 type. It is up to frontends to determine pick a MIME to to use and
132 display that data in an appropriate manner.
114 display that data in an appropriate manner.
133
115
134 This method only computes the format data for the object and should
116 This method only computes the format data for the object and should
135 NOT actually print or write that to a stream.
117 NOT actually print or write that to a stream.
136
118
137 Parameters
119 Parameters
138 ----------
120 ----------
139 result : object
121 result : object
140 The Python object passed to the display hook, whose format will be
122 The Python object passed to the display hook, whose format will be
141 computed.
123 computed.
142
124
143 Returns
125 Returns
144 -------
126 -------
145 (format_dict, md_dict) : dict
127 (format_dict, md_dict) : dict
146 format_dict is a :class:`dict` whose keys are valid MIME types and values are
128 format_dict is a :class:`dict` whose keys are valid MIME types and values are
147 JSON'able raw data for that MIME type. It is recommended that
129 JSON'able raw data for that MIME type. It is recommended that
148 all return values of this should always include the "text/plain"
130 all return values of this should always include the "text/plain"
149 MIME type representation of the object.
131 MIME type representation of the object.
150 md_dict is a :class:`dict` with the same MIME type keys
132 md_dict is a :class:`dict` with the same MIME type keys
151 of metadata associated with each output.
133 of metadata associated with each output.
152
134
153 """
135 """
154 return self.shell.display_formatter.format(result)
136 return self.shell.display_formatter.format(result)
155
137
156 def write_format_data(self, format_dict, md_dict=None):
138 def write_format_data(self, format_dict, md_dict=None):
157 """Write the format data dict to the frontend.
139 """Write the format data dict to the frontend.
158
140
159 This default version of this method simply writes the plain text
141 This default version of this method simply writes the plain text
160 representation of the object to ``io.stdout``. Subclasses should
142 representation of the object to ``io.stdout``. Subclasses should
161 override this method to send the entire `format_dict` to the
143 override this method to send the entire `format_dict` to the
162 frontends.
144 frontends.
163
145
164 Parameters
146 Parameters
165 ----------
147 ----------
166 format_dict : dict
148 format_dict : dict
167 The format dict for the object passed to `sys.displayhook`.
149 The format dict for the object passed to `sys.displayhook`.
168 md_dict : dict (optional)
150 md_dict : dict (optional)
169 The metadata dict to be associated with the display data.
151 The metadata dict to be associated with the display data.
170 """
152 """
153 if 'text/plain' not in format_dict:
154 # nothing to do
155 return
171 # We want to print because we want to always make sure we have a
156 # We want to print because we want to always make sure we have a
172 # newline, even if all the prompt separators are ''. This is the
157 # newline, even if all the prompt separators are ''. This is the
173 # standard IPython behavior.
158 # standard IPython behavior.
174 result_repr = format_dict['text/plain']
159 result_repr = format_dict['text/plain']
175 if '\n' in result_repr:
160 if '\n' in result_repr:
176 # So that multi-line strings line up with the left column of
161 # So that multi-line strings line up with the left column of
177 # the screen, instead of having the output prompt mess up
162 # the screen, instead of having the output prompt mess up
178 # their first line.
163 # their first line.
179 # We use the prompt template instead of the expanded prompt
164 # We use the prompt template instead of the expanded prompt
180 # because the expansion may add ANSI escapes that will interfere
165 # because the expansion may add ANSI escapes that will interfere
181 # with our ability to determine whether or not we should add
166 # with our ability to determine whether or not we should add
182 # a newline.
167 # a newline.
183 prompt_template = self.shell.prompt_manager.out_template
168 prompt_template = self.shell.prompt_manager.out_template
184 if prompt_template and not prompt_template.endswith('\n'):
169 if prompt_template and not prompt_template.endswith('\n'):
185 # But avoid extraneous empty lines.
170 # But avoid extraneous empty lines.
186 result_repr = '\n' + result_repr
171 result_repr = '\n' + result_repr
187
172
188 print(result_repr, file=io.stdout)
173 print(result_repr, file=io.stdout)
189
174
190 def update_user_ns(self, result):
175 def update_user_ns(self, result):
191 """Update user_ns with various things like _, __, _1, etc."""
176 """Update user_ns with various things like _, __, _1, etc."""
192
177
193 # Avoid recursive reference when displaying _oh/Out
178 # Avoid recursive reference when displaying _oh/Out
194 if result is not self.shell.user_ns['_oh']:
179 if result is not self.shell.user_ns['_oh']:
195 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
180 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
196 warn('Output cache limit (currently '+
181 self.cull_cache()
197 repr(self.cache_size)+' entries) hit.\n'
198 'Flushing cache and resetting history counter...\n'
199 'The only history variables available will be _,__,___ and _1\n'
200 'with the current result.')
201
202 self.flush()
203 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
182 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
204 # we cause buggy behavior for things like gettext).
183 # we cause buggy behavior for things like gettext).
205
184
206 if '_' not in builtin_mod.__dict__:
185 if '_' not in builtin_mod.__dict__:
207 self.___ = self.__
186 self.___ = self.__
208 self.__ = self._
187 self.__ = self._
209 self._ = result
188 self._ = result
210 self.shell.push({'_':self._,
189 self.shell.push({'_':self._,
211 '__':self.__,
190 '__':self.__,
212 '___':self.___}, interactive=False)
191 '___':self.___}, interactive=False)
213
192
214 # hackish access to top-level namespace to create _1,_2... dynamically
193 # hackish access to top-level namespace to create _1,_2... dynamically
215 to_main = {}
194 to_main = {}
216 if self.do_full_cache:
195 if self.do_full_cache:
217 new_result = '_'+repr(self.prompt_count)
196 new_result = '_'+repr(self.prompt_count)
218 to_main[new_result] = result
197 to_main[new_result] = result
219 self.shell.push(to_main, interactive=False)
198 self.shell.push(to_main, interactive=False)
220 self.shell.user_ns['_oh'][self.prompt_count] = result
199 self.shell.user_ns['_oh'][self.prompt_count] = result
221
200
222 def log_output(self, format_dict):
201 def log_output(self, format_dict):
223 """Log the output."""
202 """Log the output."""
203 if 'text/plain' not in format_dict:
204 # nothing to do
205 return
224 if self.shell.logger.log_output:
206 if self.shell.logger.log_output:
225 self.shell.logger.log_write(format_dict['text/plain'], 'output')
207 self.shell.logger.log_write(format_dict['text/plain'], 'output')
226 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
208 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
227 format_dict['text/plain']
209 format_dict['text/plain']
228
210
229 def finish_displayhook(self):
211 def finish_displayhook(self):
230 """Finish up all displayhook activities."""
212 """Finish up all displayhook activities."""
231 io.stdout.write(self.shell.separate_out2)
213 io.stdout.write(self.shell.separate_out2)
232 io.stdout.flush()
214 io.stdout.flush()
233
215
234 def __call__(self, result=None):
216 def __call__(self, result=None):
235 """Printing with history cache management.
217 """Printing with history cache management.
236
218
237 This is invoked everytime the interpreter needs to print, and is
219 This is invoked everytime the interpreter needs to print, and is
238 activated by setting the variable sys.displayhook to it.
220 activated by setting the variable sys.displayhook to it.
239 """
221 """
240 self.check_for_underscore()
222 self.check_for_underscore()
241 if result is not None and not self.quiet():
223 if result is not None and not self.quiet():
242 # If _ipython_display_ is defined, use that to display this object.
224 # If _ipython_display_ is defined, use that to display this object.
243 display_method = _safe_get_formatter_method(result, '_ipython_display_')
225 display_method = _safe_get_formatter_method(result, '_ipython_display_')
244 if display_method is not None:
226 if display_method is not None:
245 try:
227 try:
246 return display_method()
228 return display_method()
247 except NotImplementedError:
229 except NotImplementedError:
248 pass
230 pass
249
231
250 self.start_displayhook()
232 self.start_displayhook()
251 self.write_output_prompt()
233 self.write_output_prompt()
252 format_dict, md_dict = self.compute_format_data(result)
234 format_dict, md_dict = self.compute_format_data(result)
253 self.write_format_data(format_dict, md_dict)
235 self.write_format_data(format_dict, md_dict)
254 self.update_user_ns(result)
236 self.update_user_ns(result)
255 self.log_output(format_dict)
237 self.log_output(format_dict)
256 self.finish_displayhook()
238 self.finish_displayhook()
257
239
240 def cull_cache(self):
241 """Output cache is full, cull the oldest entries"""
242 oh = self.shell.user_ns.get('_oh', {})
243 sz = len(oh)
244 cull_count = max(int(sz * self.cull_fraction), 2)
245 warn('Output cache limit (currently {sz} entries) hit.\n'
246 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
247
248 for i, n in enumerate(sorted(oh)):
249 if i >= cull_count:
250 break
251 self.shell.user_ns.pop('_%i' % n, None)
252 oh.pop(n, None)
253
254
258 def flush(self):
255 def flush(self):
259 if not self.do_full_cache:
256 if not self.do_full_cache:
260 raise ValueError("You shouldn't have reached the cache flush "
257 raise ValueError("You shouldn't have reached the cache flush "
261 "if full caching is not enabled!")
258 "if full caching is not enabled!")
262 # delete auto-generated vars from global namespace
259 # delete auto-generated vars from global namespace
263
260
264 for n in range(1,self.prompt_count + 1):
261 for n in range(1,self.prompt_count + 1):
265 key = '_'+repr(n)
262 key = '_'+repr(n)
266 try:
263 try:
267 del self.shell.user_ns[key]
264 del self.shell.user_ns[key]
268 except: pass
265 except: pass
269 # In some embedded circumstances, the user_ns doesn't have the
266 # In some embedded circumstances, the user_ns doesn't have the
270 # '_oh' key set up.
267 # '_oh' key set up.
271 oh = self.shell.user_ns.get('_oh', None)
268 oh = self.shell.user_ns.get('_oh', None)
272 if oh is not None:
269 if oh is not None:
273 oh.clear()
270 oh.clear()
274
271
275 # Release our own references to objects:
272 # Release our own references to objects:
276 self._, self.__, self.___ = '', '', ''
273 self._, self.__, self.___ = '', '', ''
277
274
278 if '_' not in builtin_mod.__dict__:
275 if '_' not in builtin_mod.__dict__:
279 self.shell.user_ns.update({'_':None,'__':None, '___':None})
276 self.shell.user_ns.update({'_':None,'__':None, '___':None})
280 import gc
277 import gc
281 # TODO: Is this really needed?
278 # TODO: Is this really needed?
282 # IronPython blocks here forever
279 # IronPython blocks here forever
283 if sys.platform != "cli":
280 if sys.platform != "cli":
284 gc.collect()
281 gc.collect()
285
282
@@ -1,139 +1,131 b''
1 """Infrastructure for registering and firing callbacks on application events.
1 """Infrastructure for registering and firing callbacks on application events.
2
2
3 Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
3 Unlike :mod:`IPython.core.hooks`, which lets end users set single functions to
4 be called at specific times, or a collection of alternative methods to try,
4 be called at specific times, or a collection of alternative methods to try,
5 callbacks are designed to be used by extension authors. A number of callbacks
5 callbacks are designed to be used by extension authors. A number of callbacks
6 can be registered for the same event without needing to be aware of one another.
6 can be registered for the same event without needing to be aware of one another.
7
7
8 The functions defined in this module are no-ops indicating the names of available
8 The functions defined in this module are no-ops indicating the names of available
9 events and the arguments which will be passed to them.
9 events and the arguments which will be passed to them.
10
10
11 .. note::
11 .. note::
12
12
13 This API is experimental in IPython 2.0, and may be revised in future versions.
13 This API is experimental in IPython 2.0, and may be revised in future versions.
14 """
14 """
15 from __future__ import print_function
15 from __future__ import print_function
16
16
17 class EventManager(object):
17 class EventManager(object):
18 """Manage a collection of events and a sequence of callbacks for each.
18 """Manage a collection of events and a sequence of callbacks for each.
19
19
20 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
20 This is attached to :class:`~IPython.core.interactiveshell.InteractiveShell`
21 instances as an ``events`` attribute.
21 instances as an ``events`` attribute.
22
22
23 .. note::
23 .. note::
24
24
25 This API is experimental in IPython 2.0, and may be revised in future versions.
25 This API is experimental in IPython 2.0, and may be revised in future versions.
26 """
26 """
27 def __init__(self, shell, available_events):
27 def __init__(self, shell, available_events):
28 """Initialise the :class:`CallbackManager`.
28 """Initialise the :class:`CallbackManager`.
29
29
30 Parameters
30 Parameters
31 ----------
31 ----------
32 shell
32 shell
33 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
33 The :class:`~IPython.core.interactiveshell.InteractiveShell` instance
34 available_callbacks
34 available_callbacks
35 An iterable of names for callback events.
35 An iterable of names for callback events.
36 """
36 """
37 self.shell = shell
37 self.shell = shell
38 self.callbacks = {n:[] for n in available_events}
38 self.callbacks = {n:[] for n in available_events}
39
39
40 def register(self, event, function):
40 def register(self, event, function):
41 """Register a new event callback
41 """Register a new event callback
42
42
43 Parameters
43 Parameters
44 ----------
44 ----------
45 event : str
45 event : str
46 The event for which to register this callback.
46 The event for which to register this callback.
47 function : callable
47 function : callable
48 A function to be called on the given event. It should take the same
48 A function to be called on the given event. It should take the same
49 parameters as the appropriate callback prototype.
49 parameters as the appropriate callback prototype.
50
50
51 Raises
51 Raises
52 ------
52 ------
53 TypeError
53 TypeError
54 If ``function`` is not callable.
54 If ``function`` is not callable.
55 KeyError
55 KeyError
56 If ``event`` is not one of the known events.
56 If ``event`` is not one of the known events.
57 """
57 """
58 if not callable(function):
58 if not callable(function):
59 raise TypeError('Need a callable, got %r' % function)
59 raise TypeError('Need a callable, got %r' % function)
60 self.callbacks[event].append(function)
60 self.callbacks[event].append(function)
61
61
62 def unregister(self, event, function):
62 def unregister(self, event, function):
63 """Remove a callback from the given event."""
63 """Remove a callback from the given event."""
64 self.callbacks[event].remove(function)
64 self.callbacks[event].remove(function)
65
65
66 def reset(self, event):
67 """Clear all callbacks for the given event."""
68 self.callbacks[event] = []
69
70 def reset_all(self):
71 """Clear all callbacks for all events."""
72 self.callbacks = {n:[] for n in self.callbacks}
73
74 def trigger(self, event, *args, **kwargs):
66 def trigger(self, event, *args, **kwargs):
75 """Call callbacks for ``event``.
67 """Call callbacks for ``event``.
76
68
77 Any additional arguments are passed to all callbacks registered for this
69 Any additional arguments are passed to all callbacks registered for this
78 event. Exceptions raised by callbacks are caught, and a message printed.
70 event. Exceptions raised by callbacks are caught, and a message printed.
79 """
71 """
80 for func in self.callbacks[event]:
72 for func in self.callbacks[event]:
81 try:
73 try:
82 func(*args, **kwargs)
74 func(*args, **kwargs)
83 except Exception:
75 except Exception:
84 print("Error in callback {} (for {}):".format(func, event))
76 print("Error in callback {} (for {}):".format(func, event))
85 self.shell.showtraceback()
77 self.shell.showtraceback()
86
78
87 # event_name -> prototype mapping
79 # event_name -> prototype mapping
88 available_events = {}
80 available_events = {}
89
81
90 def _define_event(callback_proto):
82 def _define_event(callback_proto):
91 available_events[callback_proto.__name__] = callback_proto
83 available_events[callback_proto.__name__] = callback_proto
92 return callback_proto
84 return callback_proto
93
85
94 # ------------------------------------------------------------------------------
86 # ------------------------------------------------------------------------------
95 # Callback prototypes
87 # Callback prototypes
96 #
88 #
97 # No-op functions which describe the names of available events and the
89 # No-op functions which describe the names of available events and the
98 # signatures of callbacks for those events.
90 # signatures of callbacks for those events.
99 # ------------------------------------------------------------------------------
91 # ------------------------------------------------------------------------------
100
92
101 @_define_event
93 @_define_event
102 def pre_execute():
94 def pre_execute():
103 """Fires before code is executed in response to user/frontend action.
95 """Fires before code is executed in response to user/frontend action.
104
96
105 This includes comm and widget messages and silent execution, as well as user
97 This includes comm and widget messages and silent execution, as well as user
106 code cells."""
98 code cells."""
107 pass
99 pass
108
100
109 @_define_event
101 @_define_event
110 def pre_run_cell():
102 def pre_run_cell():
111 """Fires before user-entered code runs."""
103 """Fires before user-entered code runs."""
112 pass
104 pass
113
105
114 @_define_event
106 @_define_event
115 def post_execute():
107 def post_execute():
116 """Fires after code is executed in response to user/frontend action.
108 """Fires after code is executed in response to user/frontend action.
117
109
118 This includes comm and widget messages and silent execution, as well as user
110 This includes comm and widget messages and silent execution, as well as user
119 code cells."""
111 code cells."""
120 pass
112 pass
121
113
122 @_define_event
114 @_define_event
123 def post_run_cell():
115 def post_run_cell():
124 """Fires after user-entered code runs."""
116 """Fires after user-entered code runs."""
125 pass
117 pass
126
118
127 @_define_event
119 @_define_event
128 def shell_initialized(ip):
120 def shell_initialized(ip):
129 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
121 """Fires after initialisation of :class:`~IPython.core.interactiveshell.InteractiveShell`.
130
122
131 This is before extensions and startup scripts are loaded, so it can only be
123 This is before extensions and startup scripts are loaded, so it can only be
132 set by subclassing.
124 set by subclassing.
133
125
134 Parameters
126 Parameters
135 ----------
127 ----------
136 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
128 ip : :class:`~IPython.core.interactiveshell.InteractiveShell`
137 The newly initialised shell.
129 The newly initialised shell.
138 """
130 """
139 pass
131 pass
@@ -1,900 +1,912 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Display formatters.
2 """Display formatters.
3
3
4 Inheritance diagram:
4 Inheritance diagram:
5
5
6 .. inheritance-diagram:: IPython.core.formatters
6 .. inheritance-diagram:: IPython.core.formatters
7 :parts: 3
7 :parts: 3
8
9 Authors:
10
11 * Robert Kern
12 * Brian Granger
13 """
8 """
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2010-2011, IPython Development Team.
16 #
17 # Distributed under the terms of the Modified BSD License.
18 #
19 # The full license is in the file COPYING.txt, distributed with this software.
20 #-----------------------------------------------------------------------------
21
9
22 #-----------------------------------------------------------------------------
10 # Copyright (c) IPython Development Team.
23 # Imports
11 # Distributed under the terms of the Modified BSD License.
24 #-----------------------------------------------------------------------------
25
12
26 # Stdlib imports
27 import abc
13 import abc
28 import inspect
14 import inspect
29 import sys
15 import sys
16 import traceback
30 import types
17 import types
31 import warnings
18 import warnings
32
19
33 from IPython.external.decorator import decorator
20 from IPython.external.decorator import decorator
34
21
35 # Our own imports
36 from IPython.config.configurable import Configurable
22 from IPython.config.configurable import Configurable
23 from IPython.core.getipython import get_ipython
37 from IPython.lib import pretty
24 from IPython.lib import pretty
38 from IPython.utils.traitlets import (
25 from IPython.utils.traitlets import (
39 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
26 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
40 )
27 )
41 from IPython.utils.py3compat import (
28 from IPython.utils.py3compat import (
42 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
29 unicode_to_str, with_metaclass, PY3, string_types, unicode_type,
43 )
30 )
44
31
45 if PY3:
32 if PY3:
46 from io import StringIO
33 from io import StringIO
47 else:
34 else:
48 from StringIO import StringIO
35 from StringIO import StringIO
49
36
50
37
51 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
52 # The main DisplayFormatter class
39 # The main DisplayFormatter class
53 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
54
41
55
42
56 def _valid_formatter(f):
43 def _valid_formatter(f):
57 """Return whether an object is a valid formatter
44 """Return whether an object is a valid formatter
58
45
59 Cases checked:
46 Cases checked:
60
47
61 - bound methods OK
48 - bound methods OK
62 - unbound methods NO
49 - unbound methods NO
63 - callable with zero args OK
50 - callable with zero args OK
64 """
51 """
65 if f is None:
52 if f is None:
66 return False
53 return False
67 elif isinstance(f, type(str.find)):
54 elif isinstance(f, type(str.find)):
68 # unbound methods on compiled classes have type method_descriptor
55 # unbound methods on compiled classes have type method_descriptor
69 return False
56 return False
70 elif isinstance(f, types.BuiltinFunctionType):
57 elif isinstance(f, types.BuiltinFunctionType):
71 # bound methods on compiled classes have type builtin_function
58 # bound methods on compiled classes have type builtin_function
72 return True
59 return True
73 elif callable(f):
60 elif callable(f):
74 # anything that works with zero args should be okay
61 # anything that works with zero args should be okay
75 try:
62 try:
76 inspect.getcallargs(f)
63 inspect.getcallargs(f)
77 except Exception:
64 except Exception:
78 return False
65 return False
79 else:
66 else:
80 return True
67 return True
81 return False
68 return False
82
69
83 def _safe_get_formatter_method(obj, name):
70 def _safe_get_formatter_method(obj, name):
84 """Safely get a formatter method"""
71 """Safely get a formatter method"""
85 method = pretty._safe_getattr(obj, name, None)
72 method = pretty._safe_getattr(obj, name, None)
86 # formatter methods must be bound
73 # formatter methods must be bound
87 if _valid_formatter(method):
74 if _valid_formatter(method):
88 return method
75 return method
89
76
90
77
91 class DisplayFormatter(Configurable):
78 class DisplayFormatter(Configurable):
92
79
93 # When set to true only the default plain text formatter will be used.
80 # When set to true only the default plain text formatter will be used.
94 plain_text_only = Bool(False, config=True)
81 plain_text_only = Bool(False, config=True)
95 def _plain_text_only_changed(self, name, old, new):
82 def _plain_text_only_changed(self, name, old, new):
96 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
83 warnings.warn("""DisplayFormatter.plain_text_only is deprecated.
97
84
98 Use DisplayFormatter.active_types = ['text/plain']
85 Use DisplayFormatter.active_types = ['text/plain']
99 for the same effect.
86 for the same effect.
100 """, DeprecationWarning)
87 """, DeprecationWarning)
101 if new:
88 if new:
102 self.active_types = ['text/plain']
89 self.active_types = ['text/plain']
103 else:
90 else:
104 self.active_types = self.format_types
91 self.active_types = self.format_types
105
92
106 active_types = List(Unicode, config=True,
93 active_types = List(Unicode, config=True,
107 help="""List of currently active mime-types to display.
94 help="""List of currently active mime-types to display.
108 You can use this to set a white-list for formats to display.
95 You can use this to set a white-list for formats to display.
109
96
110 Most users will not need to change this value.
97 Most users will not need to change this value.
111 """)
98 """)
112 def _active_types_default(self):
99 def _active_types_default(self):
113 return self.format_types
100 return self.format_types
114
101
115 def _active_types_changed(self, name, old, new):
102 def _active_types_changed(self, name, old, new):
116 for key, formatter in self.formatters.items():
103 for key, formatter in self.formatters.items():
117 if key in new:
104 if key in new:
118 formatter.enabled = True
105 formatter.enabled = True
119 else:
106 else:
120 formatter.enabled = False
107 formatter.enabled = False
121
108
122 # A dict of formatter whose keys are format types (MIME types) and whose
109 # A dict of formatter whose keys are format types (MIME types) and whose
123 # values are subclasses of BaseFormatter.
110 # values are subclasses of BaseFormatter.
124 formatters = Dict()
111 formatters = Dict()
125 def _formatters_default(self):
112 def _formatters_default(self):
126 """Activate the default formatters."""
113 """Activate the default formatters."""
127 formatter_classes = [
114 formatter_classes = [
128 PlainTextFormatter,
115 PlainTextFormatter,
129 HTMLFormatter,
116 HTMLFormatter,
130 MarkdownFormatter,
117 MarkdownFormatter,
131 SVGFormatter,
118 SVGFormatter,
132 PNGFormatter,
119 PNGFormatter,
133 PDFFormatter,
120 PDFFormatter,
134 JPEGFormatter,
121 JPEGFormatter,
135 LatexFormatter,
122 LatexFormatter,
136 JSONFormatter,
123 JSONFormatter,
137 JavascriptFormatter
124 JavascriptFormatter
138 ]
125 ]
139 d = {}
126 d = {}
140 for cls in formatter_classes:
127 for cls in formatter_classes:
141 f = cls(parent=self)
128 f = cls(parent=self)
142 d[f.format_type] = f
129 d[f.format_type] = f
143 return d
130 return d
144
131
145 def format(self, obj, include=None, exclude=None):
132 def format(self, obj, include=None, exclude=None):
146 """Return a format data dict for an object.
133 """Return a format data dict for an object.
147
134
148 By default all format types will be computed.
135 By default all format types will be computed.
149
136
150 The following MIME types are currently implemented:
137 The following MIME types are currently implemented:
151
138
152 * text/plain
139 * text/plain
153 * text/html
140 * text/html
154 * text/markdown
141 * text/markdown
155 * text/latex
142 * text/latex
156 * application/json
143 * application/json
157 * application/javascript
144 * application/javascript
158 * application/pdf
145 * application/pdf
159 * image/png
146 * image/png
160 * image/jpeg
147 * image/jpeg
161 * image/svg+xml
148 * image/svg+xml
162
149
163 Parameters
150 Parameters
164 ----------
151 ----------
165 obj : object
152 obj : object
166 The Python object whose format data will be computed.
153 The Python object whose format data will be computed.
167 include : list or tuple, optional
154 include : list or tuple, optional
168 A list of format type strings (MIME types) to include in the
155 A list of format type strings (MIME types) to include in the
169 format data dict. If this is set *only* the format types included
156 format data dict. If this is set *only* the format types included
170 in this list will be computed.
157 in this list will be computed.
171 exclude : list or tuple, optional
158 exclude : list or tuple, optional
172 A list of format type string (MIME types) to exclude in the format
159 A list of format type string (MIME types) to exclude in the format
173 data dict. If this is set all format types will be computed,
160 data dict. If this is set all format types will be computed,
174 except for those included in this argument.
161 except for those included in this argument.
175
162
176 Returns
163 Returns
177 -------
164 -------
178 (format_dict, metadata_dict) : tuple of two dicts
165 (format_dict, metadata_dict) : tuple of two dicts
179
166
180 format_dict is a dictionary of key/value pairs, one of each format that was
167 format_dict is a dictionary of key/value pairs, one of each format that was
181 generated for the object. The keys are the format types, which
168 generated for the object. The keys are the format types, which
182 will usually be MIME type strings and the values and JSON'able
169 will usually be MIME type strings and the values and JSON'able
183 data structure containing the raw data for the representation in
170 data structure containing the raw data for the representation in
184 that format.
171 that format.
185
172
186 metadata_dict is a dictionary of metadata about each mime-type output.
173 metadata_dict is a dictionary of metadata about each mime-type output.
187 Its keys will be a strict subset of the keys in format_dict.
174 Its keys will be a strict subset of the keys in format_dict.
188 """
175 """
189 format_dict = {}
176 format_dict = {}
190 md_dict = {}
177 md_dict = {}
191
178
192 for format_type, formatter in self.formatters.items():
179 for format_type, formatter in self.formatters.items():
193 if include and format_type not in include:
180 if include and format_type not in include:
194 continue
181 continue
195 if exclude and format_type in exclude:
182 if exclude and format_type in exclude:
196 continue
183 continue
197
184
198 md = None
185 md = None
199 try:
186 try:
200 data = formatter(obj)
187 data = formatter(obj)
201 except:
188 except:
202 # FIXME: log the exception
189 # FIXME: log the exception
203 raise
190 raise
204
191
205 # formatters can return raw data or (data, metadata)
192 # formatters can return raw data or (data, metadata)
206 if isinstance(data, tuple) and len(data) == 2:
193 if isinstance(data, tuple) and len(data) == 2:
207 data, md = data
194 data, md = data
208
195
209 if data is not None:
196 if data is not None:
210 format_dict[format_type] = data
197 format_dict[format_type] = data
211 if md is not None:
198 if md is not None:
212 md_dict[format_type] = md
199 md_dict[format_type] = md
213
200
214 return format_dict, md_dict
201 return format_dict, md_dict
215
202
216 @property
203 @property
217 def format_types(self):
204 def format_types(self):
218 """Return the format types (MIME types) of the active formatters."""
205 """Return the format types (MIME types) of the active formatters."""
219 return list(self.formatters.keys())
206 return list(self.formatters.keys())
220
207
221
208
222 #-----------------------------------------------------------------------------
209 #-----------------------------------------------------------------------------
223 # Formatters for specific format types (text, html, svg, etc.)
210 # Formatters for specific format types (text, html, svg, etc.)
224 #-----------------------------------------------------------------------------
211 #-----------------------------------------------------------------------------
225
212
213
214 def _safe_repr(obj):
215 """Try to return a repr of an object
216
217 always returns a string, at least.
218 """
219 try:
220 return repr(obj)
221 except Exception as e:
222 return "un-repr-able object (%r)" % e
223
224
226 class FormatterWarning(UserWarning):
225 class FormatterWarning(UserWarning):
227 """Warning class for errors in formatters"""
226 """Warning class for errors in formatters"""
228
227
229 @decorator
228 @decorator
230 def warn_format_error(method, self, *args, **kwargs):
229 def warn_format_error(method, self, *args, **kwargs):
231 """decorator for warning on failed format call"""
230 """decorator for warning on failed format call"""
232 try:
231 try:
233 r = method(self, *args, **kwargs)
232 r = method(self, *args, **kwargs)
234 except NotImplementedError as e:
233 except NotImplementedError:
235 # don't warn on NotImplementedErrors
234 # don't warn on NotImplementedErrors
236 return None
235 return None
237 except Exception as e:
236 except Exception:
238 warnings.warn("Exception in %s formatter: %s" % (self.format_type, e),
237 exc_info = sys.exc_info()
239 FormatterWarning,
238 ip = get_ipython()
240 )
239 if ip is not None:
240 ip.showtraceback(exc_info)
241 else:
242 traceback.print_exception(*exc_info)
241 return None
243 return None
242 if r is None or isinstance(r, self._return_type) or \
244 if r is None or isinstance(r, self._return_type) or \
243 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
245 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
244 return r
246 return r
245 else:
247 else:
246 warnings.warn(
248 warnings.warn(
247 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
249 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
248 (self.format_type, type(r), self._return_type, pretty._safe_repr(args[0])),
250 (self.format_type, type(r), self._return_type, _safe_repr(args[0])),
249 FormatterWarning
251 FormatterWarning
250 )
252 )
251
253
252
254
253 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
255 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
254 """ Abstract base class for Formatters.
256 """ Abstract base class for Formatters.
255
257
256 A formatter is a callable class that is responsible for computing the
258 A formatter is a callable class that is responsible for computing the
257 raw format data for a particular format type (MIME type). For example,
259 raw format data for a particular format type (MIME type). For example,
258 an HTML formatter would have a format type of `text/html` and would return
260 an HTML formatter would have a format type of `text/html` and would return
259 the HTML representation of the object when called.
261 the HTML representation of the object when called.
260 """
262 """
261
263
262 # The format type of the data returned, usually a MIME type.
264 # The format type of the data returned, usually a MIME type.
263 format_type = 'text/plain'
265 format_type = 'text/plain'
264
266
265 # Is the formatter enabled...
267 # Is the formatter enabled...
266 enabled = True
268 enabled = True
267
269
268 @abc.abstractmethod
270 @abc.abstractmethod
269 @warn_format_error
271 @warn_format_error
270 def __call__(self, obj):
272 def __call__(self, obj):
271 """Return a JSON'able representation of the object.
273 """Return a JSON'able representation of the object.
272
274
273 If the object cannot be formatted by this formatter,
275 If the object cannot be formatted by this formatter,
274 warn and return None.
276 warn and return None.
275 """
277 """
276 return repr(obj)
278 return repr(obj)
277
279
278
280
279 def _mod_name_key(typ):
281 def _mod_name_key(typ):
280 """Return a (__module__, __name__) tuple for a type.
282 """Return a (__module__, __name__) tuple for a type.
281
283
282 Used as key in Formatter.deferred_printers.
284 Used as key in Formatter.deferred_printers.
283 """
285 """
284 module = getattr(typ, '__module__', None)
286 module = getattr(typ, '__module__', None)
285 name = getattr(typ, '__name__', None)
287 name = getattr(typ, '__name__', None)
286 return (module, name)
288 return (module, name)
287
289
288
290
289 def _get_type(obj):
291 def _get_type(obj):
290 """Return the type of an instance (old and new-style)"""
292 """Return the type of an instance (old and new-style)"""
291 return getattr(obj, '__class__', None) or type(obj)
293 return getattr(obj, '__class__', None) or type(obj)
292
294
293 _raise_key_error = object()
295 _raise_key_error = object()
294
296
295
297
296 class BaseFormatter(Configurable):
298 class BaseFormatter(Configurable):
297 """A base formatter class that is configurable.
299 """A base formatter class that is configurable.
298
300
299 This formatter should usually be used as the base class of all formatters.
301 This formatter should usually be used as the base class of all formatters.
300 It is a traited :class:`Configurable` class and includes an extensible
302 It is a traited :class:`Configurable` class and includes an extensible
301 API for users to determine how their objects are formatted. The following
303 API for users to determine how their objects are formatted. The following
302 logic is used to find a function to format an given object.
304 logic is used to find a function to format an given object.
303
305
304 1. The object is introspected to see if it has a method with the name
306 1. The object is introspected to see if it has a method with the name
305 :attr:`print_method`. If is does, that object is passed to that method
307 :attr:`print_method`. If is does, that object is passed to that method
306 for formatting.
308 for formatting.
307 2. If no print method is found, three internal dictionaries are consulted
309 2. If no print method is found, three internal dictionaries are consulted
308 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
310 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
309 and :attr:`deferred_printers`.
311 and :attr:`deferred_printers`.
310
312
311 Users should use these dictionaries to register functions that will be
313 Users should use these dictionaries to register functions that will be
312 used to compute the format data for their objects (if those objects don't
314 used to compute the format data for their objects (if those objects don't
313 have the special print methods). The easiest way of using these
315 have the special print methods). The easiest way of using these
314 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
316 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
315 methods.
317 methods.
316
318
317 If no function/callable is found to compute the format data, ``None`` is
319 If no function/callable is found to compute the format data, ``None`` is
318 returned and this format type is not used.
320 returned and this format type is not used.
319 """
321 """
320
322
321 format_type = Unicode('text/plain')
323 format_type = Unicode('text/plain')
322 _return_type = string_types
324 _return_type = string_types
323
325
324 enabled = Bool(True, config=True)
326 enabled = Bool(True, config=True)
325
327
326 print_method = ObjectName('__repr__')
328 print_method = ObjectName('__repr__')
327
329
328 # The singleton printers.
330 # The singleton printers.
329 # Maps the IDs of the builtin singleton objects to the format functions.
331 # Maps the IDs of the builtin singleton objects to the format functions.
330 singleton_printers = Dict(config=True)
332 singleton_printers = Dict(config=True)
331
333
332 # The type-specific printers.
334 # The type-specific printers.
333 # Map type objects to the format functions.
335 # Map type objects to the format functions.
334 type_printers = Dict(config=True)
336 type_printers = Dict(config=True)
335
337
336 # The deferred-import type-specific printers.
338 # The deferred-import type-specific printers.
337 # Map (modulename, classname) pairs to the format functions.
339 # Map (modulename, classname) pairs to the format functions.
338 deferred_printers = Dict(config=True)
340 deferred_printers = Dict(config=True)
339
341
340 @warn_format_error
342 @warn_format_error
341 def __call__(self, obj):
343 def __call__(self, obj):
342 """Compute the format for an object."""
344 """Compute the format for an object."""
343 if self.enabled:
345 if self.enabled:
344 # lookup registered printer
346 # lookup registered printer
345 try:
347 try:
346 printer = self.lookup(obj)
348 printer = self.lookup(obj)
347 except KeyError:
349 except KeyError:
348 pass
350 pass
349 else:
351 else:
350 return printer(obj)
352 return printer(obj)
351 # Finally look for special method names
353 # Finally look for special method names
352 method = _safe_get_formatter_method(obj, self.print_method)
354 method = _safe_get_formatter_method(obj, self.print_method)
353 if method is not None:
355 if method is not None:
354 return method()
356 return method()
355 return None
357 return None
356 else:
358 else:
357 return None
359 return None
358
360
359 def __contains__(self, typ):
361 def __contains__(self, typ):
360 """map in to lookup_by_type"""
362 """map in to lookup_by_type"""
361 try:
363 try:
362 self.lookup_by_type(typ)
364 self.lookup_by_type(typ)
363 except KeyError:
365 except KeyError:
364 return False
366 return False
365 else:
367 else:
366 return True
368 return True
367
369
368 def lookup(self, obj):
370 def lookup(self, obj):
369 """Look up the formatter for a given instance.
371 """Look up the formatter for a given instance.
370
372
371 Parameters
373 Parameters
372 ----------
374 ----------
373 obj : object instance
375 obj : object instance
374
376
375 Returns
377 Returns
376 -------
378 -------
377 f : callable
379 f : callable
378 The registered formatting callable for the type.
380 The registered formatting callable for the type.
379
381
380 Raises
382 Raises
381 ------
383 ------
382 KeyError if the type has not been registered.
384 KeyError if the type has not been registered.
383 """
385 """
384 # look for singleton first
386 # look for singleton first
385 obj_id = id(obj)
387 obj_id = id(obj)
386 if obj_id in self.singleton_printers:
388 if obj_id in self.singleton_printers:
387 return self.singleton_printers[obj_id]
389 return self.singleton_printers[obj_id]
388 # then lookup by type
390 # then lookup by type
389 return self.lookup_by_type(_get_type(obj))
391 return self.lookup_by_type(_get_type(obj))
390
392
391 def lookup_by_type(self, typ):
393 def lookup_by_type(self, typ):
392 """Look up the registered formatter for a type.
394 """Look up the registered formatter for a type.
393
395
394 Parameters
396 Parameters
395 ----------
397 ----------
396 typ : type or '__module__.__name__' string for a type
398 typ : type or '__module__.__name__' string for a type
397
399
398 Returns
400 Returns
399 -------
401 -------
400 f : callable
402 f : callable
401 The registered formatting callable for the type.
403 The registered formatting callable for the type.
402
404
403 Raises
405 Raises
404 ------
406 ------
405 KeyError if the type has not been registered.
407 KeyError if the type has not been registered.
406 """
408 """
407 if isinstance(typ, string_types):
409 if isinstance(typ, string_types):
408 typ_key = tuple(typ.rsplit('.',1))
410 typ_key = tuple(typ.rsplit('.',1))
409 if typ_key not in self.deferred_printers:
411 if typ_key not in self.deferred_printers:
410 # We may have it cached in the type map. We will have to
412 # We may have it cached in the type map. We will have to
411 # iterate over all of the types to check.
413 # iterate over all of the types to check.
412 for cls in self.type_printers:
414 for cls in self.type_printers:
413 if _mod_name_key(cls) == typ_key:
415 if _mod_name_key(cls) == typ_key:
414 return self.type_printers[cls]
416 return self.type_printers[cls]
415 else:
417 else:
416 return self.deferred_printers[typ_key]
418 return self.deferred_printers[typ_key]
417 else:
419 else:
418 for cls in pretty._get_mro(typ):
420 for cls in pretty._get_mro(typ):
419 if cls in self.type_printers or self._in_deferred_types(cls):
421 if cls in self.type_printers or self._in_deferred_types(cls):
420 return self.type_printers[cls]
422 return self.type_printers[cls]
421
423
422 # If we have reached here, the lookup failed.
424 # If we have reached here, the lookup failed.
423 raise KeyError("No registered printer for {0!r}".format(typ))
425 raise KeyError("No registered printer for {0!r}".format(typ))
424
426
425 def for_type(self, typ, func=None):
427 def for_type(self, typ, func=None):
426 """Add a format function for a given type.
428 """Add a format function for a given type.
427
429
428 Parameters
430 Parameters
429 -----------
431 -----------
430 typ : type or '__module__.__name__' string for a type
432 typ : type or '__module__.__name__' string for a type
431 The class of the object that will be formatted using `func`.
433 The class of the object that will be formatted using `func`.
432 func : callable
434 func : callable
433 A callable for computing the format data.
435 A callable for computing the format data.
434 `func` will be called with the object to be formatted,
436 `func` will be called with the object to be formatted,
435 and will return the raw data in this formatter's format.
437 and will return the raw data in this formatter's format.
436 Subclasses may use a different call signature for the
438 Subclasses may use a different call signature for the
437 `func` argument.
439 `func` argument.
438
440
439 If `func` is None or not specified, there will be no change,
441 If `func` is None or not specified, there will be no change,
440 only returning the current value.
442 only returning the current value.
441
443
442 Returns
444 Returns
443 -------
445 -------
444 oldfunc : callable
446 oldfunc : callable
445 The currently registered callable.
447 The currently registered callable.
446 If you are registering a new formatter,
448 If you are registering a new formatter,
447 this will be the previous value (to enable restoring later).
449 this will be the previous value (to enable restoring later).
448 """
450 """
449 # if string given, interpret as 'pkg.module.class_name'
451 # if string given, interpret as 'pkg.module.class_name'
450 if isinstance(typ, string_types):
452 if isinstance(typ, string_types):
451 type_module, type_name = typ.rsplit('.', 1)
453 type_module, type_name = typ.rsplit('.', 1)
452 return self.for_type_by_name(type_module, type_name, func)
454 return self.for_type_by_name(type_module, type_name, func)
453
455
454 try:
456 try:
455 oldfunc = self.lookup_by_type(typ)
457 oldfunc = self.lookup_by_type(typ)
456 except KeyError:
458 except KeyError:
457 oldfunc = None
459 oldfunc = None
458
460
459 if func is not None:
461 if func is not None:
460 self.type_printers[typ] = func
462 self.type_printers[typ] = func
461
463
462 return oldfunc
464 return oldfunc
463
465
464 def for_type_by_name(self, type_module, type_name, func=None):
466 def for_type_by_name(self, type_module, type_name, func=None):
465 """Add a format function for a type specified by the full dotted
467 """Add a format function for a type specified by the full dotted
466 module and name of the type, rather than the type of the object.
468 module and name of the type, rather than the type of the object.
467
469
468 Parameters
470 Parameters
469 ----------
471 ----------
470 type_module : str
472 type_module : str
471 The full dotted name of the module the type is defined in, like
473 The full dotted name of the module the type is defined in, like
472 ``numpy``.
474 ``numpy``.
473 type_name : str
475 type_name : str
474 The name of the type (the class name), like ``dtype``
476 The name of the type (the class name), like ``dtype``
475 func : callable
477 func : callable
476 A callable for computing the format data.
478 A callable for computing the format data.
477 `func` will be called with the object to be formatted,
479 `func` will be called with the object to be formatted,
478 and will return the raw data in this formatter's format.
480 and will return the raw data in this formatter's format.
479 Subclasses may use a different call signature for the
481 Subclasses may use a different call signature for the
480 `func` argument.
482 `func` argument.
481
483
482 If `func` is None or unspecified, there will be no change,
484 If `func` is None or unspecified, there will be no change,
483 only returning the current value.
485 only returning the current value.
484
486
485 Returns
487 Returns
486 -------
488 -------
487 oldfunc : callable
489 oldfunc : callable
488 The currently registered callable.
490 The currently registered callable.
489 If you are registering a new formatter,
491 If you are registering a new formatter,
490 this will be the previous value (to enable restoring later).
492 this will be the previous value (to enable restoring later).
491 """
493 """
492 key = (type_module, type_name)
494 key = (type_module, type_name)
493
495
494 try:
496 try:
495 oldfunc = self.lookup_by_type("%s.%s" % key)
497 oldfunc = self.lookup_by_type("%s.%s" % key)
496 except KeyError:
498 except KeyError:
497 oldfunc = None
499 oldfunc = None
498
500
499 if func is not None:
501 if func is not None:
500 self.deferred_printers[key] = func
502 self.deferred_printers[key] = func
501 return oldfunc
503 return oldfunc
502
504
503 def pop(self, typ, default=_raise_key_error):
505 def pop(self, typ, default=_raise_key_error):
504 """Pop a formatter for the given type.
506 """Pop a formatter for the given type.
505
507
506 Parameters
508 Parameters
507 ----------
509 ----------
508 typ : type or '__module__.__name__' string for a type
510 typ : type or '__module__.__name__' string for a type
509 default : object
511 default : object
510 value to be returned if no formatter is registered for typ.
512 value to be returned if no formatter is registered for typ.
511
513
512 Returns
514 Returns
513 -------
515 -------
514 obj : object
516 obj : object
515 The last registered object for the type.
517 The last registered object for the type.
516
518
517 Raises
519 Raises
518 ------
520 ------
519 KeyError if the type is not registered and default is not specified.
521 KeyError if the type is not registered and default is not specified.
520 """
522 """
521
523
522 if isinstance(typ, string_types):
524 if isinstance(typ, string_types):
523 typ_key = tuple(typ.rsplit('.',1))
525 typ_key = tuple(typ.rsplit('.',1))
524 if typ_key not in self.deferred_printers:
526 if typ_key not in self.deferred_printers:
525 # We may have it cached in the type map. We will have to
527 # We may have it cached in the type map. We will have to
526 # iterate over all of the types to check.
528 # iterate over all of the types to check.
527 for cls in self.type_printers:
529 for cls in self.type_printers:
528 if _mod_name_key(cls) == typ_key:
530 if _mod_name_key(cls) == typ_key:
529 old = self.type_printers.pop(cls)
531 old = self.type_printers.pop(cls)
530 break
532 break
531 else:
533 else:
532 old = default
534 old = default
533 else:
535 else:
534 old = self.deferred_printers.pop(typ_key)
536 old = self.deferred_printers.pop(typ_key)
535 else:
537 else:
536 if typ in self.type_printers:
538 if typ in self.type_printers:
537 old = self.type_printers.pop(typ)
539 old = self.type_printers.pop(typ)
538 else:
540 else:
539 old = self.deferred_printers.pop(_mod_name_key(typ), default)
541 old = self.deferred_printers.pop(_mod_name_key(typ), default)
540 if old is _raise_key_error:
542 if old is _raise_key_error:
541 raise KeyError("No registered value for {0!r}".format(typ))
543 raise KeyError("No registered value for {0!r}".format(typ))
542 return old
544 return old
543
545
544 def _in_deferred_types(self, cls):
546 def _in_deferred_types(self, cls):
545 """
547 """
546 Check if the given class is specified in the deferred type registry.
548 Check if the given class is specified in the deferred type registry.
547
549
548 Successful matches will be moved to the regular type registry for future use.
550 Successful matches will be moved to the regular type registry for future use.
549 """
551 """
550 mod = getattr(cls, '__module__', None)
552 mod = getattr(cls, '__module__', None)
551 name = getattr(cls, '__name__', None)
553 name = getattr(cls, '__name__', None)
552 key = (mod, name)
554 key = (mod, name)
553 if key in self.deferred_printers:
555 if key in self.deferred_printers:
554 # Move the printer over to the regular registry.
556 # Move the printer over to the regular registry.
555 printer = self.deferred_printers.pop(key)
557 printer = self.deferred_printers.pop(key)
556 self.type_printers[cls] = printer
558 self.type_printers[cls] = printer
557 return True
559 return True
558 return False
560 return False
559
561
560
562
561 class PlainTextFormatter(BaseFormatter):
563 class PlainTextFormatter(BaseFormatter):
562 """The default pretty-printer.
564 """The default pretty-printer.
563
565
564 This uses :mod:`IPython.lib.pretty` to compute the format data of
566 This uses :mod:`IPython.lib.pretty` to compute the format data of
565 the object. If the object cannot be pretty printed, :func:`repr` is used.
567 the object. If the object cannot be pretty printed, :func:`repr` is used.
566 See the documentation of :mod:`IPython.lib.pretty` for details on
568 See the documentation of :mod:`IPython.lib.pretty` for details on
567 how to write pretty printers. Here is a simple example::
569 how to write pretty printers. Here is a simple example::
568
570
569 def dtype_pprinter(obj, p, cycle):
571 def dtype_pprinter(obj, p, cycle):
570 if cycle:
572 if cycle:
571 return p.text('dtype(...)')
573 return p.text('dtype(...)')
572 if hasattr(obj, 'fields'):
574 if hasattr(obj, 'fields'):
573 if obj.fields is None:
575 if obj.fields is None:
574 p.text(repr(obj))
576 p.text(repr(obj))
575 else:
577 else:
576 p.begin_group(7, 'dtype([')
578 p.begin_group(7, 'dtype([')
577 for i, field in enumerate(obj.descr):
579 for i, field in enumerate(obj.descr):
578 if i > 0:
580 if i > 0:
579 p.text(',')
581 p.text(',')
580 p.breakable()
582 p.breakable()
581 p.pretty(field)
583 p.pretty(field)
582 p.end_group(7, '])')
584 p.end_group(7, '])')
583 """
585 """
584
586
585 # The format type of data returned.
587 # The format type of data returned.
586 format_type = Unicode('text/plain')
588 format_type = Unicode('text/plain')
587
589
588 # This subclass ignores this attribute as it always need to return
590 # This subclass ignores this attribute as it always need to return
589 # something.
591 # something.
590 enabled = Bool(True, config=False)
592 enabled = Bool(True, config=False)
591
593
594 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH, config=True,
595 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
596
597 Set to 0 to disable truncation.
598 """
599 )
600
592 # Look for a _repr_pretty_ methods to use for pretty printing.
601 # Look for a _repr_pretty_ methods to use for pretty printing.
593 print_method = ObjectName('_repr_pretty_')
602 print_method = ObjectName('_repr_pretty_')
594
603
595 # Whether to pretty-print or not.
604 # Whether to pretty-print or not.
596 pprint = Bool(True, config=True)
605 pprint = Bool(True, config=True)
597
606
598 # Whether to be verbose or not.
607 # Whether to be verbose or not.
599 verbose = Bool(False, config=True)
608 verbose = Bool(False, config=True)
600
609
601 # The maximum width.
610 # The maximum width.
602 max_width = Integer(79, config=True)
611 max_width = Integer(79, config=True)
603
612
604 # The newline character.
613 # The newline character.
605 newline = Unicode('\n', config=True)
614 newline = Unicode('\n', config=True)
606
615
607 # format-string for pprinting floats
616 # format-string for pprinting floats
608 float_format = Unicode('%r')
617 float_format = Unicode('%r')
609 # setter for float precision, either int or direct format-string
618 # setter for float precision, either int or direct format-string
610 float_precision = CUnicode('', config=True)
619 float_precision = CUnicode('', config=True)
611
620
612 def _float_precision_changed(self, name, old, new):
621 def _float_precision_changed(self, name, old, new):
613 """float_precision changed, set float_format accordingly.
622 """float_precision changed, set float_format accordingly.
614
623
615 float_precision can be set by int or str.
624 float_precision can be set by int or str.
616 This will set float_format, after interpreting input.
625 This will set float_format, after interpreting input.
617 If numpy has been imported, numpy print precision will also be set.
626 If numpy has been imported, numpy print precision will also be set.
618
627
619 integer `n` sets format to '%.nf', otherwise, format set directly.
628 integer `n` sets format to '%.nf', otherwise, format set directly.
620
629
621 An empty string returns to defaults (repr for float, 8 for numpy).
630 An empty string returns to defaults (repr for float, 8 for numpy).
622
631
623 This parameter can be set via the '%precision' magic.
632 This parameter can be set via the '%precision' magic.
624 """
633 """
625
634
626 if '%' in new:
635 if '%' in new:
627 # got explicit format string
636 # got explicit format string
628 fmt = new
637 fmt = new
629 try:
638 try:
630 fmt%3.14159
639 fmt%3.14159
631 except Exception:
640 except Exception:
632 raise ValueError("Precision must be int or format string, not %r"%new)
641 raise ValueError("Precision must be int or format string, not %r"%new)
633 elif new:
642 elif new:
634 # otherwise, should be an int
643 # otherwise, should be an int
635 try:
644 try:
636 i = int(new)
645 i = int(new)
637 assert i >= 0
646 assert i >= 0
638 except ValueError:
647 except ValueError:
639 raise ValueError("Precision must be int or format string, not %r"%new)
648 raise ValueError("Precision must be int or format string, not %r"%new)
640 except AssertionError:
649 except AssertionError:
641 raise ValueError("int precision must be non-negative, not %r"%i)
650 raise ValueError("int precision must be non-negative, not %r"%i)
642
651
643 fmt = '%%.%if'%i
652 fmt = '%%.%if'%i
644 if 'numpy' in sys.modules:
653 if 'numpy' in sys.modules:
645 # set numpy precision if it has been imported
654 # set numpy precision if it has been imported
646 import numpy
655 import numpy
647 numpy.set_printoptions(precision=i)
656 numpy.set_printoptions(precision=i)
648 else:
657 else:
649 # default back to repr
658 # default back to repr
650 fmt = '%r'
659 fmt = '%r'
651 if 'numpy' in sys.modules:
660 if 'numpy' in sys.modules:
652 import numpy
661 import numpy
653 # numpy default is 8
662 # numpy default is 8
654 numpy.set_printoptions(precision=8)
663 numpy.set_printoptions(precision=8)
655 self.float_format = fmt
664 self.float_format = fmt
656
665
657 # Use the default pretty printers from IPython.lib.pretty.
666 # Use the default pretty printers from IPython.lib.pretty.
658 def _singleton_printers_default(self):
667 def _singleton_printers_default(self):
659 return pretty._singleton_pprinters.copy()
668 return pretty._singleton_pprinters.copy()
660
669
661 def _type_printers_default(self):
670 def _type_printers_default(self):
662 d = pretty._type_pprinters.copy()
671 d = pretty._type_pprinters.copy()
663 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
672 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
664 return d
673 return d
665
674
666 def _deferred_printers_default(self):
675 def _deferred_printers_default(self):
667 return pretty._deferred_type_pprinters.copy()
676 return pretty._deferred_type_pprinters.copy()
668
677
669 #### FormatterABC interface ####
678 #### FormatterABC interface ####
670
679
671 @warn_format_error
680 @warn_format_error
672 def __call__(self, obj):
681 def __call__(self, obj):
673 """Compute the pretty representation of the object."""
682 """Compute the pretty representation of the object."""
674 if not self.pprint:
683 if not self.pprint:
675 return pretty._safe_repr(obj)
684 return repr(obj)
676 else:
685 else:
677 # This uses use StringIO, as cStringIO doesn't handle unicode.
686 # This uses use StringIO, as cStringIO doesn't handle unicode.
678 stream = StringIO()
687 stream = StringIO()
679 # self.newline.encode() is a quick fix for issue gh-597. We need to
688 # self.newline.encode() is a quick fix for issue gh-597. We need to
680 # ensure that stream does not get a mix of unicode and bytestrings,
689 # ensure that stream does not get a mix of unicode and bytestrings,
681 # or it will cause trouble.
690 # or it will cause trouble.
682 printer = pretty.RepresentationPrinter(stream, self.verbose,
691 printer = pretty.RepresentationPrinter(stream, self.verbose,
683 self.max_width, unicode_to_str(self.newline),
692 self.max_width, unicode_to_str(self.newline),
693 max_seq_length=self.max_seq_length,
684 singleton_pprinters=self.singleton_printers,
694 singleton_pprinters=self.singleton_printers,
685 type_pprinters=self.type_printers,
695 type_pprinters=self.type_printers,
686 deferred_pprinters=self.deferred_printers)
696 deferred_pprinters=self.deferred_printers)
687 printer.pretty(obj)
697 printer.pretty(obj)
688 printer.flush()
698 printer.flush()
689 return stream.getvalue()
699 return stream.getvalue()
690
700
691
701
692 class HTMLFormatter(BaseFormatter):
702 class HTMLFormatter(BaseFormatter):
693 """An HTML formatter.
703 """An HTML formatter.
694
704
695 To define the callables that compute the HTML representation of your
705 To define the callables that compute the HTML representation of your
696 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
706 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
697 or :meth:`for_type_by_name` methods to register functions that handle
707 or :meth:`for_type_by_name` methods to register functions that handle
698 this.
708 this.
699
709
700 The return value of this formatter should be a valid HTML snippet that
710 The return value of this formatter should be a valid HTML snippet that
701 could be injected into an existing DOM. It should *not* include the
711 could be injected into an existing DOM. It should *not* include the
702 ```<html>`` or ```<body>`` tags.
712 ```<html>`` or ```<body>`` tags.
703 """
713 """
704 format_type = Unicode('text/html')
714 format_type = Unicode('text/html')
705
715
706 print_method = ObjectName('_repr_html_')
716 print_method = ObjectName('_repr_html_')
707
717
708
718
709 class MarkdownFormatter(BaseFormatter):
719 class MarkdownFormatter(BaseFormatter):
710 """A Markdown formatter.
720 """A Markdown formatter.
711
721
712 To define the callables that compute the Markdown representation of your
722 To define the callables that compute the Markdown representation of your
713 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
723 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
714 or :meth:`for_type_by_name` methods to register functions that handle
724 or :meth:`for_type_by_name` methods to register functions that handle
715 this.
725 this.
716
726
717 The return value of this formatter should be a valid Markdown.
727 The return value of this formatter should be a valid Markdown.
718 """
728 """
719 format_type = Unicode('text/markdown')
729 format_type = Unicode('text/markdown')
720
730
721 print_method = ObjectName('_repr_markdown_')
731 print_method = ObjectName('_repr_markdown_')
722
732
723 class SVGFormatter(BaseFormatter):
733 class SVGFormatter(BaseFormatter):
724 """An SVG formatter.
734 """An SVG formatter.
725
735
726 To define the callables that compute the SVG representation of your
736 To define the callables that compute the SVG representation of your
727 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
737 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
728 or :meth:`for_type_by_name` methods to register functions that handle
738 or :meth:`for_type_by_name` methods to register functions that handle
729 this.
739 this.
730
740
731 The return value of this formatter should be valid SVG enclosed in
741 The return value of this formatter should be valid SVG enclosed in
732 ```<svg>``` tags, that could be injected into an existing DOM. It should
742 ```<svg>``` tags, that could be injected into an existing DOM. It should
733 *not* include the ```<html>`` or ```<body>`` tags.
743 *not* include the ```<html>`` or ```<body>`` tags.
734 """
744 """
735 format_type = Unicode('image/svg+xml')
745 format_type = Unicode('image/svg+xml')
736
746
737 print_method = ObjectName('_repr_svg_')
747 print_method = ObjectName('_repr_svg_')
738
748
739
749
740 class PNGFormatter(BaseFormatter):
750 class PNGFormatter(BaseFormatter):
741 """A PNG formatter.
751 """A PNG formatter.
742
752
743 To define the callables that compute the PNG representation of your
753 To define the callables that compute the PNG representation of your
744 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
754 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
745 or :meth:`for_type_by_name` methods to register functions that handle
755 or :meth:`for_type_by_name` methods to register functions that handle
746 this.
756 this.
747
757
748 The return value of this formatter should be raw PNG data, *not*
758 The return value of this formatter should be raw PNG data, *not*
749 base64 encoded.
759 base64 encoded.
750 """
760 """
751 format_type = Unicode('image/png')
761 format_type = Unicode('image/png')
752
762
753 print_method = ObjectName('_repr_png_')
763 print_method = ObjectName('_repr_png_')
754
764
755 _return_type = (bytes, unicode_type)
765 _return_type = (bytes, unicode_type)
756
766
757
767
758 class JPEGFormatter(BaseFormatter):
768 class JPEGFormatter(BaseFormatter):
759 """A JPEG formatter.
769 """A JPEG formatter.
760
770
761 To define the callables that compute the JPEG representation of your
771 To define the callables that compute the JPEG representation of your
762 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
772 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
763 or :meth:`for_type_by_name` methods to register functions that handle
773 or :meth:`for_type_by_name` methods to register functions that handle
764 this.
774 this.
765
775
766 The return value of this formatter should be raw JPEG data, *not*
776 The return value of this formatter should be raw JPEG data, *not*
767 base64 encoded.
777 base64 encoded.
768 """
778 """
769 format_type = Unicode('image/jpeg')
779 format_type = Unicode('image/jpeg')
770
780
771 print_method = ObjectName('_repr_jpeg_')
781 print_method = ObjectName('_repr_jpeg_')
772
782
773 _return_type = (bytes, unicode_type)
783 _return_type = (bytes, unicode_type)
774
784
775
785
776 class LatexFormatter(BaseFormatter):
786 class LatexFormatter(BaseFormatter):
777 """A LaTeX formatter.
787 """A LaTeX formatter.
778
788
779 To define the callables that compute the LaTeX representation of your
789 To define the callables that compute the LaTeX representation of your
780 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
790 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
781 or :meth:`for_type_by_name` methods to register functions that handle
791 or :meth:`for_type_by_name` methods to register functions that handle
782 this.
792 this.
783
793
784 The return value of this formatter should be a valid LaTeX equation,
794 The return value of this formatter should be a valid LaTeX equation,
785 enclosed in either ```$```, ```$$``` or another LaTeX equation
795 enclosed in either ```$```, ```$$``` or another LaTeX equation
786 environment.
796 environment.
787 """
797 """
788 format_type = Unicode('text/latex')
798 format_type = Unicode('text/latex')
789
799
790 print_method = ObjectName('_repr_latex_')
800 print_method = ObjectName('_repr_latex_')
791
801
792
802
793 class JSONFormatter(BaseFormatter):
803 class JSONFormatter(BaseFormatter):
794 """A JSON string formatter.
804 """A JSON string formatter.
795
805
796 To define the callables that compute the JSON string representation of
806 To define the callables that compute the JSON string representation of
797 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
807 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
798 or :meth:`for_type_by_name` methods to register functions that handle
808 or :meth:`for_type_by_name` methods to register functions that handle
799 this.
809 this.
800
810
801 The return value of this formatter should be a valid JSON string.
811 The return value of this formatter should be a valid JSON string.
802 """
812 """
803 format_type = Unicode('application/json')
813 format_type = Unicode('application/json')
804
814
805 print_method = ObjectName('_repr_json_')
815 print_method = ObjectName('_repr_json_')
806
816
807
817
808 class JavascriptFormatter(BaseFormatter):
818 class JavascriptFormatter(BaseFormatter):
809 """A Javascript formatter.
819 """A Javascript formatter.
810
820
811 To define the callables that compute the Javascript representation of
821 To define the callables that compute the Javascript representation of
812 your objects, define a :meth:`_repr_javascript_` method or use the
822 your objects, define a :meth:`_repr_javascript_` method or use the
813 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
823 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
814 that handle this.
824 that handle this.
815
825
816 The return value of this formatter should be valid Javascript code and
826 The return value of this formatter should be valid Javascript code and
817 should *not* be enclosed in ```<script>``` tags.
827 should *not* be enclosed in ```<script>``` tags.
818 """
828 """
819 format_type = Unicode('application/javascript')
829 format_type = Unicode('application/javascript')
820
830
821 print_method = ObjectName('_repr_javascript_')
831 print_method = ObjectName('_repr_javascript_')
822
832
823
833
824 class PDFFormatter(BaseFormatter):
834 class PDFFormatter(BaseFormatter):
825 """A PDF formatter.
835 """A PDF formatter.
826
836
827 To define the callables that compute the PDF representation of your
837 To define the callables that compute the PDF representation of your
828 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
838 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
829 or :meth:`for_type_by_name` methods to register functions that handle
839 or :meth:`for_type_by_name` methods to register functions that handle
830 this.
840 this.
831
841
832 The return value of this formatter should be raw PDF data, *not*
842 The return value of this formatter should be raw PDF data, *not*
833 base64 encoded.
843 base64 encoded.
834 """
844 """
835 format_type = Unicode('application/pdf')
845 format_type = Unicode('application/pdf')
836
846
837 print_method = ObjectName('_repr_pdf_')
847 print_method = ObjectName('_repr_pdf_')
838
848
849 _return_type = (bytes, unicode_type)
850
839
851
840 FormatterABC.register(BaseFormatter)
852 FormatterABC.register(BaseFormatter)
841 FormatterABC.register(PlainTextFormatter)
853 FormatterABC.register(PlainTextFormatter)
842 FormatterABC.register(HTMLFormatter)
854 FormatterABC.register(HTMLFormatter)
843 FormatterABC.register(MarkdownFormatter)
855 FormatterABC.register(MarkdownFormatter)
844 FormatterABC.register(SVGFormatter)
856 FormatterABC.register(SVGFormatter)
845 FormatterABC.register(PNGFormatter)
857 FormatterABC.register(PNGFormatter)
846 FormatterABC.register(PDFFormatter)
858 FormatterABC.register(PDFFormatter)
847 FormatterABC.register(JPEGFormatter)
859 FormatterABC.register(JPEGFormatter)
848 FormatterABC.register(LatexFormatter)
860 FormatterABC.register(LatexFormatter)
849 FormatterABC.register(JSONFormatter)
861 FormatterABC.register(JSONFormatter)
850 FormatterABC.register(JavascriptFormatter)
862 FormatterABC.register(JavascriptFormatter)
851
863
852
864
853 def format_display_data(obj, include=None, exclude=None):
865 def format_display_data(obj, include=None, exclude=None):
854 """Return a format data dict for an object.
866 """Return a format data dict for an object.
855
867
856 By default all format types will be computed.
868 By default all format types will be computed.
857
869
858 The following MIME types are currently implemented:
870 The following MIME types are currently implemented:
859
871
860 * text/plain
872 * text/plain
861 * text/html
873 * text/html
862 * text/markdown
874 * text/markdown
863 * text/latex
875 * text/latex
864 * application/json
876 * application/json
865 * application/javascript
877 * application/javascript
866 * application/pdf
878 * application/pdf
867 * image/png
879 * image/png
868 * image/jpeg
880 * image/jpeg
869 * image/svg+xml
881 * image/svg+xml
870
882
871 Parameters
883 Parameters
872 ----------
884 ----------
873 obj : object
885 obj : object
874 The Python object whose format data will be computed.
886 The Python object whose format data will be computed.
875
887
876 Returns
888 Returns
877 -------
889 -------
878 format_dict : dict
890 format_dict : dict
879 A dictionary of key/value pairs, one or each format that was
891 A dictionary of key/value pairs, one or each format that was
880 generated for the object. The keys are the format types, which
892 generated for the object. The keys are the format types, which
881 will usually be MIME type strings and the values and JSON'able
893 will usually be MIME type strings and the values and JSON'able
882 data structure containing the raw data for the representation in
894 data structure containing the raw data for the representation in
883 that format.
895 that format.
884 include : list or tuple, optional
896 include : list or tuple, optional
885 A list of format type strings (MIME types) to include in the
897 A list of format type strings (MIME types) to include in the
886 format data dict. If this is set *only* the format types included
898 format data dict. If this is set *only* the format types included
887 in this list will be computed.
899 in this list will be computed.
888 exclude : list or tuple, optional
900 exclude : list or tuple, optional
889 A list of format type string (MIME types) to exclue in the format
901 A list of format type string (MIME types) to exclue in the format
890 data dict. If this is set all format types will be computed,
902 data dict. If this is set all format types will be computed,
891 except for those included in this argument.
903 except for those included in this argument.
892 """
904 """
893 from IPython.core.interactiveshell import InteractiveShell
905 from IPython.core.interactiveshell import InteractiveShell
894
906
895 InteractiveShell.instance().display_formatter.format(
907 InteractiveShell.instance().display_formatter.format(
896 obj,
908 obj,
897 include,
909 include,
898 exclude
910 exclude
899 )
911 )
900
912
@@ -1,855 +1,870 b''
1 """ History related magics and functionality """
1 """ History related magics and functionality """
2 #-----------------------------------------------------------------------------
2 #-----------------------------------------------------------------------------
3 # Copyright (C) 2010-2011 The IPython Development Team.
3 # Copyright (C) 2010-2011 The IPython Development Team.
4 #
4 #
5 # Distributed under the terms of the BSD License.
5 # Distributed under the terms of the BSD License.
6 #
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 from __future__ import print_function
13 from __future__ import print_function
14
14
15 # Stdlib imports
15 # Stdlib imports
16 import atexit
16 import atexit
17 import datetime
17 import datetime
18 import os
18 import os
19 import re
19 import re
20 try:
20 try:
21 import sqlite3
21 import sqlite3
22 except ImportError:
22 except ImportError:
23 try:
23 try:
24 from pysqlite2 import dbapi2 as sqlite3
24 from pysqlite2 import dbapi2 as sqlite3
25 except ImportError:
25 except ImportError:
26 sqlite3 = None
26 sqlite3 = None
27 import threading
27 import threading
28
28
29 # Our own packages
29 # Our own packages
30 from IPython.config.configurable import Configurable
30 from IPython.config.configurable import Configurable
31 from IPython.external.decorator import decorator
31 from IPython.external.decorator import decorator
32 from IPython.utils.decorators import undoc
32 from IPython.utils.decorators import undoc
33 from IPython.utils.path import locate_profile
33 from IPython.utils.path import locate_profile
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.traitlets import (
35 from IPython.utils.traitlets import (
36 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
36 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
37 )
37 )
38 from IPython.utils.warn import warn
38 from IPython.utils.warn import warn
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Classes and functions
41 # Classes and functions
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 @undoc
44 @undoc
45 class DummyDB(object):
45 class DummyDB(object):
46 """Dummy DB that will act as a black hole for history.
46 """Dummy DB that will act as a black hole for history.
47
47
48 Only used in the absence of sqlite"""
48 Only used in the absence of sqlite"""
49 def execute(*args, **kwargs):
49 def execute(*args, **kwargs):
50 return []
50 return []
51
51
52 def commit(self, *args, **kwargs):
52 def commit(self, *args, **kwargs):
53 pass
53 pass
54
54
55 def __enter__(self, *args, **kwargs):
55 def __enter__(self, *args, **kwargs):
56 pass
56 pass
57
57
58 def __exit__(self, *args, **kwargs):
58 def __exit__(self, *args, **kwargs):
59 pass
59 pass
60
60
61
61
62 @decorator
62 @decorator
63 def needs_sqlite(f, self, *a, **kw):
63 def needs_sqlite(f, self, *a, **kw):
64 """Decorator: return an empty list in the absence of sqlite."""
64 """Decorator: return an empty list in the absence of sqlite."""
65 if sqlite3 is None or not self.enabled:
65 if sqlite3 is None or not self.enabled:
66 return []
66 return []
67 else:
67 else:
68 return f(self, *a, **kw)
68 return f(self, *a, **kw)
69
69
70
70
71 if sqlite3 is not None:
71 if sqlite3 is not None:
72 DatabaseError = sqlite3.DatabaseError
72 DatabaseError = sqlite3.DatabaseError
73 else:
73 else:
74 @undoc
74 @undoc
75 class DatabaseError(Exception):
75 class DatabaseError(Exception):
76 "Dummy exception when sqlite could not be imported. Should never occur."
76 "Dummy exception when sqlite could not be imported. Should never occur."
77
77
78 @decorator
78 @decorator
79 def catch_corrupt_db(f, self, *a, **kw):
79 def catch_corrupt_db(f, self, *a, **kw):
80 """A decorator which wraps HistoryAccessor method calls to catch errors from
80 """A decorator which wraps HistoryAccessor method calls to catch errors from
81 a corrupt SQLite database, move the old database out of the way, and create
81 a corrupt SQLite database, move the old database out of the way, and create
82 a new one.
82 a new one.
83 """
83 """
84 try:
84 try:
85 return f(self, *a, **kw)
85 return f(self, *a, **kw)
86 except DatabaseError:
86 except DatabaseError:
87 if os.path.isfile(self.hist_file):
87 if os.path.isfile(self.hist_file):
88 # Try to move the file out of the way
88 # Try to move the file out of the way
89 base,ext = os.path.splitext(self.hist_file)
89 base,ext = os.path.splitext(self.hist_file)
90 newpath = base + '-corrupt' + ext
90 newpath = base + '-corrupt' + ext
91 os.rename(self.hist_file, newpath)
91 os.rename(self.hist_file, newpath)
92 self.init_db()
92 self.init_db()
93 print("ERROR! History file wasn't a valid SQLite database.",
93 print("ERROR! History file wasn't a valid SQLite database.",
94 "It was moved to %s" % newpath, "and a new file created.")
94 "It was moved to %s" % newpath, "and a new file created.")
95 return []
95 return []
96
96
97 else:
97 else:
98 # The hist_file is probably :memory: or something else.
98 # The hist_file is probably :memory: or something else.
99 raise
99 raise
100
100
101 class HistoryAccessorBase(Configurable):
102 """An abstract class for History Accessors """
101
103
104 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
105 raise NotImplementedError
106
107 def search(self, pattern="*", raw=True, search_raw=True,
108 output=False, n=None, unique=False):
109 raise NotImplementedError
110
111 def get_range(self, session, start=1, stop=None, raw=True,output=False):
112 raise NotImplementedError
102
113
103 class HistoryAccessor(Configurable):
114 def get_range_by_str(self, rangestr, raw=True, output=False):
115 raise NotImplementedError
116
117
118 class HistoryAccessor(HistoryAccessorBase):
104 """Access the history database without adding to it.
119 """Access the history database without adding to it.
105
120
106 This is intended for use by standalone history tools. IPython shells use
121 This is intended for use by standalone history tools. IPython shells use
107 HistoryManager, below, which is a subclass of this."""
122 HistoryManager, below, which is a subclass of this."""
108
123
109 # String holding the path to the history file
124 # String holding the path to the history file
110 hist_file = Unicode(config=True,
125 hist_file = Unicode(config=True,
111 help="""Path to file to use for SQLite history database.
126 help="""Path to file to use for SQLite history database.
112
127
113 By default, IPython will put the history database in the IPython
128 By default, IPython will put the history database in the IPython
114 profile directory. If you would rather share one history among
129 profile directory. If you would rather share one history among
115 profiles, you can set this value in each, so that they are consistent.
130 profiles, you can set this value in each, so that they are consistent.
116
131
117 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
132 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
118 mounts. If you see IPython hanging, try setting this to something on a
133 mounts. If you see IPython hanging, try setting this to something on a
119 local disk, e.g::
134 local disk, e.g::
120
135
121 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
136 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
122
137
123 """)
138 """)
124
139
125 enabled = Bool(True, config=True,
140 enabled = Bool(True, config=True,
126 help="""enable the SQLite history
141 help="""enable the SQLite history
127
142
128 set enabled=False to disable the SQLite history,
143 set enabled=False to disable the SQLite history,
129 in which case there will be no stored history, no SQLite connection,
144 in which case there will be no stored history, no SQLite connection,
130 and no background saving thread. This may be necessary in some
145 and no background saving thread. This may be necessary in some
131 threaded environments where IPython is embedded.
146 threaded environments where IPython is embedded.
132 """
147 """
133 )
148 )
134
149
135 connection_options = Dict(config=True,
150 connection_options = Dict(config=True,
136 help="""Options for configuring the SQLite connection
151 help="""Options for configuring the SQLite connection
137
152
138 These options are passed as keyword args to sqlite3.connect
153 These options are passed as keyword args to sqlite3.connect
139 when establishing database conenctions.
154 when establishing database conenctions.
140 """
155 """
141 )
156 )
142
157
143 # The SQLite database
158 # The SQLite database
144 db = Any()
159 db = Any()
145 def _db_changed(self, name, old, new):
160 def _db_changed(self, name, old, new):
146 """validate the db, since it can be an Instance of two different types"""
161 """validate the db, since it can be an Instance of two different types"""
147 connection_types = (DummyDB,)
162 connection_types = (DummyDB,)
148 if sqlite3 is not None:
163 if sqlite3 is not None:
149 connection_types = (DummyDB, sqlite3.Connection)
164 connection_types = (DummyDB, sqlite3.Connection)
150 if not isinstance(new, connection_types):
165 if not isinstance(new, connection_types):
151 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
166 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
152 (self.__class__.__name__, new)
167 (self.__class__.__name__, new)
153 raise TraitError(msg)
168 raise TraitError(msg)
154
169
155 def __init__(self, profile='default', hist_file=u'', **traits):
170 def __init__(self, profile='default', hist_file=u'', **traits):
156 """Create a new history accessor.
171 """Create a new history accessor.
157
172
158 Parameters
173 Parameters
159 ----------
174 ----------
160 profile : str
175 profile : str
161 The name of the profile from which to open history.
176 The name of the profile from which to open history.
162 hist_file : str
177 hist_file : str
163 Path to an SQLite history database stored by IPython. If specified,
178 Path to an SQLite history database stored by IPython. If specified,
164 hist_file overrides profile.
179 hist_file overrides profile.
165 config : :class:`~IPython.config.loader.Config`
180 config : :class:`~IPython.config.loader.Config`
166 Config object. hist_file can also be set through this.
181 Config object. hist_file can also be set through this.
167 """
182 """
168 # We need a pointer back to the shell for various tasks.
183 # We need a pointer back to the shell for various tasks.
169 super(HistoryAccessor, self).__init__(**traits)
184 super(HistoryAccessor, self).__init__(**traits)
170 # defer setting hist_file from kwarg until after init,
185 # defer setting hist_file from kwarg until after init,
171 # otherwise the default kwarg value would clobber any value
186 # otherwise the default kwarg value would clobber any value
172 # set by config
187 # set by config
173 if hist_file:
188 if hist_file:
174 self.hist_file = hist_file
189 self.hist_file = hist_file
175
190
176 if self.hist_file == u'':
191 if self.hist_file == u'':
177 # No one has set the hist_file, yet.
192 # No one has set the hist_file, yet.
178 self.hist_file = self._get_hist_file_name(profile)
193 self.hist_file = self._get_hist_file_name(profile)
179
194
180 if sqlite3 is None and self.enabled:
195 if sqlite3 is None and self.enabled:
181 warn("IPython History requires SQLite, your history will not be saved")
196 warn("IPython History requires SQLite, your history will not be saved")
182 self.enabled = False
197 self.enabled = False
183
198
184 self.init_db()
199 self.init_db()
185
200
186 def _get_hist_file_name(self, profile='default'):
201 def _get_hist_file_name(self, profile='default'):
187 """Find the history file for the given profile name.
202 """Find the history file for the given profile name.
188
203
189 This is overridden by the HistoryManager subclass, to use the shell's
204 This is overridden by the HistoryManager subclass, to use the shell's
190 active profile.
205 active profile.
191
206
192 Parameters
207 Parameters
193 ----------
208 ----------
194 profile : str
209 profile : str
195 The name of a profile which has a history file.
210 The name of a profile which has a history file.
196 """
211 """
197 return os.path.join(locate_profile(profile), 'history.sqlite')
212 return os.path.join(locate_profile(profile), 'history.sqlite')
198
213
199 @catch_corrupt_db
214 @catch_corrupt_db
200 def init_db(self):
215 def init_db(self):
201 """Connect to the database, and create tables if necessary."""
216 """Connect to the database, and create tables if necessary."""
202 if not self.enabled:
217 if not self.enabled:
203 self.db = DummyDB()
218 self.db = DummyDB()
204 return
219 return
205
220
206 # use detect_types so that timestamps return datetime objects
221 # use detect_types so that timestamps return datetime objects
207 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
222 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
208 kwargs.update(self.connection_options)
223 kwargs.update(self.connection_options)
209 self.db = sqlite3.connect(self.hist_file, **kwargs)
224 self.db = sqlite3.connect(self.hist_file, **kwargs)
210 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
225 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
211 primary key autoincrement, start timestamp,
226 primary key autoincrement, start timestamp,
212 end timestamp, num_cmds integer, remark text)""")
227 end timestamp, num_cmds integer, remark text)""")
213 self.db.execute("""CREATE TABLE IF NOT EXISTS history
228 self.db.execute("""CREATE TABLE IF NOT EXISTS history
214 (session integer, line integer, source text, source_raw text,
229 (session integer, line integer, source text, source_raw text,
215 PRIMARY KEY (session, line))""")
230 PRIMARY KEY (session, line))""")
216 # Output history is optional, but ensure the table's there so it can be
231 # Output history is optional, but ensure the table's there so it can be
217 # enabled later.
232 # enabled later.
218 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
233 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
219 (session integer, line integer, output text,
234 (session integer, line integer, output text,
220 PRIMARY KEY (session, line))""")
235 PRIMARY KEY (session, line))""")
221 self.db.commit()
236 self.db.commit()
222
237
223 def writeout_cache(self):
238 def writeout_cache(self):
224 """Overridden by HistoryManager to dump the cache before certain
239 """Overridden by HistoryManager to dump the cache before certain
225 database lookups."""
240 database lookups."""
226 pass
241 pass
227
242
228 ## -------------------------------
243 ## -------------------------------
229 ## Methods for retrieving history:
244 ## Methods for retrieving history:
230 ## -------------------------------
245 ## -------------------------------
231 def _run_sql(self, sql, params, raw=True, output=False):
246 def _run_sql(self, sql, params, raw=True, output=False):
232 """Prepares and runs an SQL query for the history database.
247 """Prepares and runs an SQL query for the history database.
233
248
234 Parameters
249 Parameters
235 ----------
250 ----------
236 sql : str
251 sql : str
237 Any filtering expressions to go after SELECT ... FROM ...
252 Any filtering expressions to go after SELECT ... FROM ...
238 params : tuple
253 params : tuple
239 Parameters passed to the SQL query (to replace "?")
254 Parameters passed to the SQL query (to replace "?")
240 raw, output : bool
255 raw, output : bool
241 See :meth:`get_range`
256 See :meth:`get_range`
242
257
243 Returns
258 Returns
244 -------
259 -------
245 Tuples as :meth:`get_range`
260 Tuples as :meth:`get_range`
246 """
261 """
247 toget = 'source_raw' if raw else 'source'
262 toget = 'source_raw' if raw else 'source'
248 sqlfrom = "history"
263 sqlfrom = "history"
249 if output:
264 if output:
250 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
265 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
251 toget = "history.%s, output_history.output" % toget
266 toget = "history.%s, output_history.output" % toget
252 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
267 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
253 (toget, sqlfrom) + sql, params)
268 (toget, sqlfrom) + sql, params)
254 if output: # Regroup into 3-tuples, and parse JSON
269 if output: # Regroup into 3-tuples, and parse JSON
255 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
270 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
256 return cur
271 return cur
257
272
258 @needs_sqlite
273 @needs_sqlite
259 @catch_corrupt_db
274 @catch_corrupt_db
260 def get_session_info(self, session):
275 def get_session_info(self, session):
261 """Get info about a session.
276 """Get info about a session.
262
277
263 Parameters
278 Parameters
264 ----------
279 ----------
265
280
266 session : int
281 session : int
267 Session number to retrieve.
282 Session number to retrieve.
268
283
269 Returns
284 Returns
270 -------
285 -------
271
286
272 session_id : int
287 session_id : int
273 Session ID number
288 Session ID number
274 start : datetime
289 start : datetime
275 Timestamp for the start of the session.
290 Timestamp for the start of the session.
276 end : datetime
291 end : datetime
277 Timestamp for the end of the session, or None if IPython crashed.
292 Timestamp for the end of the session, or None if IPython crashed.
278 num_cmds : int
293 num_cmds : int
279 Number of commands run, or None if IPython crashed.
294 Number of commands run, or None if IPython crashed.
280 remark : unicode
295 remark : unicode
281 A manually set description.
296 A manually set description.
282 """
297 """
283 query = "SELECT * from sessions where session == ?"
298 query = "SELECT * from sessions where session == ?"
284 return self.db.execute(query, (session,)).fetchone()
299 return self.db.execute(query, (session,)).fetchone()
285
300
286 @catch_corrupt_db
301 @catch_corrupt_db
287 def get_last_session_id(self):
302 def get_last_session_id(self):
288 """Get the last session ID currently in the database.
303 """Get the last session ID currently in the database.
289
304
290 Within IPython, this should be the same as the value stored in
305 Within IPython, this should be the same as the value stored in
291 :attr:`HistoryManager.session_number`.
306 :attr:`HistoryManager.session_number`.
292 """
307 """
293 for record in self.get_tail(n=1, include_latest=True):
308 for record in self.get_tail(n=1, include_latest=True):
294 return record[0]
309 return record[0]
295
310
296 @catch_corrupt_db
311 @catch_corrupt_db
297 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
312 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
298 """Get the last n lines from the history database.
313 """Get the last n lines from the history database.
299
314
300 Parameters
315 Parameters
301 ----------
316 ----------
302 n : int
317 n : int
303 The number of lines to get
318 The number of lines to get
304 raw, output : bool
319 raw, output : bool
305 See :meth:`get_range`
320 See :meth:`get_range`
306 include_latest : bool
321 include_latest : bool
307 If False (default), n+1 lines are fetched, and the latest one
322 If False (default), n+1 lines are fetched, and the latest one
308 is discarded. This is intended to be used where the function
323 is discarded. This is intended to be used where the function
309 is called by a user command, which it should not return.
324 is called by a user command, which it should not return.
310
325
311 Returns
326 Returns
312 -------
327 -------
313 Tuples as :meth:`get_range`
328 Tuples as :meth:`get_range`
314 """
329 """
315 self.writeout_cache()
330 self.writeout_cache()
316 if not include_latest:
331 if not include_latest:
317 n += 1
332 n += 1
318 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
333 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
319 (n,), raw=raw, output=output)
334 (n,), raw=raw, output=output)
320 if not include_latest:
335 if not include_latest:
321 return reversed(list(cur)[1:])
336 return reversed(list(cur)[1:])
322 return reversed(list(cur))
337 return reversed(list(cur))
323
338
324 @catch_corrupt_db
339 @catch_corrupt_db
325 def search(self, pattern="*", raw=True, search_raw=True,
340 def search(self, pattern="*", raw=True, search_raw=True,
326 output=False, n=None, unique=False):
341 output=False, n=None, unique=False):
327 """Search the database using unix glob-style matching (wildcards
342 """Search the database using unix glob-style matching (wildcards
328 * and ?).
343 * and ?).
329
344
330 Parameters
345 Parameters
331 ----------
346 ----------
332 pattern : str
347 pattern : str
333 The wildcarded pattern to match when searching
348 The wildcarded pattern to match when searching
334 search_raw : bool
349 search_raw : bool
335 If True, search the raw input, otherwise, the parsed input
350 If True, search the raw input, otherwise, the parsed input
336 raw, output : bool
351 raw, output : bool
337 See :meth:`get_range`
352 See :meth:`get_range`
338 n : None or int
353 n : None or int
339 If an integer is given, it defines the limit of
354 If an integer is given, it defines the limit of
340 returned entries.
355 returned entries.
341 unique : bool
356 unique : bool
342 When it is true, return only unique entries.
357 When it is true, return only unique entries.
343
358
344 Returns
359 Returns
345 -------
360 -------
346 Tuples as :meth:`get_range`
361 Tuples as :meth:`get_range`
347 """
362 """
348 tosearch = "source_raw" if search_raw else "source"
363 tosearch = "source_raw" if search_raw else "source"
349 if output:
364 if output:
350 tosearch = "history." + tosearch
365 tosearch = "history." + tosearch
351 self.writeout_cache()
366 self.writeout_cache()
352 sqlform = "WHERE %s GLOB ?" % tosearch
367 sqlform = "WHERE %s GLOB ?" % tosearch
353 params = (pattern,)
368 params = (pattern,)
354 if unique:
369 if unique:
355 sqlform += ' GROUP BY {0}'.format(tosearch)
370 sqlform += ' GROUP BY {0}'.format(tosearch)
356 if n is not None:
371 if n is not None:
357 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
372 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
358 params += (n,)
373 params += (n,)
359 elif unique:
374 elif unique:
360 sqlform += " ORDER BY session, line"
375 sqlform += " ORDER BY session, line"
361 cur = self._run_sql(sqlform, params, raw=raw, output=output)
376 cur = self._run_sql(sqlform, params, raw=raw, output=output)
362 if n is not None:
377 if n is not None:
363 return reversed(list(cur))
378 return reversed(list(cur))
364 return cur
379 return cur
365
380
366 @catch_corrupt_db
381 @catch_corrupt_db
367 def get_range(self, session, start=1, stop=None, raw=True,output=False):
382 def get_range(self, session, start=1, stop=None, raw=True,output=False):
368 """Retrieve input by session.
383 """Retrieve input by session.
369
384
370 Parameters
385 Parameters
371 ----------
386 ----------
372 session : int
387 session : int
373 Session number to retrieve.
388 Session number to retrieve.
374 start : int
389 start : int
375 First line to retrieve.
390 First line to retrieve.
376 stop : int
391 stop : int
377 End of line range (excluded from output itself). If None, retrieve
392 End of line range (excluded from output itself). If None, retrieve
378 to the end of the session.
393 to the end of the session.
379 raw : bool
394 raw : bool
380 If True, return untranslated input
395 If True, return untranslated input
381 output : bool
396 output : bool
382 If True, attempt to include output. This will be 'real' Python
397 If True, attempt to include output. This will be 'real' Python
383 objects for the current session, or text reprs from previous
398 objects for the current session, or text reprs from previous
384 sessions if db_log_output was enabled at the time. Where no output
399 sessions if db_log_output was enabled at the time. Where no output
385 is found, None is used.
400 is found, None is used.
386
401
387 Returns
402 Returns
388 -------
403 -------
389 entries
404 entries
390 An iterator over the desired lines. Each line is a 3-tuple, either
405 An iterator over the desired lines. Each line is a 3-tuple, either
391 (session, line, input) if output is False, or
406 (session, line, input) if output is False, or
392 (session, line, (input, output)) if output is True.
407 (session, line, (input, output)) if output is True.
393 """
408 """
394 if stop:
409 if stop:
395 lineclause = "line >= ? AND line < ?"
410 lineclause = "line >= ? AND line < ?"
396 params = (session, start, stop)
411 params = (session, start, stop)
397 else:
412 else:
398 lineclause = "line>=?"
413 lineclause = "line>=?"
399 params = (session, start)
414 params = (session, start)
400
415
401 return self._run_sql("WHERE session==? AND %s" % lineclause,
416 return self._run_sql("WHERE session==? AND %s" % lineclause,
402 params, raw=raw, output=output)
417 params, raw=raw, output=output)
403
418
404 def get_range_by_str(self, rangestr, raw=True, output=False):
419 def get_range_by_str(self, rangestr, raw=True, output=False):
405 """Get lines of history from a string of ranges, as used by magic
420 """Get lines of history from a string of ranges, as used by magic
406 commands %hist, %save, %macro, etc.
421 commands %hist, %save, %macro, etc.
407
422
408 Parameters
423 Parameters
409 ----------
424 ----------
410 rangestr : str
425 rangestr : str
411 A string specifying ranges, e.g. "5 ~2/1-4". See
426 A string specifying ranges, e.g. "5 ~2/1-4". See
412 :func:`magic_history` for full details.
427 :func:`magic_history` for full details.
413 raw, output : bool
428 raw, output : bool
414 As :meth:`get_range`
429 As :meth:`get_range`
415
430
416 Returns
431 Returns
417 -------
432 -------
418 Tuples as :meth:`get_range`
433 Tuples as :meth:`get_range`
419 """
434 """
420 for sess, s, e in extract_hist_ranges(rangestr):
435 for sess, s, e in extract_hist_ranges(rangestr):
421 for line in self.get_range(sess, s, e, raw=raw, output=output):
436 for line in self.get_range(sess, s, e, raw=raw, output=output):
422 yield line
437 yield line
423
438
424
439
425 class HistoryManager(HistoryAccessor):
440 class HistoryManager(HistoryAccessor):
426 """A class to organize all history-related functionality in one place.
441 """A class to organize all history-related functionality in one place.
427 """
442 """
428 # Public interface
443 # Public interface
429
444
430 # An instance of the IPython shell we are attached to
445 # An instance of the IPython shell we are attached to
431 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
446 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
432 # Lists to hold processed and raw history. These start with a blank entry
447 # Lists to hold processed and raw history. These start with a blank entry
433 # so that we can index them starting from 1
448 # so that we can index them starting from 1
434 input_hist_parsed = List([""])
449 input_hist_parsed = List([""])
435 input_hist_raw = List([""])
450 input_hist_raw = List([""])
436 # A list of directories visited during session
451 # A list of directories visited during session
437 dir_hist = List()
452 dir_hist = List()
438 def _dir_hist_default(self):
453 def _dir_hist_default(self):
439 try:
454 try:
440 return [py3compat.getcwd()]
455 return [py3compat.getcwd()]
441 except OSError:
456 except OSError:
442 return []
457 return []
443
458
444 # A dict of output history, keyed with ints from the shell's
459 # A dict of output history, keyed with ints from the shell's
445 # execution count.
460 # execution count.
446 output_hist = Dict()
461 output_hist = Dict()
447 # The text/plain repr of outputs.
462 # The text/plain repr of outputs.
448 output_hist_reprs = Dict()
463 output_hist_reprs = Dict()
449
464
450 # The number of the current session in the history database
465 # The number of the current session in the history database
451 session_number = Integer()
466 session_number = Integer()
452
467
453 db_log_output = Bool(False, config=True,
468 db_log_output = Bool(False, config=True,
454 help="Should the history database include output? (default: no)"
469 help="Should the history database include output? (default: no)"
455 )
470 )
456 db_cache_size = Integer(0, config=True,
471 db_cache_size = Integer(0, config=True,
457 help="Write to database every x commands (higher values save disk access & power).\n"
472 help="Write to database every x commands (higher values save disk access & power).\n"
458 "Values of 1 or less effectively disable caching."
473 "Values of 1 or less effectively disable caching."
459 )
474 )
460 # The input and output caches
475 # The input and output caches
461 db_input_cache = List()
476 db_input_cache = List()
462 db_output_cache = List()
477 db_output_cache = List()
463
478
464 # History saving in separate thread
479 # History saving in separate thread
465 save_thread = Instance('IPython.core.history.HistorySavingThread')
480 save_thread = Instance('IPython.core.history.HistorySavingThread')
466 try: # Event is a function returning an instance of _Event...
481 try: # Event is a function returning an instance of _Event...
467 save_flag = Instance(threading._Event)
482 save_flag = Instance(threading._Event)
468 except AttributeError: # ...until Python 3.3, when it's a class.
483 except AttributeError: # ...until Python 3.3, when it's a class.
469 save_flag = Instance(threading.Event)
484 save_flag = Instance(threading.Event)
470
485
471 # Private interface
486 # Private interface
472 # Variables used to store the three last inputs from the user. On each new
487 # Variables used to store the three last inputs from the user. On each new
473 # history update, we populate the user's namespace with these, shifted as
488 # history update, we populate the user's namespace with these, shifted as
474 # necessary.
489 # necessary.
475 _i00 = Unicode(u'')
490 _i00 = Unicode(u'')
476 _i = Unicode(u'')
491 _i = Unicode(u'')
477 _ii = Unicode(u'')
492 _ii = Unicode(u'')
478 _iii = Unicode(u'')
493 _iii = Unicode(u'')
479
494
480 # A regex matching all forms of the exit command, so that we don't store
495 # A regex matching all forms of the exit command, so that we don't store
481 # them in the history (it's annoying to rewind the first entry and land on
496 # them in the history (it's annoying to rewind the first entry and land on
482 # an exit call).
497 # an exit call).
483 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
498 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
484
499
485 def __init__(self, shell=None, config=None, **traits):
500 def __init__(self, shell=None, config=None, **traits):
486 """Create a new history manager associated with a shell instance.
501 """Create a new history manager associated with a shell instance.
487 """
502 """
488 # We need a pointer back to the shell for various tasks.
503 # We need a pointer back to the shell for various tasks.
489 super(HistoryManager, self).__init__(shell=shell, config=config,
504 super(HistoryManager, self).__init__(shell=shell, config=config,
490 **traits)
505 **traits)
491 self.save_flag = threading.Event()
506 self.save_flag = threading.Event()
492 self.db_input_cache_lock = threading.Lock()
507 self.db_input_cache_lock = threading.Lock()
493 self.db_output_cache_lock = threading.Lock()
508 self.db_output_cache_lock = threading.Lock()
494 if self.enabled and self.hist_file != ':memory:':
509 if self.enabled and self.hist_file != ':memory:':
495 self.save_thread = HistorySavingThread(self)
510 self.save_thread = HistorySavingThread(self)
496 self.save_thread.start()
511 self.save_thread.start()
497
512
498 self.new_session()
513 self.new_session()
499
514
500 def _get_hist_file_name(self, profile=None):
515 def _get_hist_file_name(self, profile=None):
501 """Get default history file name based on the Shell's profile.
516 """Get default history file name based on the Shell's profile.
502
517
503 The profile parameter is ignored, but must exist for compatibility with
518 The profile parameter is ignored, but must exist for compatibility with
504 the parent class."""
519 the parent class."""
505 profile_dir = self.shell.profile_dir.location
520 profile_dir = self.shell.profile_dir.location
506 return os.path.join(profile_dir, 'history.sqlite')
521 return os.path.join(profile_dir, 'history.sqlite')
507
522
508 @needs_sqlite
523 @needs_sqlite
509 def new_session(self, conn=None):
524 def new_session(self, conn=None):
510 """Get a new session number."""
525 """Get a new session number."""
511 if conn is None:
526 if conn is None:
512 conn = self.db
527 conn = self.db
513
528
514 with conn:
529 with conn:
515 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
530 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
516 NULL, "") """, (datetime.datetime.now(),))
531 NULL, "") """, (datetime.datetime.now(),))
517 self.session_number = cur.lastrowid
532 self.session_number = cur.lastrowid
518
533
519 def end_session(self):
534 def end_session(self):
520 """Close the database session, filling in the end time and line count."""
535 """Close the database session, filling in the end time and line count."""
521 self.writeout_cache()
536 self.writeout_cache()
522 with self.db:
537 with self.db:
523 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
538 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
524 session==?""", (datetime.datetime.now(),
539 session==?""", (datetime.datetime.now(),
525 len(self.input_hist_parsed)-1, self.session_number))
540 len(self.input_hist_parsed)-1, self.session_number))
526 self.session_number = 0
541 self.session_number = 0
527
542
528 def name_session(self, name):
543 def name_session(self, name):
529 """Give the current session a name in the history database."""
544 """Give the current session a name in the history database."""
530 with self.db:
545 with self.db:
531 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
546 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
532 (name, self.session_number))
547 (name, self.session_number))
533
548
534 def reset(self, new_session=True):
549 def reset(self, new_session=True):
535 """Clear the session history, releasing all object references, and
550 """Clear the session history, releasing all object references, and
536 optionally open a new session."""
551 optionally open a new session."""
537 self.output_hist.clear()
552 self.output_hist.clear()
538 # The directory history can't be completely empty
553 # The directory history can't be completely empty
539 self.dir_hist[:] = [py3compat.getcwd()]
554 self.dir_hist[:] = [py3compat.getcwd()]
540
555
541 if new_session:
556 if new_session:
542 if self.session_number:
557 if self.session_number:
543 self.end_session()
558 self.end_session()
544 self.input_hist_parsed[:] = [""]
559 self.input_hist_parsed[:] = [""]
545 self.input_hist_raw[:] = [""]
560 self.input_hist_raw[:] = [""]
546 self.new_session()
561 self.new_session()
547
562
548 # ------------------------------
563 # ------------------------------
549 # Methods for retrieving history
564 # Methods for retrieving history
550 # ------------------------------
565 # ------------------------------
551 def get_session_info(self, session=0):
566 def get_session_info(self, session=0):
552 """Get info about a session.
567 """Get info about a session.
553
568
554 Parameters
569 Parameters
555 ----------
570 ----------
556
571
557 session : int
572 session : int
558 Session number to retrieve. The current session is 0, and negative
573 Session number to retrieve. The current session is 0, and negative
559 numbers count back from current session, so -1 is the previous session.
574 numbers count back from current session, so -1 is the previous session.
560
575
561 Returns
576 Returns
562 -------
577 -------
563
578
564 session_id : int
579 session_id : int
565 Session ID number
580 Session ID number
566 start : datetime
581 start : datetime
567 Timestamp for the start of the session.
582 Timestamp for the start of the session.
568 end : datetime
583 end : datetime
569 Timestamp for the end of the session, or None if IPython crashed.
584 Timestamp for the end of the session, or None if IPython crashed.
570 num_cmds : int
585 num_cmds : int
571 Number of commands run, or None if IPython crashed.
586 Number of commands run, or None if IPython crashed.
572 remark : unicode
587 remark : unicode
573 A manually set description.
588 A manually set description.
574 """
589 """
575 if session <= 0:
590 if session <= 0:
576 session += self.session_number
591 session += self.session_number
577
592
578 return super(HistoryManager, self).get_session_info(session=session)
593 return super(HistoryManager, self).get_session_info(session=session)
579
594
580 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
595 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
581 """Get input and output history from the current session. Called by
596 """Get input and output history from the current session. Called by
582 get_range, and takes similar parameters."""
597 get_range, and takes similar parameters."""
583 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
598 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
584
599
585 n = len(input_hist)
600 n = len(input_hist)
586 if start < 0:
601 if start < 0:
587 start += n
602 start += n
588 if not stop or (stop > n):
603 if not stop or (stop > n):
589 stop = n
604 stop = n
590 elif stop < 0:
605 elif stop < 0:
591 stop += n
606 stop += n
592
607
593 for i in range(start, stop):
608 for i in range(start, stop):
594 if output:
609 if output:
595 line = (input_hist[i], self.output_hist_reprs.get(i))
610 line = (input_hist[i], self.output_hist_reprs.get(i))
596 else:
611 else:
597 line = input_hist[i]
612 line = input_hist[i]
598 yield (0, i, line)
613 yield (0, i, line)
599
614
600 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
615 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
601 """Retrieve input by session.
616 """Retrieve input by session.
602
617
603 Parameters
618 Parameters
604 ----------
619 ----------
605 session : int
620 session : int
606 Session number to retrieve. The current session is 0, and negative
621 Session number to retrieve. The current session is 0, and negative
607 numbers count back from current session, so -1 is previous session.
622 numbers count back from current session, so -1 is previous session.
608 start : int
623 start : int
609 First line to retrieve.
624 First line to retrieve.
610 stop : int
625 stop : int
611 End of line range (excluded from output itself). If None, retrieve
626 End of line range (excluded from output itself). If None, retrieve
612 to the end of the session.
627 to the end of the session.
613 raw : bool
628 raw : bool
614 If True, return untranslated input
629 If True, return untranslated input
615 output : bool
630 output : bool
616 If True, attempt to include output. This will be 'real' Python
631 If True, attempt to include output. This will be 'real' Python
617 objects for the current session, or text reprs from previous
632 objects for the current session, or text reprs from previous
618 sessions if db_log_output was enabled at the time. Where no output
633 sessions if db_log_output was enabled at the time. Where no output
619 is found, None is used.
634 is found, None is used.
620
635
621 Returns
636 Returns
622 -------
637 -------
623 entries
638 entries
624 An iterator over the desired lines. Each line is a 3-tuple, either
639 An iterator over the desired lines. Each line is a 3-tuple, either
625 (session, line, input) if output is False, or
640 (session, line, input) if output is False, or
626 (session, line, (input, output)) if output is True.
641 (session, line, (input, output)) if output is True.
627 """
642 """
628 if session <= 0:
643 if session <= 0:
629 session += self.session_number
644 session += self.session_number
630 if session==self.session_number: # Current session
645 if session==self.session_number: # Current session
631 return self._get_range_session(start, stop, raw, output)
646 return self._get_range_session(start, stop, raw, output)
632 return super(HistoryManager, self).get_range(session, start, stop, raw,
647 return super(HistoryManager, self).get_range(session, start, stop, raw,
633 output)
648 output)
634
649
635 ## ----------------------------
650 ## ----------------------------
636 ## Methods for storing history:
651 ## Methods for storing history:
637 ## ----------------------------
652 ## ----------------------------
638 def store_inputs(self, line_num, source, source_raw=None):
653 def store_inputs(self, line_num, source, source_raw=None):
639 """Store source and raw input in history and create input cache
654 """Store source and raw input in history and create input cache
640 variables ``_i*``.
655 variables ``_i*``.
641
656
642 Parameters
657 Parameters
643 ----------
658 ----------
644 line_num : int
659 line_num : int
645 The prompt number of this input.
660 The prompt number of this input.
646
661
647 source : str
662 source : str
648 Python input.
663 Python input.
649
664
650 source_raw : str, optional
665 source_raw : str, optional
651 If given, this is the raw input without any IPython transformations
666 If given, this is the raw input without any IPython transformations
652 applied to it. If not given, ``source`` is used.
667 applied to it. If not given, ``source`` is used.
653 """
668 """
654 if source_raw is None:
669 if source_raw is None:
655 source_raw = source
670 source_raw = source
656 source = source.rstrip('\n')
671 source = source.rstrip('\n')
657 source_raw = source_raw.rstrip('\n')
672 source_raw = source_raw.rstrip('\n')
658
673
659 # do not store exit/quit commands
674 # do not store exit/quit commands
660 if self._exit_re.match(source_raw.strip()):
675 if self._exit_re.match(source_raw.strip()):
661 return
676 return
662
677
663 self.input_hist_parsed.append(source)
678 self.input_hist_parsed.append(source)
664 self.input_hist_raw.append(source_raw)
679 self.input_hist_raw.append(source_raw)
665
680
666 with self.db_input_cache_lock:
681 with self.db_input_cache_lock:
667 self.db_input_cache.append((line_num, source, source_raw))
682 self.db_input_cache.append((line_num, source, source_raw))
668 # Trigger to flush cache and write to DB.
683 # Trigger to flush cache and write to DB.
669 if len(self.db_input_cache) >= self.db_cache_size:
684 if len(self.db_input_cache) >= self.db_cache_size:
670 self.save_flag.set()
685 self.save_flag.set()
671
686
672 # update the auto _i variables
687 # update the auto _i variables
673 self._iii = self._ii
688 self._iii = self._ii
674 self._ii = self._i
689 self._ii = self._i
675 self._i = self._i00
690 self._i = self._i00
676 self._i00 = source_raw
691 self._i00 = source_raw
677
692
678 # hackish access to user namespace to create _i1,_i2... dynamically
693 # hackish access to user namespace to create _i1,_i2... dynamically
679 new_i = '_i%s' % line_num
694 new_i = '_i%s' % line_num
680 to_main = {'_i': self._i,
695 to_main = {'_i': self._i,
681 '_ii': self._ii,
696 '_ii': self._ii,
682 '_iii': self._iii,
697 '_iii': self._iii,
683 new_i : self._i00 }
698 new_i : self._i00 }
684
699
685 if self.shell is not None:
700 if self.shell is not None:
686 self.shell.push(to_main, interactive=False)
701 self.shell.push(to_main, interactive=False)
687
702
688 def store_output(self, line_num):
703 def store_output(self, line_num):
689 """If database output logging is enabled, this saves all the
704 """If database output logging is enabled, this saves all the
690 outputs from the indicated prompt number to the database. It's
705 outputs from the indicated prompt number to the database. It's
691 called by run_cell after code has been executed.
706 called by run_cell after code has been executed.
692
707
693 Parameters
708 Parameters
694 ----------
709 ----------
695 line_num : int
710 line_num : int
696 The line number from which to save outputs
711 The line number from which to save outputs
697 """
712 """
698 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
713 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
699 return
714 return
700 output = self.output_hist_reprs[line_num]
715 output = self.output_hist_reprs[line_num]
701
716
702 with self.db_output_cache_lock:
717 with self.db_output_cache_lock:
703 self.db_output_cache.append((line_num, output))
718 self.db_output_cache.append((line_num, output))
704 if self.db_cache_size <= 1:
719 if self.db_cache_size <= 1:
705 self.save_flag.set()
720 self.save_flag.set()
706
721
707 def _writeout_input_cache(self, conn):
722 def _writeout_input_cache(self, conn):
708 with conn:
723 with conn:
709 for line in self.db_input_cache:
724 for line in self.db_input_cache:
710 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
725 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
711 (self.session_number,)+line)
726 (self.session_number,)+line)
712
727
713 def _writeout_output_cache(self, conn):
728 def _writeout_output_cache(self, conn):
714 with conn:
729 with conn:
715 for line in self.db_output_cache:
730 for line in self.db_output_cache:
716 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
731 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
717 (self.session_number,)+line)
732 (self.session_number,)+line)
718
733
719 @needs_sqlite
734 @needs_sqlite
720 def writeout_cache(self, conn=None):
735 def writeout_cache(self, conn=None):
721 """Write any entries in the cache to the database."""
736 """Write any entries in the cache to the database."""
722 if conn is None:
737 if conn is None:
723 conn = self.db
738 conn = self.db
724
739
725 with self.db_input_cache_lock:
740 with self.db_input_cache_lock:
726 try:
741 try:
727 self._writeout_input_cache(conn)
742 self._writeout_input_cache(conn)
728 except sqlite3.IntegrityError:
743 except sqlite3.IntegrityError:
729 self.new_session(conn)
744 self.new_session(conn)
730 print("ERROR! Session/line number was not unique in",
745 print("ERROR! Session/line number was not unique in",
731 "database. History logging moved to new session",
746 "database. History logging moved to new session",
732 self.session_number)
747 self.session_number)
733 try:
748 try:
734 # Try writing to the new session. If this fails, don't
749 # Try writing to the new session. If this fails, don't
735 # recurse
750 # recurse
736 self._writeout_input_cache(conn)
751 self._writeout_input_cache(conn)
737 except sqlite3.IntegrityError:
752 except sqlite3.IntegrityError:
738 pass
753 pass
739 finally:
754 finally:
740 self.db_input_cache = []
755 self.db_input_cache = []
741
756
742 with self.db_output_cache_lock:
757 with self.db_output_cache_lock:
743 try:
758 try:
744 self._writeout_output_cache(conn)
759 self._writeout_output_cache(conn)
745 except sqlite3.IntegrityError:
760 except sqlite3.IntegrityError:
746 print("!! Session/line number for output was not unique",
761 print("!! Session/line number for output was not unique",
747 "in database. Output will not be stored.")
762 "in database. Output will not be stored.")
748 finally:
763 finally:
749 self.db_output_cache = []
764 self.db_output_cache = []
750
765
751
766
752 class HistorySavingThread(threading.Thread):
767 class HistorySavingThread(threading.Thread):
753 """This thread takes care of writing history to the database, so that
768 """This thread takes care of writing history to the database, so that
754 the UI isn't held up while that happens.
769 the UI isn't held up while that happens.
755
770
756 It waits for the HistoryManager's save_flag to be set, then writes out
771 It waits for the HistoryManager's save_flag to be set, then writes out
757 the history cache. The main thread is responsible for setting the flag when
772 the history cache. The main thread is responsible for setting the flag when
758 the cache size reaches a defined threshold."""
773 the cache size reaches a defined threshold."""
759 daemon = True
774 daemon = True
760 stop_now = False
775 stop_now = False
761 enabled = True
776 enabled = True
762 def __init__(self, history_manager):
777 def __init__(self, history_manager):
763 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
778 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
764 self.history_manager = history_manager
779 self.history_manager = history_manager
765 self.enabled = history_manager.enabled
780 self.enabled = history_manager.enabled
766 atexit.register(self.stop)
781 atexit.register(self.stop)
767
782
768 @needs_sqlite
783 @needs_sqlite
769 def run(self):
784 def run(self):
770 # We need a separate db connection per thread:
785 # We need a separate db connection per thread:
771 try:
786 try:
772 self.db = sqlite3.connect(self.history_manager.hist_file,
787 self.db = sqlite3.connect(self.history_manager.hist_file,
773 **self.history_manager.connection_options
788 **self.history_manager.connection_options
774 )
789 )
775 while True:
790 while True:
776 self.history_manager.save_flag.wait()
791 self.history_manager.save_flag.wait()
777 if self.stop_now:
792 if self.stop_now:
778 self.db.close()
793 self.db.close()
779 return
794 return
780 self.history_manager.save_flag.clear()
795 self.history_manager.save_flag.clear()
781 self.history_manager.writeout_cache(self.db)
796 self.history_manager.writeout_cache(self.db)
782 except Exception as e:
797 except Exception as e:
783 print(("The history saving thread hit an unexpected error (%s)."
798 print(("The history saving thread hit an unexpected error (%s)."
784 "History will not be written to the database.") % repr(e))
799 "History will not be written to the database.") % repr(e))
785
800
786 def stop(self):
801 def stop(self):
787 """This can be called from the main thread to safely stop this thread.
802 """This can be called from the main thread to safely stop this thread.
788
803
789 Note that it does not attempt to write out remaining history before
804 Note that it does not attempt to write out remaining history before
790 exiting. That should be done by calling the HistoryManager's
805 exiting. That should be done by calling the HistoryManager's
791 end_session method."""
806 end_session method."""
792 self.stop_now = True
807 self.stop_now = True
793 self.history_manager.save_flag.set()
808 self.history_manager.save_flag.set()
794 self.join()
809 self.join()
795
810
796
811
797 # To match, e.g. ~5/8-~2/3
812 # To match, e.g. ~5/8-~2/3
798 range_re = re.compile(r"""
813 range_re = re.compile(r"""
799 ((?P<startsess>~?\d+)/)?
814 ((?P<startsess>~?\d+)/)?
800 (?P<start>\d+)?
815 (?P<start>\d+)?
801 ((?P<sep>[\-:])
816 ((?P<sep>[\-:])
802 ((?P<endsess>~?\d+)/)?
817 ((?P<endsess>~?\d+)/)?
803 (?P<end>\d+))?
818 (?P<end>\d+))?
804 $""", re.VERBOSE)
819 $""", re.VERBOSE)
805
820
806
821
807 def extract_hist_ranges(ranges_str):
822 def extract_hist_ranges(ranges_str):
808 """Turn a string of history ranges into 3-tuples of (session, start, stop).
823 """Turn a string of history ranges into 3-tuples of (session, start, stop).
809
824
810 Examples
825 Examples
811 --------
826 --------
812 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
827 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
813 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
828 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
814 """
829 """
815 for range_str in ranges_str.split():
830 for range_str in ranges_str.split():
816 rmatch = range_re.match(range_str)
831 rmatch = range_re.match(range_str)
817 if not rmatch:
832 if not rmatch:
818 continue
833 continue
819 start = rmatch.group("start")
834 start = rmatch.group("start")
820 if start:
835 if start:
821 start = int(start)
836 start = int(start)
822 end = rmatch.group("end")
837 end = rmatch.group("end")
823 # If no end specified, get (a, a + 1)
838 # If no end specified, get (a, a + 1)
824 end = int(end) if end else start + 1
839 end = int(end) if end else start + 1
825 else: # start not specified
840 else: # start not specified
826 if not rmatch.group('startsess'): # no startsess
841 if not rmatch.group('startsess'): # no startsess
827 continue
842 continue
828 start = 1
843 start = 1
829 end = None # provide the entire session hist
844 end = None # provide the entire session hist
830
845
831 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
846 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
832 end += 1
847 end += 1
833 startsess = rmatch.group("startsess") or "0"
848 startsess = rmatch.group("startsess") or "0"
834 endsess = rmatch.group("endsess") or startsess
849 endsess = rmatch.group("endsess") or startsess
835 startsess = int(startsess.replace("~","-"))
850 startsess = int(startsess.replace("~","-"))
836 endsess = int(endsess.replace("~","-"))
851 endsess = int(endsess.replace("~","-"))
837 assert endsess >= startsess, "start session must be earlier than end session"
852 assert endsess >= startsess, "start session must be earlier than end session"
838
853
839 if endsess == startsess:
854 if endsess == startsess:
840 yield (startsess, start, end)
855 yield (startsess, start, end)
841 continue
856 continue
842 # Multiple sessions in one range:
857 # Multiple sessions in one range:
843 yield (startsess, start, None)
858 yield (startsess, start, None)
844 for sess in range(startsess+1, endsess):
859 for sess in range(startsess+1, endsess):
845 yield (sess, 1, None)
860 yield (sess, 1, None)
846 yield (endsess, 1, end)
861 yield (endsess, 1, end)
847
862
848
863
849 def _format_lineno(session, line):
864 def _format_lineno(session, line):
850 """Helper function to format line numbers properly."""
865 """Helper function to format line numbers properly."""
851 if session == 0:
866 if session == 0:
852 return str(line)
867 return str(line)
853 return "%s#%s" % (session, line)
868 return "%s#%s" % (session, line)
854
869
855
870
@@ -1,638 +1,682 b''
1 """Input handling and transformation machinery.
1 """Input handling and transformation machinery.
2
2
3 The first class in this module, :class:`InputSplitter`, is designed to tell when
3 The first class in this module, :class:`InputSplitter`, is designed to tell when
4 input from a line-oriented frontend is complete and should be executed, and when
4 input from a line-oriented frontend is complete and should be executed, and when
5 the user should be prompted for another line of code instead. The name 'input
5 the user should be prompted for another line of code instead. The name 'input
6 splitter' is largely for historical reasons.
6 splitter' is largely for historical reasons.
7
7
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
9 with full support for the extended IPython syntax (magics, system calls, etc).
9 with full support for the extended IPython syntax (magics, system calls, etc).
10 The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
10 The code to actually do these transformations is in :mod:`IPython.core.inputtransformer`.
11 :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
11 :class:`IPythonInputSplitter` feeds the raw code to the transformers in order
12 and stores the results.
12 and stores the results.
13
13
14 For more details, see the class docstrings below.
14 For more details, see the class docstrings below.
15 """
15 """
16
16
17 # Copyright (c) IPython Development Team.
17 # Copyright (c) IPython Development Team.
18 # Distributed under the terms of the Modified BSD License.
18 # Distributed under the terms of the Modified BSD License.
19 import ast
19 import ast
20 import codeop
20 import codeop
21 import re
21 import re
22 import sys
22 import sys
23 import warnings
23
24
24 from IPython.utils.py3compat import cast_unicode
25 from IPython.utils.py3compat import cast_unicode
25 from IPython.core.inputtransformer import (leading_indent,
26 from IPython.core.inputtransformer import (leading_indent,
26 classic_prompt,
27 classic_prompt,
27 ipy_prompt,
28 ipy_prompt,
28 strip_encoding_cookie,
29 strip_encoding_cookie,
29 cellmagic,
30 cellmagic,
30 assemble_logical_lines,
31 assemble_logical_lines,
31 help_end,
32 help_end,
32 escaped_commands,
33 escaped_commands,
33 assign_from_magic,
34 assign_from_magic,
34 assign_from_system,
35 assign_from_system,
35 assemble_python_lines,
36 assemble_python_lines,
36 )
37 )
37
38
38 # These are available in this module for backwards compatibility.
39 # These are available in this module for backwards compatibility.
39 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
40 from IPython.core.inputtransformer import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
40 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
41 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
41 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
42 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN, ESC_SEQUENCES)
42
43
43 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
44 # Utilities
45 # Utilities
45 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
46
47
47 # FIXME: These are general-purpose utilities that later can be moved to the
48 # FIXME: These are general-purpose utilities that later can be moved to the
48 # general ward. Kept here for now because we're being very strict about test
49 # general ward. Kept here for now because we're being very strict about test
49 # coverage with this code, and this lets us ensure that we keep 100% coverage
50 # coverage with this code, and this lets us ensure that we keep 100% coverage
50 # while developing.
51 # while developing.
51
52
52 # compiled regexps for autoindent management
53 # compiled regexps for autoindent management
53 dedent_re = re.compile('|'.join([
54 dedent_re = re.compile('|'.join([
54 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
55 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
55 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
56 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
56 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
57 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
57 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
58 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
58 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
59 r'^\s+pass\s*$', # pass (optionally followed by trailing spaces)
59 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
60 r'^\s+break\s*$', # break (optionally followed by trailing spaces)
60 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
61 r'^\s+continue\s*$', # continue (optionally followed by trailing spaces)
61 ]))
62 ]))
62 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
63 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
63
64
64 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
65 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
65 # before pure comments
66 # before pure comments
66 comment_line_re = re.compile('^\s*\#')
67 comment_line_re = re.compile('^\s*\#')
67
68
68
69
69 def num_ini_spaces(s):
70 def num_ini_spaces(s):
70 """Return the number of initial spaces in a string.
71 """Return the number of initial spaces in a string.
71
72
72 Note that tabs are counted as a single space. For now, we do *not* support
73 Note that tabs are counted as a single space. For now, we do *not* support
73 mixing of tabs and spaces in the user's input.
74 mixing of tabs and spaces in the user's input.
74
75
75 Parameters
76 Parameters
76 ----------
77 ----------
77 s : string
78 s : string
78
79
79 Returns
80 Returns
80 -------
81 -------
81 n : int
82 n : int
82 """
83 """
83
84
84 ini_spaces = ini_spaces_re.match(s)
85 ini_spaces = ini_spaces_re.match(s)
85 if ini_spaces:
86 if ini_spaces:
86 return ini_spaces.end()
87 return ini_spaces.end()
87 else:
88 else:
88 return 0
89 return 0
89
90
90 def last_blank(src):
91 def last_blank(src):
91 """Determine if the input source ends in a blank.
92 """Determine if the input source ends in a blank.
92
93
93 A blank is either a newline or a line consisting of whitespace.
94 A blank is either a newline or a line consisting of whitespace.
94
95
95 Parameters
96 Parameters
96 ----------
97 ----------
97 src : string
98 src : string
98 A single or multiline string.
99 A single or multiline string.
99 """
100 """
100 if not src: return False
101 if not src: return False
101 ll = src.splitlines()[-1]
102 ll = src.splitlines()[-1]
102 return (ll == '') or ll.isspace()
103 return (ll == '') or ll.isspace()
103
104
104
105
105 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
106 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
106 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
107 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
107
108
108 def last_two_blanks(src):
109 def last_two_blanks(src):
109 """Determine if the input source ends in two blanks.
110 """Determine if the input source ends in two blanks.
110
111
111 A blank is either a newline or a line consisting of whitespace.
112 A blank is either a newline or a line consisting of whitespace.
112
113
113 Parameters
114 Parameters
114 ----------
115 ----------
115 src : string
116 src : string
116 A single or multiline string.
117 A single or multiline string.
117 """
118 """
118 if not src: return False
119 if not src: return False
119 # The logic here is tricky: I couldn't get a regexp to work and pass all
120 # The logic here is tricky: I couldn't get a regexp to work and pass all
120 # the tests, so I took a different approach: split the source by lines,
121 # the tests, so I took a different approach: split the source by lines,
121 # grab the last two and prepend '###\n' as a stand-in for whatever was in
122 # grab the last two and prepend '###\n' as a stand-in for whatever was in
122 # the body before the last two lines. Then, with that structure, it's
123 # the body before the last two lines. Then, with that structure, it's
123 # possible to analyze with two regexps. Not the most elegant solution, but
124 # possible to analyze with two regexps. Not the most elegant solution, but
124 # it works. If anyone tries to change this logic, make sure to validate
125 # it works. If anyone tries to change this logic, make sure to validate
125 # the whole test suite first!
126 # the whole test suite first!
126 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
127 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
127 return (bool(last_two_blanks_re.match(new_src)) or
128 return (bool(last_two_blanks_re.match(new_src)) or
128 bool(last_two_blanks_re2.match(new_src)) )
129 bool(last_two_blanks_re2.match(new_src)) )
129
130
130
131
131 def remove_comments(src):
132 def remove_comments(src):
132 """Remove all comments from input source.
133 """Remove all comments from input source.
133
134
134 Note: comments are NOT recognized inside of strings!
135 Note: comments are NOT recognized inside of strings!
135
136
136 Parameters
137 Parameters
137 ----------
138 ----------
138 src : string
139 src : string
139 A single or multiline input string.
140 A single or multiline input string.
140
141
141 Returns
142 Returns
142 -------
143 -------
143 String with all Python comments removed.
144 String with all Python comments removed.
144 """
145 """
145
146
146 return re.sub('#.*', '', src)
147 return re.sub('#.*', '', src)
147
148
148
149
149 def get_input_encoding():
150 def get_input_encoding():
150 """Return the default standard input encoding.
151 """Return the default standard input encoding.
151
152
152 If sys.stdin has no encoding, 'ascii' is returned."""
153 If sys.stdin has no encoding, 'ascii' is returned."""
153 # There are strange environments for which sys.stdin.encoding is None. We
154 # There are strange environments for which sys.stdin.encoding is None. We
154 # ensure that a valid encoding is returned.
155 # ensure that a valid encoding is returned.
155 encoding = getattr(sys.stdin, 'encoding', None)
156 encoding = getattr(sys.stdin, 'encoding', None)
156 if encoding is None:
157 if encoding is None:
157 encoding = 'ascii'
158 encoding = 'ascii'
158 return encoding
159 return encoding
159
160
160 #-----------------------------------------------------------------------------
161 #-----------------------------------------------------------------------------
161 # Classes and functions for normal Python syntax handling
162 # Classes and functions for normal Python syntax handling
162 #-----------------------------------------------------------------------------
163 #-----------------------------------------------------------------------------
163
164
164 class InputSplitter(object):
165 class InputSplitter(object):
165 r"""An object that can accumulate lines of Python source before execution.
166 r"""An object that can accumulate lines of Python source before execution.
166
167
167 This object is designed to be fed python source line-by-line, using
168 This object is designed to be fed python source line-by-line, using
168 :meth:`push`. It will return on each push whether the currently pushed
169 :meth:`push`. It will return on each push whether the currently pushed
169 code could be executed already. In addition, it provides a method called
170 code could be executed already. In addition, it provides a method called
170 :meth:`push_accepts_more` that can be used to query whether more input
171 :meth:`push_accepts_more` that can be used to query whether more input
171 can be pushed into a single interactive block.
172 can be pushed into a single interactive block.
172
173
173 This is a simple example of how an interactive terminal-based client can use
174 This is a simple example of how an interactive terminal-based client can use
174 this tool::
175 this tool::
175
176
176 isp = InputSplitter()
177 isp = InputSplitter()
177 while isp.push_accepts_more():
178 while isp.push_accepts_more():
178 indent = ' '*isp.indent_spaces
179 indent = ' '*isp.indent_spaces
179 prompt = '>>> ' + indent
180 prompt = '>>> ' + indent
180 line = indent + raw_input(prompt)
181 line = indent + raw_input(prompt)
181 isp.push(line)
182 isp.push(line)
182 print 'Input source was:\n', isp.source_reset(),
183 print 'Input source was:\n', isp.source_reset(),
183 """
184 """
184 # Number of spaces of indentation computed from input that has been pushed
185 # Number of spaces of indentation computed from input that has been pushed
185 # so far. This is the attributes callers should query to get the current
186 # so far. This is the attributes callers should query to get the current
186 # indentation level, in order to provide auto-indent facilities.
187 # indentation level, in order to provide auto-indent facilities.
187 indent_spaces = 0
188 indent_spaces = 0
188 # String, indicating the default input encoding. It is computed by default
189 # String, indicating the default input encoding. It is computed by default
189 # at initialization time via get_input_encoding(), but it can be reset by a
190 # at initialization time via get_input_encoding(), but it can be reset by a
190 # client with specific knowledge of the encoding.
191 # client with specific knowledge of the encoding.
191 encoding = ''
192 encoding = ''
192 # String where the current full source input is stored, properly encoded.
193 # String where the current full source input is stored, properly encoded.
193 # Reading this attribute is the normal way of querying the currently pushed
194 # Reading this attribute is the normal way of querying the currently pushed
194 # source code, that has been properly encoded.
195 # source code, that has been properly encoded.
195 source = ''
196 source = ''
196 # Code object corresponding to the current source. It is automatically
197 # Code object corresponding to the current source. It is automatically
197 # synced to the source, so it can be queried at any time to obtain the code
198 # synced to the source, so it can be queried at any time to obtain the code
198 # object; it will be None if the source doesn't compile to valid Python.
199 # object; it will be None if the source doesn't compile to valid Python.
199 code = None
200 code = None
200
201
201 # Private attributes
202 # Private attributes
202
203
203 # List with lines of input accumulated so far
204 # List with lines of input accumulated so far
204 _buffer = None
205 _buffer = None
205 # Command compiler
206 # Command compiler
206 _compile = None
207 _compile = None
207 # Mark when input has changed indentation all the way back to flush-left
208 # Mark when input has changed indentation all the way back to flush-left
208 _full_dedent = False
209 _full_dedent = False
209 # Boolean indicating whether the current block is complete
210 # Boolean indicating whether the current block is complete
210 _is_complete = None
211 _is_complete = None
212 # Boolean indicating whether the current block has an unrecoverable syntax error
213 _is_invalid = False
211
214
212 def __init__(self):
215 def __init__(self):
213 """Create a new InputSplitter instance.
216 """Create a new InputSplitter instance.
214 """
217 """
215 self._buffer = []
218 self._buffer = []
216 self._compile = codeop.CommandCompiler()
219 self._compile = codeop.CommandCompiler()
217 self.encoding = get_input_encoding()
220 self.encoding = get_input_encoding()
218
221
219 def reset(self):
222 def reset(self):
220 """Reset the input buffer and associated state."""
223 """Reset the input buffer and associated state."""
221 self.indent_spaces = 0
224 self.indent_spaces = 0
222 self._buffer[:] = []
225 self._buffer[:] = []
223 self.source = ''
226 self.source = ''
224 self.code = None
227 self.code = None
225 self._is_complete = False
228 self._is_complete = False
229 self._is_invalid = False
226 self._full_dedent = False
230 self._full_dedent = False
227
231
228 def source_reset(self):
232 def source_reset(self):
229 """Return the input source and perform a full reset.
233 """Return the input source and perform a full reset.
230 """
234 """
231 out = self.source
235 out = self.source
232 self.reset()
236 self.reset()
233 return out
237 return out
234
238
239 def check_complete(self, source):
240 """Return whether a block of code is ready to execute, or should be continued
241
242 This is a non-stateful API, and will reset the state of this InputSplitter.
243
244 Parameters
245 ----------
246 source : string
247 Python input code, which can be multiline.
248
249 Returns
250 -------
251 status : str
252 One of 'complete', 'incomplete', or 'invalid' if source is not a
253 prefix of valid code.
254 indent_spaces : int or None
255 The number of spaces by which to indent the next line of code. If
256 status is not 'incomplete', this is None.
257 """
258 self.reset()
259 try:
260 self.push(source)
261 except SyntaxError:
262 # Transformers in IPythonInputSplitter can raise SyntaxError,
263 # which push() will not catch.
264 return 'invalid', None
265 else:
266 if self._is_invalid:
267 return 'invalid', None
268 elif self.push_accepts_more():
269 return 'incomplete', self.indent_spaces
270 else:
271 return 'complete', None
272 finally:
273 self.reset()
274
235 def push(self, lines):
275 def push(self, lines):
236 """Push one or more lines of input.
276 """Push one or more lines of input.
237
277
238 This stores the given lines and returns a status code indicating
278 This stores the given lines and returns a status code indicating
239 whether the code forms a complete Python block or not.
279 whether the code forms a complete Python block or not.
240
280
241 Any exceptions generated in compilation are swallowed, but if an
281 Any exceptions generated in compilation are swallowed, but if an
242 exception was produced, the method returns True.
282 exception was produced, the method returns True.
243
283
244 Parameters
284 Parameters
245 ----------
285 ----------
246 lines : string
286 lines : string
247 One or more lines of Python input.
287 One or more lines of Python input.
248
288
249 Returns
289 Returns
250 -------
290 -------
251 is_complete : boolean
291 is_complete : boolean
252 True if the current input source (the result of the current input
292 True if the current input source (the result of the current input
253 plus prior inputs) forms a complete Python execution block. Note that
293 plus prior inputs) forms a complete Python execution block. Note that
254 this value is also stored as a private attribute (``_is_complete``), so it
294 this value is also stored as a private attribute (``_is_complete``), so it
255 can be queried at any time.
295 can be queried at any time.
256 """
296 """
257 self._store(lines)
297 self._store(lines)
258 source = self.source
298 source = self.source
259
299
260 # Before calling _compile(), reset the code object to None so that if an
300 # Before calling _compile(), reset the code object to None so that if an
261 # exception is raised in compilation, we don't mislead by having
301 # exception is raised in compilation, we don't mislead by having
262 # inconsistent code/source attributes.
302 # inconsistent code/source attributes.
263 self.code, self._is_complete = None, None
303 self.code, self._is_complete = None, None
304 self._is_invalid = False
264
305
265 # Honor termination lines properly
306 # Honor termination lines properly
266 if source.endswith('\\\n'):
307 if source.endswith('\\\n'):
267 return False
308 return False
268
309
269 self._update_indent(lines)
310 self._update_indent(lines)
270 try:
311 try:
271 self.code = self._compile(source, symbol="exec")
312 with warnings.catch_warnings():
313 warnings.simplefilter('error', SyntaxWarning)
314 self.code = self._compile(source, symbol="exec")
272 # Invalid syntax can produce any of a number of different errors from
315 # Invalid syntax can produce any of a number of different errors from
273 # inside the compiler, so we have to catch them all. Syntax errors
316 # inside the compiler, so we have to catch them all. Syntax errors
274 # immediately produce a 'ready' block, so the invalid Python can be
317 # immediately produce a 'ready' block, so the invalid Python can be
275 # sent to the kernel for evaluation with possible ipython
318 # sent to the kernel for evaluation with possible ipython
276 # special-syntax conversion.
319 # special-syntax conversion.
277 except (SyntaxError, OverflowError, ValueError, TypeError,
320 except (SyntaxError, OverflowError, ValueError, TypeError,
278 MemoryError):
321 MemoryError, SyntaxWarning):
279 self._is_complete = True
322 self._is_complete = True
323 self._is_invalid = True
280 else:
324 else:
281 # Compilation didn't produce any exceptions (though it may not have
325 # Compilation didn't produce any exceptions (though it may not have
282 # given a complete code object)
326 # given a complete code object)
283 self._is_complete = self.code is not None
327 self._is_complete = self.code is not None
284
328
285 return self._is_complete
329 return self._is_complete
286
330
287 def push_accepts_more(self):
331 def push_accepts_more(self):
288 """Return whether a block of interactive input can accept more input.
332 """Return whether a block of interactive input can accept more input.
289
333
290 This method is meant to be used by line-oriented frontends, who need to
334 This method is meant to be used by line-oriented frontends, who need to
291 guess whether a block is complete or not based solely on prior and
335 guess whether a block is complete or not based solely on prior and
292 current input lines. The InputSplitter considers it has a complete
336 current input lines. The InputSplitter considers it has a complete
293 interactive block and will not accept more input when either:
337 interactive block and will not accept more input when either:
294
338
295 * A SyntaxError is raised
339 * A SyntaxError is raised
296
340
297 * The code is complete and consists of a single line or a single
341 * The code is complete and consists of a single line or a single
298 non-compound statement
342 non-compound statement
299
343
300 * The code is complete and has a blank line at the end
344 * The code is complete and has a blank line at the end
301
345
302 If the current input produces a syntax error, this method immediately
346 If the current input produces a syntax error, this method immediately
303 returns False but does *not* raise the syntax error exception, as
347 returns False but does *not* raise the syntax error exception, as
304 typically clients will want to send invalid syntax to an execution
348 typically clients will want to send invalid syntax to an execution
305 backend which might convert the invalid syntax into valid Python via
349 backend which might convert the invalid syntax into valid Python via
306 one of the dynamic IPython mechanisms.
350 one of the dynamic IPython mechanisms.
307 """
351 """
308
352
309 # With incomplete input, unconditionally accept more
353 # With incomplete input, unconditionally accept more
310 # A syntax error also sets _is_complete to True - see push()
354 # A syntax error also sets _is_complete to True - see push()
311 if not self._is_complete:
355 if not self._is_complete:
312 #print("Not complete") # debug
356 #print("Not complete") # debug
313 return True
357 return True
314
358
315 # The user can make any (complete) input execute by leaving a blank line
359 # The user can make any (complete) input execute by leaving a blank line
316 last_line = self.source.splitlines()[-1]
360 last_line = self.source.splitlines()[-1]
317 if (not last_line) or last_line.isspace():
361 if (not last_line) or last_line.isspace():
318 #print("Blank line") # debug
362 #print("Blank line") # debug
319 return False
363 return False
320
364
321 # If there's just a single line or AST node, and we're flush left, as is
365 # If there's just a single line or AST node, and we're flush left, as is
322 # the case after a simple statement such as 'a=1', we want to execute it
366 # the case after a simple statement such as 'a=1', we want to execute it
323 # straight away.
367 # straight away.
324 if self.indent_spaces==0:
368 if self.indent_spaces==0:
325 if len(self.source.splitlines()) <= 1:
369 if len(self.source.splitlines()) <= 1:
326 return False
370 return False
327
371
328 try:
372 try:
329 code_ast = ast.parse(u''.join(self._buffer))
373 code_ast = ast.parse(u''.join(self._buffer))
330 except Exception:
374 except Exception:
331 #print("Can't parse AST") # debug
375 #print("Can't parse AST") # debug
332 return False
376 return False
333 else:
377 else:
334 if len(code_ast.body) == 1 and \
378 if len(code_ast.body) == 1 and \
335 not hasattr(code_ast.body[0], 'body'):
379 not hasattr(code_ast.body[0], 'body'):
336 #print("Simple statement") # debug
380 #print("Simple statement") # debug
337 return False
381 return False
338
382
339 # General fallback - accept more code
383 # General fallback - accept more code
340 return True
384 return True
341
385
342 #------------------------------------------------------------------------
386 #------------------------------------------------------------------------
343 # Private interface
387 # Private interface
344 #------------------------------------------------------------------------
388 #------------------------------------------------------------------------
345
389
346 def _find_indent(self, line):
390 def _find_indent(self, line):
347 """Compute the new indentation level for a single line.
391 """Compute the new indentation level for a single line.
348
392
349 Parameters
393 Parameters
350 ----------
394 ----------
351 line : str
395 line : str
352 A single new line of non-whitespace, non-comment Python input.
396 A single new line of non-whitespace, non-comment Python input.
353
397
354 Returns
398 Returns
355 -------
399 -------
356 indent_spaces : int
400 indent_spaces : int
357 New value for the indent level (it may be equal to self.indent_spaces
401 New value for the indent level (it may be equal to self.indent_spaces
358 if indentation doesn't change.
402 if indentation doesn't change.
359
403
360 full_dedent : boolean
404 full_dedent : boolean
361 Whether the new line causes a full flush-left dedent.
405 Whether the new line causes a full flush-left dedent.
362 """
406 """
363 indent_spaces = self.indent_spaces
407 indent_spaces = self.indent_spaces
364 full_dedent = self._full_dedent
408 full_dedent = self._full_dedent
365
409
366 inisp = num_ini_spaces(line)
410 inisp = num_ini_spaces(line)
367 if inisp < indent_spaces:
411 if inisp < indent_spaces:
368 indent_spaces = inisp
412 indent_spaces = inisp
369 if indent_spaces <= 0:
413 if indent_spaces <= 0:
370 #print 'Full dedent in text',self.source # dbg
414 #print 'Full dedent in text',self.source # dbg
371 full_dedent = True
415 full_dedent = True
372
416
373 if line.rstrip()[-1] == ':':
417 if line.rstrip()[-1] == ':':
374 indent_spaces += 4
418 indent_spaces += 4
375 elif dedent_re.match(line):
419 elif dedent_re.match(line):
376 indent_spaces -= 4
420 indent_spaces -= 4
377 if indent_spaces <= 0:
421 if indent_spaces <= 0:
378 full_dedent = True
422 full_dedent = True
379
423
380 # Safety
424 # Safety
381 if indent_spaces < 0:
425 if indent_spaces < 0:
382 indent_spaces = 0
426 indent_spaces = 0
383 #print 'safety' # dbg
427 #print 'safety' # dbg
384
428
385 return indent_spaces, full_dedent
429 return indent_spaces, full_dedent
386
430
387 def _update_indent(self, lines):
431 def _update_indent(self, lines):
388 for line in remove_comments(lines).splitlines():
432 for line in remove_comments(lines).splitlines():
389 if line and not line.isspace():
433 if line and not line.isspace():
390 self.indent_spaces, self._full_dedent = self._find_indent(line)
434 self.indent_spaces, self._full_dedent = self._find_indent(line)
391
435
392 def _store(self, lines, buffer=None, store='source'):
436 def _store(self, lines, buffer=None, store='source'):
393 """Store one or more lines of input.
437 """Store one or more lines of input.
394
438
395 If input lines are not newline-terminated, a newline is automatically
439 If input lines are not newline-terminated, a newline is automatically
396 appended."""
440 appended."""
397
441
398 if buffer is None:
442 if buffer is None:
399 buffer = self._buffer
443 buffer = self._buffer
400
444
401 if lines.endswith('\n'):
445 if lines.endswith('\n'):
402 buffer.append(lines)
446 buffer.append(lines)
403 else:
447 else:
404 buffer.append(lines+'\n')
448 buffer.append(lines+'\n')
405 setattr(self, store, self._set_source(buffer))
449 setattr(self, store, self._set_source(buffer))
406
450
407 def _set_source(self, buffer):
451 def _set_source(self, buffer):
408 return u''.join(buffer)
452 return u''.join(buffer)
409
453
410
454
411 class IPythonInputSplitter(InputSplitter):
455 class IPythonInputSplitter(InputSplitter):
412 """An input splitter that recognizes all of IPython's special syntax."""
456 """An input splitter that recognizes all of IPython's special syntax."""
413
457
414 # String with raw, untransformed input.
458 # String with raw, untransformed input.
415 source_raw = ''
459 source_raw = ''
416
460
417 # Flag to track when a transformer has stored input that it hasn't given
461 # Flag to track when a transformer has stored input that it hasn't given
418 # back yet.
462 # back yet.
419 transformer_accumulating = False
463 transformer_accumulating = False
420
464
421 # Flag to track when assemble_python_lines has stored input that it hasn't
465 # Flag to track when assemble_python_lines has stored input that it hasn't
422 # given back yet.
466 # given back yet.
423 within_python_line = False
467 within_python_line = False
424
468
425 # Private attributes
469 # Private attributes
426
470
427 # List with lines of raw input accumulated so far.
471 # List with lines of raw input accumulated so far.
428 _buffer_raw = None
472 _buffer_raw = None
429
473
430 def __init__(self, line_input_checker=True, physical_line_transforms=None,
474 def __init__(self, line_input_checker=True, physical_line_transforms=None,
431 logical_line_transforms=None, python_line_transforms=None):
475 logical_line_transforms=None, python_line_transforms=None):
432 super(IPythonInputSplitter, self).__init__()
476 super(IPythonInputSplitter, self).__init__()
433 self._buffer_raw = []
477 self._buffer_raw = []
434 self._validate = True
478 self._validate = True
435
479
436 if physical_line_transforms is not None:
480 if physical_line_transforms is not None:
437 self.physical_line_transforms = physical_line_transforms
481 self.physical_line_transforms = physical_line_transforms
438 else:
482 else:
439 self.physical_line_transforms = [
483 self.physical_line_transforms = [
440 leading_indent(),
484 leading_indent(),
441 classic_prompt(),
485 classic_prompt(),
442 ipy_prompt(),
486 ipy_prompt(),
443 strip_encoding_cookie(),
487 strip_encoding_cookie(),
444 cellmagic(end_on_blank_line=line_input_checker),
488 cellmagic(end_on_blank_line=line_input_checker),
445 ]
489 ]
446
490
447 self.assemble_logical_lines = assemble_logical_lines()
491 self.assemble_logical_lines = assemble_logical_lines()
448 if logical_line_transforms is not None:
492 if logical_line_transforms is not None:
449 self.logical_line_transforms = logical_line_transforms
493 self.logical_line_transforms = logical_line_transforms
450 else:
494 else:
451 self.logical_line_transforms = [
495 self.logical_line_transforms = [
452 help_end(),
496 help_end(),
453 escaped_commands(),
497 escaped_commands(),
454 assign_from_magic(),
498 assign_from_magic(),
455 assign_from_system(),
499 assign_from_system(),
456 ]
500 ]
457
501
458 self.assemble_python_lines = assemble_python_lines()
502 self.assemble_python_lines = assemble_python_lines()
459 if python_line_transforms is not None:
503 if python_line_transforms is not None:
460 self.python_line_transforms = python_line_transforms
504 self.python_line_transforms = python_line_transforms
461 else:
505 else:
462 # We don't use any of these at present
506 # We don't use any of these at present
463 self.python_line_transforms = []
507 self.python_line_transforms = []
464
508
465 @property
509 @property
466 def transforms(self):
510 def transforms(self):
467 "Quick access to all transformers."
511 "Quick access to all transformers."
468 return self.physical_line_transforms + \
512 return self.physical_line_transforms + \
469 [self.assemble_logical_lines] + self.logical_line_transforms + \
513 [self.assemble_logical_lines] + self.logical_line_transforms + \
470 [self.assemble_python_lines] + self.python_line_transforms
514 [self.assemble_python_lines] + self.python_line_transforms
471
515
472 @property
516 @property
473 def transforms_in_use(self):
517 def transforms_in_use(self):
474 """Transformers, excluding logical line transformers if we're in a
518 """Transformers, excluding logical line transformers if we're in a
475 Python line."""
519 Python line."""
476 t = self.physical_line_transforms[:]
520 t = self.physical_line_transforms[:]
477 if not self.within_python_line:
521 if not self.within_python_line:
478 t += [self.assemble_logical_lines] + self.logical_line_transforms
522 t += [self.assemble_logical_lines] + self.logical_line_transforms
479 return t + [self.assemble_python_lines] + self.python_line_transforms
523 return t + [self.assemble_python_lines] + self.python_line_transforms
480
524
481 def reset(self):
525 def reset(self):
482 """Reset the input buffer and associated state."""
526 """Reset the input buffer and associated state."""
483 super(IPythonInputSplitter, self).reset()
527 super(IPythonInputSplitter, self).reset()
484 self._buffer_raw[:] = []
528 self._buffer_raw[:] = []
485 self.source_raw = ''
529 self.source_raw = ''
486 self.transformer_accumulating = False
530 self.transformer_accumulating = False
487 self.within_python_line = False
531 self.within_python_line = False
488
532
489 for t in self.transforms:
533 for t in self.transforms:
490 try:
534 try:
491 t.reset()
535 t.reset()
492 except SyntaxError:
536 except SyntaxError:
493 # Nothing that calls reset() expects to handle transformer
537 # Nothing that calls reset() expects to handle transformer
494 # errors
538 # errors
495 pass
539 pass
496
540
497 def flush_transformers(self):
541 def flush_transformers(self):
498 def _flush(transform, outs):
542 def _flush(transform, outs):
499 """yield transformed lines
543 """yield transformed lines
500
544
501 always strings, never None
545 always strings, never None
502
546
503 transform: the current transform
547 transform: the current transform
504 outs: an iterable of previously transformed inputs.
548 outs: an iterable of previously transformed inputs.
505 Each may be multiline, which will be passed
549 Each may be multiline, which will be passed
506 one line at a time to transform.
550 one line at a time to transform.
507 """
551 """
508 for out in outs:
552 for out in outs:
509 for line in out.splitlines():
553 for line in out.splitlines():
510 # push one line at a time
554 # push one line at a time
511 tmp = transform.push(line)
555 tmp = transform.push(line)
512 if tmp is not None:
556 if tmp is not None:
513 yield tmp
557 yield tmp
514
558
515 # reset the transform
559 # reset the transform
516 tmp = transform.reset()
560 tmp = transform.reset()
517 if tmp is not None:
561 if tmp is not None:
518 yield tmp
562 yield tmp
519
563
520 out = []
564 out = []
521 for t in self.transforms_in_use:
565 for t in self.transforms_in_use:
522 out = _flush(t, out)
566 out = _flush(t, out)
523
567
524 out = list(out)
568 out = list(out)
525 if out:
569 if out:
526 self._store('\n'.join(out))
570 self._store('\n'.join(out))
527
571
528 def raw_reset(self):
572 def raw_reset(self):
529 """Return raw input only and perform a full reset.
573 """Return raw input only and perform a full reset.
530 """
574 """
531 out = self.source_raw
575 out = self.source_raw
532 self.reset()
576 self.reset()
533 return out
577 return out
534
578
535 def source_reset(self):
579 def source_reset(self):
536 try:
580 try:
537 self.flush_transformers()
581 self.flush_transformers()
538 return self.source
582 return self.source
539 finally:
583 finally:
540 self.reset()
584 self.reset()
541
585
542 def push_accepts_more(self):
586 def push_accepts_more(self):
543 if self.transformer_accumulating:
587 if self.transformer_accumulating:
544 return True
588 return True
545 else:
589 else:
546 return super(IPythonInputSplitter, self).push_accepts_more()
590 return super(IPythonInputSplitter, self).push_accepts_more()
547
591
548 def transform_cell(self, cell):
592 def transform_cell(self, cell):
549 """Process and translate a cell of input.
593 """Process and translate a cell of input.
550 """
594 """
551 self.reset()
595 self.reset()
552 try:
596 try:
553 self.push(cell)
597 self.push(cell)
554 self.flush_transformers()
598 self.flush_transformers()
555 return self.source
599 return self.source
556 finally:
600 finally:
557 self.reset()
601 self.reset()
558
602
559 def push(self, lines):
603 def push(self, lines):
560 """Push one or more lines of IPython input.
604 """Push one or more lines of IPython input.
561
605
562 This stores the given lines and returns a status code indicating
606 This stores the given lines and returns a status code indicating
563 whether the code forms a complete Python block or not, after processing
607 whether the code forms a complete Python block or not, after processing
564 all input lines for special IPython syntax.
608 all input lines for special IPython syntax.
565
609
566 Any exceptions generated in compilation are swallowed, but if an
610 Any exceptions generated in compilation are swallowed, but if an
567 exception was produced, the method returns True.
611 exception was produced, the method returns True.
568
612
569 Parameters
613 Parameters
570 ----------
614 ----------
571 lines : string
615 lines : string
572 One or more lines of Python input.
616 One or more lines of Python input.
573
617
574 Returns
618 Returns
575 -------
619 -------
576 is_complete : boolean
620 is_complete : boolean
577 True if the current input source (the result of the current input
621 True if the current input source (the result of the current input
578 plus prior inputs) forms a complete Python execution block. Note that
622 plus prior inputs) forms a complete Python execution block. Note that
579 this value is also stored as a private attribute (_is_complete), so it
623 this value is also stored as a private attribute (_is_complete), so it
580 can be queried at any time.
624 can be queried at any time.
581 """
625 """
582
626
583 # We must ensure all input is pure unicode
627 # We must ensure all input is pure unicode
584 lines = cast_unicode(lines, self.encoding)
628 lines = cast_unicode(lines, self.encoding)
585
629
586 # ''.splitlines() --> [], but we need to push the empty line to transformers
630 # ''.splitlines() --> [], but we need to push the empty line to transformers
587 lines_list = lines.splitlines()
631 lines_list = lines.splitlines()
588 if not lines_list:
632 if not lines_list:
589 lines_list = ['']
633 lines_list = ['']
590
634
591 # Store raw source before applying any transformations to it. Note
635 # Store raw source before applying any transformations to it. Note
592 # that this must be done *after* the reset() call that would otherwise
636 # that this must be done *after* the reset() call that would otherwise
593 # flush the buffer.
637 # flush the buffer.
594 self._store(lines, self._buffer_raw, 'source_raw')
638 self._store(lines, self._buffer_raw, 'source_raw')
595
639
596 for line in lines_list:
640 for line in lines_list:
597 out = self.push_line(line)
641 out = self.push_line(line)
598
642
599 return out
643 return out
600
644
601 def push_line(self, line):
645 def push_line(self, line):
602 buf = self._buffer
646 buf = self._buffer
603
647
604 def _accumulating(dbg):
648 def _accumulating(dbg):
605 #print(dbg)
649 #print(dbg)
606 self.transformer_accumulating = True
650 self.transformer_accumulating = True
607 return False
651 return False
608
652
609 for transformer in self.physical_line_transforms:
653 for transformer in self.physical_line_transforms:
610 line = transformer.push(line)
654 line = transformer.push(line)
611 if line is None:
655 if line is None:
612 return _accumulating(transformer)
656 return _accumulating(transformer)
613
657
614 if not self.within_python_line:
658 if not self.within_python_line:
615 line = self.assemble_logical_lines.push(line)
659 line = self.assemble_logical_lines.push(line)
616 if line is None:
660 if line is None:
617 return _accumulating('acc logical line')
661 return _accumulating('acc logical line')
618
662
619 for transformer in self.logical_line_transforms:
663 for transformer in self.logical_line_transforms:
620 line = transformer.push(line)
664 line = transformer.push(line)
621 if line is None:
665 if line is None:
622 return _accumulating(transformer)
666 return _accumulating(transformer)
623
667
624 line = self.assemble_python_lines.push(line)
668 line = self.assemble_python_lines.push(line)
625 if line is None:
669 if line is None:
626 self.within_python_line = True
670 self.within_python_line = True
627 return _accumulating('acc python line')
671 return _accumulating('acc python line')
628 else:
672 else:
629 self.within_python_line = False
673 self.within_python_line = False
630
674
631 for transformer in self.python_line_transforms:
675 for transformer in self.python_line_transforms:
632 line = transformer.push(line)
676 line = transformer.push(line)
633 if line is None:
677 if line is None:
634 return _accumulating(transformer)
678 return _accumulating(transformer)
635
679
636 #print("transformers clear") #debug
680 #print("transformers clear") #debug
637 self.transformer_accumulating = False
681 self.transformer_accumulating = False
638 return super(IPythonInputSplitter, self).push(line)
682 return super(IPythonInputSplitter, self).push(line)
@@ -1,549 +1,549 b''
1 """Input transformer classes to support IPython special syntax.
1 """Input transformer classes to support IPython special syntax.
2
2
3 This includes the machinery to recognise and transform ``%magic`` commands,
3 This includes the machinery to recognise and transform ``%magic`` commands,
4 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
4 ``!system`` commands, ``help?`` querying, prompt stripping, and so forth.
5 """
5 """
6 import abc
6 import abc
7 import functools
7 import functools
8 import re
8 import re
9
9
10 from IPython.core.splitinput import LineInfo
10 from IPython.core.splitinput import LineInfo
11 from IPython.utils import tokenize2
11 from IPython.utils import tokenize2
12 from IPython.utils.openpy import cookie_comment_re
12 from IPython.utils.openpy import cookie_comment_re
13 from IPython.utils.py3compat import with_metaclass, PY3
13 from IPython.utils.py3compat import with_metaclass, PY3
14 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
14 from IPython.utils.tokenize2 import generate_tokens, untokenize, TokenError
15
15
16 if PY3:
16 if PY3:
17 from io import StringIO
17 from io import StringIO
18 else:
18 else:
19 from StringIO import StringIO
19 from StringIO import StringIO
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Globals
22 # Globals
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 # The escape sequences that define the syntax transformations IPython will
25 # The escape sequences that define the syntax transformations IPython will
26 # apply to user input. These can NOT be just changed here: many regular
26 # apply to user input. These can NOT be just changed here: many regular
27 # expressions and other parts of the code may use their hardcoded values, and
27 # expressions and other parts of the code may use their hardcoded values, and
28 # for all intents and purposes they constitute the 'IPython syntax', so they
28 # for all intents and purposes they constitute the 'IPython syntax', so they
29 # should be considered fixed.
29 # should be considered fixed.
30
30
31 ESC_SHELL = '!' # Send line to underlying system shell
31 ESC_SHELL = '!' # Send line to underlying system shell
32 ESC_SH_CAP = '!!' # Send line to system shell and capture output
32 ESC_SH_CAP = '!!' # Send line to system shell and capture output
33 ESC_HELP = '?' # Find information about object
33 ESC_HELP = '?' # Find information about object
34 ESC_HELP2 = '??' # Find extra-detailed information about object
34 ESC_HELP2 = '??' # Find extra-detailed information about object
35 ESC_MAGIC = '%' # Call magic function
35 ESC_MAGIC = '%' # Call magic function
36 ESC_MAGIC2 = '%%' # Call cell-magic function
36 ESC_MAGIC2 = '%%' # Call cell-magic function
37 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
37 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
38 ESC_QUOTE2 = ';' # Quote all args as a single string, call
38 ESC_QUOTE2 = ';' # Quote all args as a single string, call
39 ESC_PAREN = '/' # Call first argument with rest of line as arguments
39 ESC_PAREN = '/' # Call first argument with rest of line as arguments
40
40
41 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
41 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
42 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
42 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
43 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
43 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
44
44
45
45
46 class InputTransformer(with_metaclass(abc.ABCMeta, object)):
46 class InputTransformer(with_metaclass(abc.ABCMeta, object)):
47 """Abstract base class for line-based input transformers."""
47 """Abstract base class for line-based input transformers."""
48
48
49 @abc.abstractmethod
49 @abc.abstractmethod
50 def push(self, line):
50 def push(self, line):
51 """Send a line of input to the transformer, returning the transformed
51 """Send a line of input to the transformer, returning the transformed
52 input or None if the transformer is waiting for more input.
52 input or None if the transformer is waiting for more input.
53
53
54 Must be overridden by subclasses.
54 Must be overridden by subclasses.
55
55
56 Implementations may raise ``SyntaxError`` if the input is invalid. No
56 Implementations may raise ``SyntaxError`` if the input is invalid. No
57 other exceptions may be raised.
57 other exceptions may be raised.
58 """
58 """
59 pass
59 pass
60
60
61 @abc.abstractmethod
61 @abc.abstractmethod
62 def reset(self):
62 def reset(self):
63 """Return, transformed any lines that the transformer has accumulated,
63 """Return, transformed any lines that the transformer has accumulated,
64 and reset its internal state.
64 and reset its internal state.
65
65
66 Must be overridden by subclasses.
66 Must be overridden by subclasses.
67 """
67 """
68 pass
68 pass
69
69
70 @classmethod
70 @classmethod
71 def wrap(cls, func):
71 def wrap(cls, func):
72 """Can be used by subclasses as a decorator, to return a factory that
72 """Can be used by subclasses as a decorator, to return a factory that
73 will allow instantiation with the decorated object.
73 will allow instantiation with the decorated object.
74 """
74 """
75 @functools.wraps(func)
75 @functools.wraps(func)
76 def transformer_factory(**kwargs):
76 def transformer_factory(**kwargs):
77 return cls(func, **kwargs)
77 return cls(func, **kwargs)
78
78
79 return transformer_factory
79 return transformer_factory
80
80
81 class StatelessInputTransformer(InputTransformer):
81 class StatelessInputTransformer(InputTransformer):
82 """Wrapper for a stateless input transformer implemented as a function."""
82 """Wrapper for a stateless input transformer implemented as a function."""
83 def __init__(self, func):
83 def __init__(self, func):
84 self.func = func
84 self.func = func
85
85
86 def __repr__(self):
86 def __repr__(self):
87 return "StatelessInputTransformer(func={0!r})".format(self.func)
87 return "StatelessInputTransformer(func={0!r})".format(self.func)
88
88
89 def push(self, line):
89 def push(self, line):
90 """Send a line of input to the transformer, returning the
90 """Send a line of input to the transformer, returning the
91 transformed input."""
91 transformed input."""
92 return self.func(line)
92 return self.func(line)
93
93
94 def reset(self):
94 def reset(self):
95 """No-op - exists for compatibility."""
95 """No-op - exists for compatibility."""
96 pass
96 pass
97
97
98 class CoroutineInputTransformer(InputTransformer):
98 class CoroutineInputTransformer(InputTransformer):
99 """Wrapper for an input transformer implemented as a coroutine."""
99 """Wrapper for an input transformer implemented as a coroutine."""
100 def __init__(self, coro, **kwargs):
100 def __init__(self, coro, **kwargs):
101 # Prime it
101 # Prime it
102 self.coro = coro(**kwargs)
102 self.coro = coro(**kwargs)
103 next(self.coro)
103 next(self.coro)
104
104
105 def __repr__(self):
105 def __repr__(self):
106 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
106 return "CoroutineInputTransformer(coro={0!r})".format(self.coro)
107
107
108 def push(self, line):
108 def push(self, line):
109 """Send a line of input to the transformer, returning the
109 """Send a line of input to the transformer, returning the
110 transformed input or None if the transformer is waiting for more
110 transformed input or None if the transformer is waiting for more
111 input.
111 input.
112 """
112 """
113 return self.coro.send(line)
113 return self.coro.send(line)
114
114
115 def reset(self):
115 def reset(self):
116 """Return, transformed any lines that the transformer has
116 """Return, transformed any lines that the transformer has
117 accumulated, and reset its internal state.
117 accumulated, and reset its internal state.
118 """
118 """
119 return self.coro.send(None)
119 return self.coro.send(None)
120
120
121 class TokenInputTransformer(InputTransformer):
121 class TokenInputTransformer(InputTransformer):
122 """Wrapper for a token-based input transformer.
122 """Wrapper for a token-based input transformer.
123
123
124 func should accept a list of tokens (5-tuples, see tokenize docs), and
124 func should accept a list of tokens (5-tuples, see tokenize docs), and
125 return an iterable which can be passed to tokenize.untokenize().
125 return an iterable which can be passed to tokenize.untokenize().
126 """
126 """
127 def __init__(self, func):
127 def __init__(self, func):
128 self.func = func
128 self.func = func
129 self.current_line = ""
129 self.current_line = ""
130 self.line_used = False
130 self.line_used = False
131 self.reset_tokenizer()
131 self.reset_tokenizer()
132
132
133 def reset_tokenizer(self):
133 def reset_tokenizer(self):
134 self.tokenizer = generate_tokens(self.get_line)
134 self.tokenizer = generate_tokens(self.get_line)
135
135
136 def get_line(self):
136 def get_line(self):
137 if self.line_used:
137 if self.line_used:
138 raise TokenError
138 raise TokenError
139 self.line_used = True
139 self.line_used = True
140 return self.current_line
140 return self.current_line
141
141
142 def push(self, line):
142 def push(self, line):
143 self.current_line += line + "\n"
143 self.current_line += line + "\n"
144 if self.current_line.isspace():
144 if self.current_line.isspace():
145 return self.reset()
145 return self.reset()
146
146
147 self.line_used = False
147 self.line_used = False
148 tokens = []
148 tokens = []
149 stop_at_NL = False
149 stop_at_NL = False
150 try:
150 try:
151 for intok in self.tokenizer:
151 for intok in self.tokenizer:
152 tokens.append(intok)
152 tokens.append(intok)
153 t = intok[0]
153 t = intok[0]
154 if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
154 if t == tokenize2.NEWLINE or (stop_at_NL and t == tokenize2.NL):
155 # Stop before we try to pull a line we don't have yet
155 # Stop before we try to pull a line we don't have yet
156 break
156 break
157 elif t == tokenize2.ERRORTOKEN:
157 elif t == tokenize2.ERRORTOKEN:
158 stop_at_NL = True
158 stop_at_NL = True
159 except TokenError:
159 except TokenError:
160 # Multi-line statement - stop and try again with the next line
160 # Multi-line statement - stop and try again with the next line
161 self.reset_tokenizer()
161 self.reset_tokenizer()
162 return None
162 return None
163
163
164 return self.output(tokens)
164 return self.output(tokens)
165
165
166 def output(self, tokens):
166 def output(self, tokens):
167 self.current_line = ""
167 self.current_line = ""
168 self.reset_tokenizer()
168 self.reset_tokenizer()
169 return untokenize(self.func(tokens)).rstrip('\n')
169 return untokenize(self.func(tokens)).rstrip('\n')
170
170
171 def reset(self):
171 def reset(self):
172 l = self.current_line
172 l = self.current_line
173 self.current_line = ""
173 self.current_line = ""
174 self.reset_tokenizer()
174 self.reset_tokenizer()
175 if l:
175 if l:
176 return l.rstrip('\n')
176 return l.rstrip('\n')
177
177
178 class assemble_python_lines(TokenInputTransformer):
178 class assemble_python_lines(TokenInputTransformer):
179 def __init__(self):
179 def __init__(self):
180 super(assemble_python_lines, self).__init__(None)
180 super(assemble_python_lines, self).__init__(None)
181
181
182 def output(self, tokens):
182 def output(self, tokens):
183 return self.reset()
183 return self.reset()
184
184
185 @CoroutineInputTransformer.wrap
185 @CoroutineInputTransformer.wrap
186 def assemble_logical_lines():
186 def assemble_logical_lines():
187 """Join lines following explicit line continuations (\)"""
187 """Join lines following explicit line continuations (\)"""
188 line = ''
188 line = ''
189 while True:
189 while True:
190 line = (yield line)
190 line = (yield line)
191 if not line or line.isspace():
191 if not line or line.isspace():
192 continue
192 continue
193
193
194 parts = []
194 parts = []
195 while line is not None:
195 while line is not None:
196 if line.endswith('\\') and (not has_comment(line)):
196 if line.endswith('\\') and (not has_comment(line)):
197 parts.append(line[:-1])
197 parts.append(line[:-1])
198 line = (yield None) # Get another line
198 line = (yield None) # Get another line
199 else:
199 else:
200 parts.append(line)
200 parts.append(line)
201 break
201 break
202
202
203 # Output
203 # Output
204 line = ''.join(parts)
204 line = ''.join(parts)
205
205
206 # Utilities
206 # Utilities
207 def _make_help_call(target, esc, lspace, next_input=None):
207 def _make_help_call(target, esc, lspace, next_input=None):
208 """Prepares a pinfo(2)/psearch call from a target name and the escape
208 """Prepares a pinfo(2)/psearch call from a target name and the escape
209 (i.e. ? or ??)"""
209 (i.e. ? or ??)"""
210 method = 'pinfo2' if esc == '??' \
210 method = 'pinfo2' if esc == '??' \
211 else 'psearch' if '*' in target \
211 else 'psearch' if '*' in target \
212 else 'pinfo'
212 else 'pinfo'
213 arg = " ".join([method, target])
213 arg = " ".join([method, target])
214 if next_input is None:
214 if next_input is None:
215 return '%sget_ipython().magic(%r)' % (lspace, arg)
215 return '%sget_ipython().magic(%r)' % (lspace, arg)
216 else:
216 else:
217 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
217 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
218 (lspace, next_input, arg)
218 (lspace, next_input, arg)
219
219
220 # These define the transformations for the different escape characters.
220 # These define the transformations for the different escape characters.
221 def _tr_system(line_info):
221 def _tr_system(line_info):
222 "Translate lines escaped with: !"
222 "Translate lines escaped with: !"
223 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
223 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
224 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
224 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
225
225
226 def _tr_system2(line_info):
226 def _tr_system2(line_info):
227 "Translate lines escaped with: !!"
227 "Translate lines escaped with: !!"
228 cmd = line_info.line.lstrip()[2:]
228 cmd = line_info.line.lstrip()[2:]
229 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
229 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
230
230
231 def _tr_help(line_info):
231 def _tr_help(line_info):
232 "Translate lines escaped with: ?/??"
232 "Translate lines escaped with: ?/??"
233 # A naked help line should just fire the intro help screen
233 # A naked help line should just fire the intro help screen
234 if not line_info.line[1:]:
234 if not line_info.line[1:]:
235 return 'get_ipython().show_usage()'
235 return 'get_ipython().show_usage()'
236
236
237 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
237 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
238
238
239 def _tr_magic(line_info):
239 def _tr_magic(line_info):
240 "Translate lines escaped with: %"
240 "Translate lines escaped with: %"
241 tpl = '%sget_ipython().magic(%r)'
241 tpl = '%sget_ipython().magic(%r)'
242 if line_info.line.startswith(ESC_MAGIC2):
242 if line_info.line.startswith(ESC_MAGIC2):
243 return line_info.line
243 return line_info.line
244 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
244 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
245 return tpl % (line_info.pre, cmd)
245 return tpl % (line_info.pre, cmd)
246
246
247 def _tr_quote(line_info):
247 def _tr_quote(line_info):
248 "Translate lines escaped with: ,"
248 "Translate lines escaped with: ,"
249 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
249 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
250 '", "'.join(line_info.the_rest.split()) )
250 '", "'.join(line_info.the_rest.split()) )
251
251
252 def _tr_quote2(line_info):
252 def _tr_quote2(line_info):
253 "Translate lines escaped with: ;"
253 "Translate lines escaped with: ;"
254 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
254 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
255 line_info.the_rest)
255 line_info.the_rest)
256
256
257 def _tr_paren(line_info):
257 def _tr_paren(line_info):
258 "Translate lines escaped with: /"
258 "Translate lines escaped with: /"
259 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
259 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
260 ", ".join(line_info.the_rest.split()))
260 ", ".join(line_info.the_rest.split()))
261
261
262 tr = { ESC_SHELL : _tr_system,
262 tr = { ESC_SHELL : _tr_system,
263 ESC_SH_CAP : _tr_system2,
263 ESC_SH_CAP : _tr_system2,
264 ESC_HELP : _tr_help,
264 ESC_HELP : _tr_help,
265 ESC_HELP2 : _tr_help,
265 ESC_HELP2 : _tr_help,
266 ESC_MAGIC : _tr_magic,
266 ESC_MAGIC : _tr_magic,
267 ESC_QUOTE : _tr_quote,
267 ESC_QUOTE : _tr_quote,
268 ESC_QUOTE2 : _tr_quote2,
268 ESC_QUOTE2 : _tr_quote2,
269 ESC_PAREN : _tr_paren }
269 ESC_PAREN : _tr_paren }
270
270
271 @StatelessInputTransformer.wrap
271 @StatelessInputTransformer.wrap
272 def escaped_commands(line):
272 def escaped_commands(line):
273 """Transform escaped commands - %magic, !system, ?help + various autocalls.
273 """Transform escaped commands - %magic, !system, ?help + various autocalls.
274 """
274 """
275 if not line or line.isspace():
275 if not line or line.isspace():
276 return line
276 return line
277 lineinf = LineInfo(line)
277 lineinf = LineInfo(line)
278 if lineinf.esc not in tr:
278 if lineinf.esc not in tr:
279 return line
279 return line
280
280
281 return tr[lineinf.esc](lineinf)
281 return tr[lineinf.esc](lineinf)
282
282
283 _initial_space_re = re.compile(r'\s*')
283 _initial_space_re = re.compile(r'\s*')
284
284
285 _help_end_re = re.compile(r"""(%{0,2}
285 _help_end_re = re.compile(r"""(%{0,2}
286 [a-zA-Z_*][\w*]* # Variable name
286 [a-zA-Z_*][\w*]* # Variable name
287 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
287 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
288 )
288 )
289 (\?\??)$ # ? or ??
289 (\?\??)$ # ? or ??
290 """,
290 """,
291 re.VERBOSE)
291 re.VERBOSE)
292
292
293 # Extra pseudotokens for multiline strings and data structures
293 # Extra pseudotokens for multiline strings and data structures
294 _MULTILINE_STRING = object()
294 _MULTILINE_STRING = object()
295 _MULTILINE_STRUCTURE = object()
295 _MULTILINE_STRUCTURE = object()
296
296
297 def _line_tokens(line):
297 def _line_tokens(line):
298 """Helper for has_comment and ends_in_comment_or_string."""
298 """Helper for has_comment and ends_in_comment_or_string."""
299 readline = StringIO(line).readline
299 readline = StringIO(line).readline
300 toktypes = set()
300 toktypes = set()
301 try:
301 try:
302 for t in generate_tokens(readline):
302 for t in generate_tokens(readline):
303 toktypes.add(t[0])
303 toktypes.add(t[0])
304 except TokenError as e:
304 except TokenError as e:
305 # There are only two cases where a TokenError is raised.
305 # There are only two cases where a TokenError is raised.
306 if 'multi-line string' in e.args[0]:
306 if 'multi-line string' in e.args[0]:
307 toktypes.add(_MULTILINE_STRING)
307 toktypes.add(_MULTILINE_STRING)
308 else:
308 else:
309 toktypes.add(_MULTILINE_STRUCTURE)
309 toktypes.add(_MULTILINE_STRUCTURE)
310 return toktypes
310 return toktypes
311
311
312 def has_comment(src):
312 def has_comment(src):
313 """Indicate whether an input line has (i.e. ends in, or is) a comment.
313 """Indicate whether an input line has (i.e. ends in, or is) a comment.
314
314
315 This uses tokenize, so it can distinguish comments from # inside strings.
315 This uses tokenize, so it can distinguish comments from # inside strings.
316
316
317 Parameters
317 Parameters
318 ----------
318 ----------
319 src : string
319 src : string
320 A single line input string.
320 A single line input string.
321
321
322 Returns
322 Returns
323 -------
323 -------
324 comment : bool
324 comment : bool
325 True if source has a comment.
325 True if source has a comment.
326 """
326 """
327 return (tokenize2.COMMENT in _line_tokens(src))
327 return (tokenize2.COMMENT in _line_tokens(src))
328
328
329 def ends_in_comment_or_string(src):
329 def ends_in_comment_or_string(src):
330 """Indicates whether or not an input line ends in a comment or within
330 """Indicates whether or not an input line ends in a comment or within
331 a multiline string.
331 a multiline string.
332
332
333 Parameters
333 Parameters
334 ----------
334 ----------
335 src : string
335 src : string
336 A single line input string.
336 A single line input string.
337
337
338 Returns
338 Returns
339 -------
339 -------
340 comment : bool
340 comment : bool
341 True if source ends in a comment or multiline string.
341 True if source ends in a comment or multiline string.
342 """
342 """
343 toktypes = _line_tokens(src)
343 toktypes = _line_tokens(src)
344 return (tokenize2.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
344 return (tokenize2.COMMENT in toktypes) or (_MULTILINE_STRING in toktypes)
345
345
346
346
347 @StatelessInputTransformer.wrap
347 @StatelessInputTransformer.wrap
348 def help_end(line):
348 def help_end(line):
349 """Translate lines with ?/?? at the end"""
349 """Translate lines with ?/?? at the end"""
350 m = _help_end_re.search(line)
350 m = _help_end_re.search(line)
351 if m is None or ends_in_comment_or_string(line):
351 if m is None or ends_in_comment_or_string(line):
352 return line
352 return line
353 target = m.group(1)
353 target = m.group(1)
354 esc = m.group(3)
354 esc = m.group(3)
355 lspace = _initial_space_re.match(line).group(0)
355 lspace = _initial_space_re.match(line).group(0)
356
356
357 # If we're mid-command, put it back on the next prompt for the user.
357 # If we're mid-command, put it back on the next prompt for the user.
358 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
358 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
359
359
360 return _make_help_call(target, esc, lspace, next_input)
360 return _make_help_call(target, esc, lspace, next_input)
361
361
362
362
363 @CoroutineInputTransformer.wrap
363 @CoroutineInputTransformer.wrap
364 def cellmagic(end_on_blank_line=False):
364 def cellmagic(end_on_blank_line=False):
365 """Captures & transforms cell magics.
365 """Captures & transforms cell magics.
366
366
367 After a cell magic is started, this stores up any lines it gets until it is
367 After a cell magic is started, this stores up any lines it gets until it is
368 reset (sent None).
368 reset (sent None).
369 """
369 """
370 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
370 tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
371 cellmagic_help_re = re.compile('%%\w+\?')
371 cellmagic_help_re = re.compile('%%\w+\?')
372 line = ''
372 line = ''
373 while True:
373 while True:
374 line = (yield line)
374 line = (yield line)
375 # consume leading empty lines
375 # consume leading empty lines
376 while not line:
376 while not line:
377 line = (yield line)
377 line = (yield line)
378
378
379 if not line.startswith(ESC_MAGIC2):
379 if not line.startswith(ESC_MAGIC2):
380 # This isn't a cell magic, idle waiting for reset then start over
380 # This isn't a cell magic, idle waiting for reset then start over
381 while line is not None:
381 while line is not None:
382 line = (yield line)
382 line = (yield line)
383 continue
383 continue
384
384
385 if cellmagic_help_re.match(line):
385 if cellmagic_help_re.match(line):
386 # This case will be handled by help_end
386 # This case will be handled by help_end
387 continue
387 continue
388
388
389 first = line
389 first = line
390 body = []
390 body = []
391 line = (yield None)
391 line = (yield None)
392 while (line is not None) and \
392 while (line is not None) and \
393 ((line.strip() != '') or not end_on_blank_line):
393 ((line.strip() != '') or not end_on_blank_line):
394 body.append(line)
394 body.append(line)
395 line = (yield None)
395 line = (yield None)
396
396
397 # Output
397 # Output
398 magic_name, _, first = first.partition(' ')
398 magic_name, _, first = first.partition(' ')
399 magic_name = magic_name.lstrip(ESC_MAGIC2)
399 magic_name = magic_name.lstrip(ESC_MAGIC2)
400 line = tpl % (magic_name, first, u'\n'.join(body))
400 line = tpl % (magic_name, first, u'\n'.join(body))
401
401
402
402
403 def _strip_prompts(prompt_re, initial_re=None):
403 def _strip_prompts(prompt_re, initial_re=None):
404 """Remove matching input prompts from a block of input.
404 """Remove matching input prompts from a block of input.
405
405
406 Parameters
406 Parameters
407 ----------
407 ----------
408 prompt_re : regular expression
408 prompt_re : regular expression
409 A regular expression matching any input prompt (including continuation)
409 A regular expression matching any input prompt (including continuation)
410 initial_re : regular expression, optional
410 initial_re : regular expression, optional
411 A regular expression matching only the initial prompt, but not continuation.
411 A regular expression matching only the initial prompt, but not continuation.
412 If no initial expression is given, prompt_re will be used everywhere.
412 If no initial expression is given, prompt_re will be used everywhere.
413 Used mainly for plain Python prompts, where the continuation prompt
413 Used mainly for plain Python prompts, where the continuation prompt
414 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
414 ``...`` is a valid Python expression in Python 3, so shouldn't be stripped.
415
415
416 If initial_re and prompt_re differ,
416 If initial_re and prompt_re differ,
417 only initial_re will be tested against the first line.
417 only initial_re will be tested against the first line.
418 If any prompt is found on the first two lines,
418 If any prompt is found on the first two lines,
419 prompts will be stripped from the rest of the block.
419 prompts will be stripped from the rest of the block.
420 """
420 """
421 if initial_re is None:
421 if initial_re is None:
422 initial_re = prompt_re
422 initial_re = prompt_re
423 line = ''
423 line = ''
424 while True:
424 while True:
425 line = (yield line)
425 line = (yield line)
426
426
427 # First line of cell
427 # First line of cell
428 if line is None:
428 if line is None:
429 continue
429 continue
430 out, n1 = initial_re.subn('', line, count=1)
430 out, n1 = initial_re.subn('', line, count=1)
431 line = (yield out)
431 line = (yield out)
432
432
433 if line is None:
433 if line is None:
434 continue
434 continue
435 # check for any prompt on the second line of the cell,
435 # check for any prompt on the second line of the cell,
436 # because people often copy from just after the first prompt,
436 # because people often copy from just after the first prompt,
437 # so we might not see it in the first line.
437 # so we might not see it in the first line.
438 out, n2 = prompt_re.subn('', line, count=1)
438 out, n2 = prompt_re.subn('', line, count=1)
439 line = (yield out)
439 line = (yield out)
440
440
441 if n1 or n2:
441 if n1 or n2:
442 # Found a prompt in the first two lines - check for it in
442 # Found a prompt in the first two lines - check for it in
443 # the rest of the cell as well.
443 # the rest of the cell as well.
444 while line is not None:
444 while line is not None:
445 line = (yield prompt_re.sub('', line, count=1))
445 line = (yield prompt_re.sub('', line, count=1))
446
446
447 else:
447 else:
448 # Prompts not in input - wait for reset
448 # Prompts not in input - wait for reset
449 while line is not None:
449 while line is not None:
450 line = (yield line)
450 line = (yield line)
451
451
452 @CoroutineInputTransformer.wrap
452 @CoroutineInputTransformer.wrap
453 def classic_prompt():
453 def classic_prompt():
454 """Strip the >>>/... prompts of the Python interactive shell."""
454 """Strip the >>>/... prompts of the Python interactive shell."""
455 # FIXME: non-capturing version (?:...) usable?
455 # FIXME: non-capturing version (?:...) usable?
456 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
456 prompt_re = re.compile(r'^(>>>|\.\.\.)( |$)')
457 initial_re = re.compile(r'^>>>( |$)')
457 initial_re = re.compile(r'^>>>( |$)')
458 return _strip_prompts(prompt_re, initial_re)
458 return _strip_prompts(prompt_re, initial_re)
459
459
460 @CoroutineInputTransformer.wrap
460 @CoroutineInputTransformer.wrap
461 def ipy_prompt():
461 def ipy_prompt():
462 """Strip IPython's In [1]:/...: prompts."""
462 """Strip IPython's In [1]:/...: prompts."""
463 # FIXME: non-capturing version (?:...) usable?
463 # FIXME: non-capturing version (?:...) usable?
464 prompt_re = re.compile(r'^(In \[\d+\]: |\ {3,}\.{3,}: )')
464 prompt_re = re.compile(r'^(In \[\d+\]: |\s*\.{3,}: ?)')
465 return _strip_prompts(prompt_re)
465 return _strip_prompts(prompt_re)
466
466
467
467
468 @CoroutineInputTransformer.wrap
468 @CoroutineInputTransformer.wrap
469 def leading_indent():
469 def leading_indent():
470 """Remove leading indentation.
470 """Remove leading indentation.
471
471
472 If the first line starts with a spaces or tabs, the same whitespace will be
472 If the first line starts with a spaces or tabs, the same whitespace will be
473 removed from each following line until it is reset.
473 removed from each following line until it is reset.
474 """
474 """
475 space_re = re.compile(r'^[ \t]+')
475 space_re = re.compile(r'^[ \t]+')
476 line = ''
476 line = ''
477 while True:
477 while True:
478 line = (yield line)
478 line = (yield line)
479
479
480 if line is None:
480 if line is None:
481 continue
481 continue
482
482
483 m = space_re.match(line)
483 m = space_re.match(line)
484 if m:
484 if m:
485 space = m.group(0)
485 space = m.group(0)
486 while line is not None:
486 while line is not None:
487 if line.startswith(space):
487 if line.startswith(space):
488 line = line[len(space):]
488 line = line[len(space):]
489 line = (yield line)
489 line = (yield line)
490 else:
490 else:
491 # No leading spaces - wait for reset
491 # No leading spaces - wait for reset
492 while line is not None:
492 while line is not None:
493 line = (yield line)
493 line = (yield line)
494
494
495
495
496 @CoroutineInputTransformer.wrap
496 @CoroutineInputTransformer.wrap
497 def strip_encoding_cookie():
497 def strip_encoding_cookie():
498 """Remove encoding comment if found in first two lines
498 """Remove encoding comment if found in first two lines
499
499
500 If the first or second line has the `# coding: utf-8` comment,
500 If the first or second line has the `# coding: utf-8` comment,
501 it will be removed.
501 it will be removed.
502 """
502 """
503 line = ''
503 line = ''
504 while True:
504 while True:
505 line = (yield line)
505 line = (yield line)
506 # check comment on first two lines
506 # check comment on first two lines
507 for i in range(2):
507 for i in range(2):
508 if line is None:
508 if line is None:
509 break
509 break
510 if cookie_comment_re.match(line):
510 if cookie_comment_re.match(line):
511 line = (yield "")
511 line = (yield "")
512 else:
512 else:
513 line = (yield line)
513 line = (yield line)
514
514
515 # no-op on the rest of the cell
515 # no-op on the rest of the cell
516 while line is not None:
516 while line is not None:
517 line = (yield line)
517 line = (yield line)
518
518
519 _assign_pat = \
519 _assign_pat = \
520 r'''(?P<lhs>(\s*)
520 r'''(?P<lhs>(\s*)
521 ([\w\.]+) # Initial identifier
521 ([\w\.]+) # Initial identifier
522 (\s*,\s*
522 (\s*,\s*
523 \*?[\w\.]+)* # Further identifiers for unpacking
523 \*?[\w\.]+)* # Further identifiers for unpacking
524 \s*?,? # Trailing comma
524 \s*?,? # Trailing comma
525 )
525 )
526 \s*=\s*
526 \s*=\s*
527 '''
527 '''
528
528
529 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
529 assign_system_re = re.compile(r'{}!\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
530 assign_system_template = '%s = get_ipython().getoutput(%r)'
530 assign_system_template = '%s = get_ipython().getoutput(%r)'
531 @StatelessInputTransformer.wrap
531 @StatelessInputTransformer.wrap
532 def assign_from_system(line):
532 def assign_from_system(line):
533 """Transform assignment from system commands (e.g. files = !ls)"""
533 """Transform assignment from system commands (e.g. files = !ls)"""
534 m = assign_system_re.match(line)
534 m = assign_system_re.match(line)
535 if m is None:
535 if m is None:
536 return line
536 return line
537
537
538 return assign_system_template % m.group('lhs', 'cmd')
538 return assign_system_template % m.group('lhs', 'cmd')
539
539
540 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
540 assign_magic_re = re.compile(r'{}%\s*(?P<cmd>.*)'.format(_assign_pat), re.VERBOSE)
541 assign_magic_template = '%s = get_ipython().magic(%r)'
541 assign_magic_template = '%s = get_ipython().magic(%r)'
542 @StatelessInputTransformer.wrap
542 @StatelessInputTransformer.wrap
543 def assign_from_magic(line):
543 def assign_from_magic(line):
544 """Transform assignment from magic commands (e.g. a = %who_ls)"""
544 """Transform assignment from magic commands (e.g. a = %who_ls)"""
545 m = assign_magic_re.match(line)
545 m = assign_magic_re.match(line)
546 if m is None:
546 if m is None:
547 return line
547 return line
548
548
549 return assign_magic_template % m.group('lhs', 'cmd')
549 return assign_magic_template % m.group('lhs', 'cmd')
@@ -1,3288 +1,3336 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Main IPython class."""
2 """Main IPython class."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 from __future__ import absolute_import, print_function
13 from __future__ import absolute_import, print_function
14
14
15 import __future__
15 import __future__
16 import abc
16 import abc
17 import ast
17 import ast
18 import atexit
18 import atexit
19 import functools
19 import functools
20 import os
20 import os
21 import re
21 import re
22 import runpy
22 import runpy
23 import sys
23 import sys
24 import tempfile
24 import tempfile
25 import traceback
25 import types
26 import types
26 import subprocess
27 import subprocess
27 from io import open as io_open
28 from io import open as io_open
28
29
29 from IPython.config.configurable import SingletonConfigurable
30 from IPython.config.configurable import SingletonConfigurable
30 from IPython.core import debugger, oinspect
31 from IPython.core import debugger, oinspect
31 from IPython.core import magic
32 from IPython.core import magic
32 from IPython.core import page
33 from IPython.core import page
33 from IPython.core import prefilter
34 from IPython.core import prefilter
34 from IPython.core import shadowns
35 from IPython.core import shadowns
35 from IPython.core import ultratb
36 from IPython.core import ultratb
36 from IPython.core.alias import AliasManager, AliasError
37 from IPython.core.alias import AliasManager, AliasError
37 from IPython.core.autocall import ExitAutocall
38 from IPython.core.autocall import ExitAutocall
38 from IPython.core.builtin_trap import BuiltinTrap
39 from IPython.core.builtin_trap import BuiltinTrap
39 from IPython.core.events import EventManager, available_events
40 from IPython.core.events import EventManager, available_events
40 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
41 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
41 from IPython.core.display_trap import DisplayTrap
42 from IPython.core.display_trap import DisplayTrap
42 from IPython.core.displayhook import DisplayHook
43 from IPython.core.displayhook import DisplayHook
43 from IPython.core.displaypub import DisplayPublisher
44 from IPython.core.displaypub import DisplayPublisher
44 from IPython.core.error import InputRejected, UsageError
45 from IPython.core.error import InputRejected, UsageError
45 from IPython.core.extensions import ExtensionManager
46 from IPython.core.extensions import ExtensionManager
46 from IPython.core.formatters import DisplayFormatter
47 from IPython.core.formatters import DisplayFormatter
47 from IPython.core.history import HistoryManager
48 from IPython.core.history import HistoryManager
48 from IPython.core.inputsplitter import IPythonInputSplitter, ESC_MAGIC, ESC_MAGIC2
49 from IPython.core.inputsplitter import IPythonInputSplitter, ESC_MAGIC, ESC_MAGIC2
49 from IPython.core.logger import Logger
50 from IPython.core.logger import Logger
50 from IPython.core.macro import Macro
51 from IPython.core.macro import Macro
51 from IPython.core.payload import PayloadManager
52 from IPython.core.payload import PayloadManager
52 from IPython.core.prefilter import PrefilterManager
53 from IPython.core.prefilter import PrefilterManager
53 from IPython.core.profiledir import ProfileDir
54 from IPython.core.profiledir import ProfileDir
54 from IPython.core.prompts import PromptManager
55 from IPython.core.prompts import PromptManager
55 from IPython.core.usage import default_banner
56 from IPython.core.usage import default_banner
56 from IPython.lib.latextools import LaTeXTool
57 from IPython.lib.latextools import LaTeXTool
57 from IPython.testing.skipdoctest import skip_doctest
58 from IPython.testing.skipdoctest import skip_doctest
58 from IPython.utils import PyColorize
59 from IPython.utils import PyColorize
59 from IPython.utils import io
60 from IPython.utils import io
60 from IPython.utils import py3compat
61 from IPython.utils import py3compat
61 from IPython.utils import openpy
62 from IPython.utils import openpy
62 from IPython.utils.decorators import undoc
63 from IPython.utils.decorators import undoc
63 from IPython.utils.io import ask_yes_no
64 from IPython.utils.io import ask_yes_no
64 from IPython.utils.ipstruct import Struct
65 from IPython.utils.ipstruct import Struct
65 from IPython.utils.path import get_home_dir, get_ipython_dir, get_py_filename, unquote_filename, ensure_dir_exists
66 from IPython.utils.path import get_home_dir, get_ipython_dir, get_py_filename, unquote_filename, ensure_dir_exists
66 from IPython.utils.pickleshare import PickleShareDB
67 from IPython.utils.pickleshare import PickleShareDB
67 from IPython.utils.process import system, getoutput
68 from IPython.utils.process import system, getoutput
68 from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,
69 from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,
69 with_metaclass, iteritems)
70 with_metaclass, iteritems)
70 from IPython.utils.strdispatch import StrDispatch
71 from IPython.utils.strdispatch import StrDispatch
71 from IPython.utils.syspathcontext import prepended_to_syspath
72 from IPython.utils.syspathcontext import prepended_to_syspath
72 from IPython.utils.text import (format_screen, LSString, SList,
73 from IPython.utils.text import (format_screen, LSString, SList,
73 DollarFormatter)
74 DollarFormatter)
74 from IPython.utils.traitlets import (Integer, CBool, CaselessStrEnum, Enum,
75 from IPython.utils.traitlets import (Integer, CBool, CaselessStrEnum, Enum,
75 List, Unicode, Instance, Type)
76 List, Unicode, Instance, Type)
76 from IPython.utils.warn import warn, error
77 from IPython.utils.warn import warn, error
77 import IPython.core.hooks
78 import IPython.core.hooks
78
79
79 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
80 # Globals
81 # Globals
81 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
82
83
83 # compiled regexps for autoindent management
84 # compiled regexps for autoindent management
84 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
85 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
85
86
86 #-----------------------------------------------------------------------------
87 #-----------------------------------------------------------------------------
87 # Utilities
88 # Utilities
88 #-----------------------------------------------------------------------------
89 #-----------------------------------------------------------------------------
89
90
90 @undoc
91 @undoc
91 def softspace(file, newvalue):
92 def softspace(file, newvalue):
92 """Copied from code.py, to remove the dependency"""
93 """Copied from code.py, to remove the dependency"""
93
94
94 oldvalue = 0
95 oldvalue = 0
95 try:
96 try:
96 oldvalue = file.softspace
97 oldvalue = file.softspace
97 except AttributeError:
98 except AttributeError:
98 pass
99 pass
99 try:
100 try:
100 file.softspace = newvalue
101 file.softspace = newvalue
101 except (AttributeError, TypeError):
102 except (AttributeError, TypeError):
102 # "attribute-less object" or "read-only attributes"
103 # "attribute-less object" or "read-only attributes"
103 pass
104 pass
104 return oldvalue
105 return oldvalue
105
106
106 @undoc
107 @undoc
107 def no_op(*a, **kw): pass
108 def no_op(*a, **kw): pass
108
109
109 @undoc
110 @undoc
110 class NoOpContext(object):
111 class NoOpContext(object):
111 def __enter__(self): pass
112 def __enter__(self): pass
112 def __exit__(self, type, value, traceback): pass
113 def __exit__(self, type, value, traceback): pass
113 no_op_context = NoOpContext()
114 no_op_context = NoOpContext()
114
115
115 class SpaceInInput(Exception): pass
116 class SpaceInInput(Exception): pass
116
117
117 @undoc
118 @undoc
118 class Bunch: pass
119 class Bunch: pass
119
120
120
121
121 def get_default_colors():
122 def get_default_colors():
122 if sys.platform=='darwin':
123 if sys.platform=='darwin':
123 return "LightBG"
124 return "LightBG"
124 elif os.name=='nt':
125 elif os.name=='nt':
125 return 'Linux'
126 return 'Linux'
126 else:
127 else:
127 return 'Linux'
128 return 'Linux'
128
129
129
130
130 class SeparateUnicode(Unicode):
131 class SeparateUnicode(Unicode):
131 r"""A Unicode subclass to validate separate_in, separate_out, etc.
132 r"""A Unicode subclass to validate separate_in, separate_out, etc.
132
133
133 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
134 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
134 """
135 """
135
136
136 def validate(self, obj, value):
137 def validate(self, obj, value):
137 if value == '0': value = ''
138 if value == '0': value = ''
138 value = value.replace('\\n','\n')
139 value = value.replace('\\n','\n')
139 return super(SeparateUnicode, self).validate(obj, value)
140 return super(SeparateUnicode, self).validate(obj, value)
140
141
141
142
142 class ReadlineNoRecord(object):
143 class ReadlineNoRecord(object):
143 """Context manager to execute some code, then reload readline history
144 """Context manager to execute some code, then reload readline history
144 so that interactive input to the code doesn't appear when pressing up."""
145 so that interactive input to the code doesn't appear when pressing up."""
145 def __init__(self, shell):
146 def __init__(self, shell):
146 self.shell = shell
147 self.shell = shell
147 self._nested_level = 0
148 self._nested_level = 0
148
149
149 def __enter__(self):
150 def __enter__(self):
150 if self._nested_level == 0:
151 if self._nested_level == 0:
151 try:
152 try:
152 self.orig_length = self.current_length()
153 self.orig_length = self.current_length()
153 self.readline_tail = self.get_readline_tail()
154 self.readline_tail = self.get_readline_tail()
154 except (AttributeError, IndexError): # Can fail with pyreadline
155 except (AttributeError, IndexError): # Can fail with pyreadline
155 self.orig_length, self.readline_tail = 999999, []
156 self.orig_length, self.readline_tail = 999999, []
156 self._nested_level += 1
157 self._nested_level += 1
157
158
158 def __exit__(self, type, value, traceback):
159 def __exit__(self, type, value, traceback):
159 self._nested_level -= 1
160 self._nested_level -= 1
160 if self._nested_level == 0:
161 if self._nested_level == 0:
161 # Try clipping the end if it's got longer
162 # Try clipping the end if it's got longer
162 try:
163 try:
163 e = self.current_length() - self.orig_length
164 e = self.current_length() - self.orig_length
164 if e > 0:
165 if e > 0:
165 for _ in range(e):
166 for _ in range(e):
166 self.shell.readline.remove_history_item(self.orig_length)
167 self.shell.readline.remove_history_item(self.orig_length)
167
168
168 # If it still doesn't match, just reload readline history.
169 # If it still doesn't match, just reload readline history.
169 if self.current_length() != self.orig_length \
170 if self.current_length() != self.orig_length \
170 or self.get_readline_tail() != self.readline_tail:
171 or self.get_readline_tail() != self.readline_tail:
171 self.shell.refill_readline_hist()
172 self.shell.refill_readline_hist()
172 except (AttributeError, IndexError):
173 except (AttributeError, IndexError):
173 pass
174 pass
174 # Returning False will cause exceptions to propagate
175 # Returning False will cause exceptions to propagate
175 return False
176 return False
176
177
177 def current_length(self):
178 def current_length(self):
178 return self.shell.readline.get_current_history_length()
179 return self.shell.readline.get_current_history_length()
179
180
180 def get_readline_tail(self, n=10):
181 def get_readline_tail(self, n=10):
181 """Get the last n items in readline history."""
182 """Get the last n items in readline history."""
182 end = self.shell.readline.get_current_history_length() + 1
183 end = self.shell.readline.get_current_history_length() + 1
183 start = max(end-n, 1)
184 start = max(end-n, 1)
184 ghi = self.shell.readline.get_history_item
185 ghi = self.shell.readline.get_history_item
185 return [ghi(x) for x in range(start, end)]
186 return [ghi(x) for x in range(start, end)]
186
187
187
188
188 @undoc
189 @undoc
189 class DummyMod(object):
190 class DummyMod(object):
190 """A dummy module used for IPython's interactive module when
191 """A dummy module used for IPython's interactive module when
191 a namespace must be assigned to the module's __dict__."""
192 a namespace must be assigned to the module's __dict__."""
192 pass
193 pass
193
194
194 #-----------------------------------------------------------------------------
195 #-----------------------------------------------------------------------------
195 # Main IPython class
196 # Main IPython class
196 #-----------------------------------------------------------------------------
197 #-----------------------------------------------------------------------------
197
198
198 class InteractiveShell(SingletonConfigurable):
199 class InteractiveShell(SingletonConfigurable):
199 """An enhanced, interactive shell for Python."""
200 """An enhanced, interactive shell for Python."""
200
201
201 _instance = None
202 _instance = None
202
203
203 ast_transformers = List([], config=True, help=
204 ast_transformers = List([], config=True, help=
204 """
205 """
205 A list of ast.NodeTransformer subclass instances, which will be applied
206 A list of ast.NodeTransformer subclass instances, which will be applied
206 to user input before code is run.
207 to user input before code is run.
207 """
208 """
208 )
209 )
209
210
210 autocall = Enum((0,1,2), default_value=0, config=True, help=
211 autocall = Enum((0,1,2), default_value=0, config=True, help=
211 """
212 """
212 Make IPython automatically call any callable object even if you didn't
213 Make IPython automatically call any callable object even if you didn't
213 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
214 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
214 automatically. The value can be '0' to disable the feature, '1' for
215 automatically. The value can be '0' to disable the feature, '1' for
215 'smart' autocall, where it is not applied if there are no more
216 'smart' autocall, where it is not applied if there are no more
216 arguments on the line, and '2' for 'full' autocall, where all callable
217 arguments on the line, and '2' for 'full' autocall, where all callable
217 objects are automatically called (even if no arguments are present).
218 objects are automatically called (even if no arguments are present).
218 """
219 """
219 )
220 )
220 # TODO: remove all autoindent logic and put into frontends.
221 # TODO: remove all autoindent logic and put into frontends.
221 # We can't do this yet because even runlines uses the autoindent.
222 # We can't do this yet because even runlines uses the autoindent.
222 autoindent = CBool(True, config=True, help=
223 autoindent = CBool(True, config=True, help=
223 """
224 """
224 Autoindent IPython code entered interactively.
225 Autoindent IPython code entered interactively.
225 """
226 """
226 )
227 )
227 automagic = CBool(True, config=True, help=
228 automagic = CBool(True, config=True, help=
228 """
229 """
229 Enable magic commands to be called without the leading %.
230 Enable magic commands to be called without the leading %.
230 """
231 """
231 )
232 )
232
233
233 banner = Unicode('')
234 banner = Unicode('')
234
235
235 banner1 = Unicode(default_banner, config=True,
236 banner1 = Unicode(default_banner, config=True,
236 help="""The part of the banner to be printed before the profile"""
237 help="""The part of the banner to be printed before the profile"""
237 )
238 )
238 banner2 = Unicode('', config=True,
239 banner2 = Unicode('', config=True,
239 help="""The part of the banner to be printed after the profile"""
240 help="""The part of the banner to be printed after the profile"""
240 )
241 )
241
242
242 cache_size = Integer(1000, config=True, help=
243 cache_size = Integer(1000, config=True, help=
243 """
244 """
244 Set the size of the output cache. The default is 1000, you can
245 Set the size of the output cache. The default is 1000, you can
245 change it permanently in your config file. Setting it to 0 completely
246 change it permanently in your config file. Setting it to 0 completely
246 disables the caching system, and the minimum value accepted is 20 (if
247 disables the caching system, and the minimum value accepted is 20 (if
247 you provide a value less than 20, it is reset to 0 and a warning is
248 you provide a value less than 20, it is reset to 0 and a warning is
248 issued). This limit is defined because otherwise you'll spend more
249 issued). This limit is defined because otherwise you'll spend more
249 time re-flushing a too small cache than working
250 time re-flushing a too small cache than working
250 """
251 """
251 )
252 )
252 color_info = CBool(True, config=True, help=
253 color_info = CBool(True, config=True, help=
253 """
254 """
254 Use colors for displaying information about objects. Because this
255 Use colors for displaying information about objects. Because this
255 information is passed through a pager (like 'less'), and some pagers
256 information is passed through a pager (like 'less'), and some pagers
256 get confused with color codes, this capability can be turned off.
257 get confused with color codes, this capability can be turned off.
257 """
258 """
258 )
259 )
259 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
260 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
260 default_value=get_default_colors(), config=True,
261 default_value=get_default_colors(), config=True,
261 help="Set the color scheme (NoColor, Linux, or LightBG)."
262 help="Set the color scheme (NoColor, Linux, or LightBG)."
262 )
263 )
263 colors_force = CBool(False, help=
264 colors_force = CBool(False, help=
264 """
265 """
265 Force use of ANSI color codes, regardless of OS and readline
266 Force use of ANSI color codes, regardless of OS and readline
266 availability.
267 availability.
267 """
268 """
268 # FIXME: This is essentially a hack to allow ZMQShell to show colors
269 # FIXME: This is essentially a hack to allow ZMQShell to show colors
269 # without readline on Win32. When the ZMQ formatting system is
270 # without readline on Win32. When the ZMQ formatting system is
270 # refactored, this should be removed.
271 # refactored, this should be removed.
271 )
272 )
272 debug = CBool(False, config=True)
273 debug = CBool(False, config=True)
273 deep_reload = CBool(False, config=True, help=
274 deep_reload = CBool(False, config=True, help=
274 """
275 """
275 Enable deep (recursive) reloading by default. IPython can use the
276 Enable deep (recursive) reloading by default. IPython can use the
276 deep_reload module which reloads changes in modules recursively (it
277 deep_reload module which reloads changes in modules recursively (it
277 replaces the reload() function, so you don't need to change anything to
278 replaces the reload() function, so you don't need to change anything to
278 use it). deep_reload() forces a full reload of modules whose code may
279 use it). deep_reload() forces a full reload of modules whose code may
279 have changed, which the default reload() function does not. When
280 have changed, which the default reload() function does not. When
280 deep_reload is off, IPython will use the normal reload(), but
281 deep_reload is off, IPython will use the normal reload(), but
281 deep_reload will still be available as dreload().
282 deep_reload will still be available as dreload().
282 """
283 """
283 )
284 )
284 disable_failing_post_execute = CBool(False, config=True,
285 disable_failing_post_execute = CBool(False, config=True,
285 help="Don't call post-execute functions that have failed in the past."
286 help="Don't call post-execute functions that have failed in the past."
286 )
287 )
287 display_formatter = Instance(DisplayFormatter)
288 display_formatter = Instance(DisplayFormatter)
288 displayhook_class = Type(DisplayHook)
289 displayhook_class = Type(DisplayHook)
289 display_pub_class = Type(DisplayPublisher)
290 display_pub_class = Type(DisplayPublisher)
290 data_pub_class = None
291 data_pub_class = None
291
292
292 exit_now = CBool(False)
293 exit_now = CBool(False)
293 exiter = Instance(ExitAutocall)
294 exiter = Instance(ExitAutocall)
294 def _exiter_default(self):
295 def _exiter_default(self):
295 return ExitAutocall(self)
296 return ExitAutocall(self)
296 # Monotonically increasing execution counter
297 # Monotonically increasing execution counter
297 execution_count = Integer(1)
298 execution_count = Integer(1)
298 filename = Unicode("<ipython console>")
299 filename = Unicode("<ipython console>")
299 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
300 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
300
301
301 # Input splitter, to transform input line by line and detect when a block
302 # Input splitter, to transform input line by line and detect when a block
302 # is ready to be executed.
303 # is ready to be executed.
303 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
304 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
304 (), {'line_input_checker': True})
305 (), {'line_input_checker': True})
305
306
306 # This InputSplitter instance is used to transform completed cells before
307 # This InputSplitter instance is used to transform completed cells before
307 # running them. It allows cell magics to contain blank lines.
308 # running them. It allows cell magics to contain blank lines.
308 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
309 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
309 (), {'line_input_checker': False})
310 (), {'line_input_checker': False})
310
311
311 logstart = CBool(False, config=True, help=
312 logstart = CBool(False, config=True, help=
312 """
313 """
313 Start logging to the default log file.
314 Start logging to the default log file.
314 """
315 """
315 )
316 )
316 logfile = Unicode('', config=True, help=
317 logfile = Unicode('', config=True, help=
317 """
318 """
318 The name of the logfile to use.
319 The name of the logfile to use.
319 """
320 """
320 )
321 )
321 logappend = Unicode('', config=True, help=
322 logappend = Unicode('', config=True, help=
322 """
323 """
323 Start logging to the given file in append mode.
324 Start logging to the given file in append mode.
324 """
325 """
325 )
326 )
326 object_info_string_level = Enum((0,1,2), default_value=0,
327 object_info_string_level = Enum((0,1,2), default_value=0,
327 config=True)
328 config=True)
328 pdb = CBool(False, config=True, help=
329 pdb = CBool(False, config=True, help=
329 """
330 """
330 Automatically call the pdb debugger after every exception.
331 Automatically call the pdb debugger after every exception.
331 """
332 """
332 )
333 )
333 multiline_history = CBool(sys.platform != 'win32', config=True,
334 multiline_history = CBool(sys.platform != 'win32', config=True,
334 help="Save multi-line entries as one entry in readline history"
335 help="Save multi-line entries as one entry in readline history"
335 )
336 )
336
337
337 # deprecated prompt traits:
338 # deprecated prompt traits:
338
339
339 prompt_in1 = Unicode('In [\\#]: ', config=True,
340 prompt_in1 = Unicode('In [\\#]: ', config=True,
340 help="Deprecated, use PromptManager.in_template")
341 help="Deprecated, use PromptManager.in_template")
341 prompt_in2 = Unicode(' .\\D.: ', config=True,
342 prompt_in2 = Unicode(' .\\D.: ', config=True,
342 help="Deprecated, use PromptManager.in2_template")
343 help="Deprecated, use PromptManager.in2_template")
343 prompt_out = Unicode('Out[\\#]: ', config=True,
344 prompt_out = Unicode('Out[\\#]: ', config=True,
344 help="Deprecated, use PromptManager.out_template")
345 help="Deprecated, use PromptManager.out_template")
345 prompts_pad_left = CBool(True, config=True,
346 prompts_pad_left = CBool(True, config=True,
346 help="Deprecated, use PromptManager.justify")
347 help="Deprecated, use PromptManager.justify")
347
348
348 def _prompt_trait_changed(self, name, old, new):
349 def _prompt_trait_changed(self, name, old, new):
349 table = {
350 table = {
350 'prompt_in1' : 'in_template',
351 'prompt_in1' : 'in_template',
351 'prompt_in2' : 'in2_template',
352 'prompt_in2' : 'in2_template',
352 'prompt_out' : 'out_template',
353 'prompt_out' : 'out_template',
353 'prompts_pad_left' : 'justify',
354 'prompts_pad_left' : 'justify',
354 }
355 }
355 warn("InteractiveShell.{name} is deprecated, use PromptManager.{newname}".format(
356 warn("InteractiveShell.{name} is deprecated, use PromptManager.{newname}".format(
356 name=name, newname=table[name])
357 name=name, newname=table[name])
357 )
358 )
358 # protect against weird cases where self.config may not exist:
359 # protect against weird cases where self.config may not exist:
359 if self.config is not None:
360 if self.config is not None:
360 # propagate to corresponding PromptManager trait
361 # propagate to corresponding PromptManager trait
361 setattr(self.config.PromptManager, table[name], new)
362 setattr(self.config.PromptManager, table[name], new)
362
363
363 _prompt_in1_changed = _prompt_trait_changed
364 _prompt_in1_changed = _prompt_trait_changed
364 _prompt_in2_changed = _prompt_trait_changed
365 _prompt_in2_changed = _prompt_trait_changed
365 _prompt_out_changed = _prompt_trait_changed
366 _prompt_out_changed = _prompt_trait_changed
366 _prompt_pad_left_changed = _prompt_trait_changed
367 _prompt_pad_left_changed = _prompt_trait_changed
367
368
368 show_rewritten_input = CBool(True, config=True,
369 show_rewritten_input = CBool(True, config=True,
369 help="Show rewritten input, e.g. for autocall."
370 help="Show rewritten input, e.g. for autocall."
370 )
371 )
371
372
372 quiet = CBool(False, config=True)
373 quiet = CBool(False, config=True)
373
374
374 history_length = Integer(10000, config=True)
375 history_length = Integer(10000, config=True)
375
376
376 # The readline stuff will eventually be moved to the terminal subclass
377 # The readline stuff will eventually be moved to the terminal subclass
377 # but for now, we can't do that as readline is welded in everywhere.
378 # but for now, we can't do that as readline is welded in everywhere.
378 readline_use = CBool(True, config=True)
379 readline_use = CBool(True, config=True)
379 readline_remove_delims = Unicode('-/~', config=True)
380 readline_remove_delims = Unicode('-/~', config=True)
380 readline_delims = Unicode() # set by init_readline()
381 readline_delims = Unicode() # set by init_readline()
381 # don't use \M- bindings by default, because they
382 # don't use \M- bindings by default, because they
382 # conflict with 8-bit encodings. See gh-58,gh-88
383 # conflict with 8-bit encodings. See gh-58,gh-88
383 readline_parse_and_bind = List([
384 readline_parse_and_bind = List([
384 'tab: complete',
385 'tab: complete',
385 '"\C-l": clear-screen',
386 '"\C-l": clear-screen',
386 'set show-all-if-ambiguous on',
387 'set show-all-if-ambiguous on',
387 '"\C-o": tab-insert',
388 '"\C-o": tab-insert',
388 '"\C-r": reverse-search-history',
389 '"\C-r": reverse-search-history',
389 '"\C-s": forward-search-history',
390 '"\C-s": forward-search-history',
390 '"\C-p": history-search-backward',
391 '"\C-p": history-search-backward',
391 '"\C-n": history-search-forward',
392 '"\C-n": history-search-forward',
392 '"\e[A": history-search-backward',
393 '"\e[A": history-search-backward',
393 '"\e[B": history-search-forward',
394 '"\e[B": history-search-forward',
394 '"\C-k": kill-line',
395 '"\C-k": kill-line',
395 '"\C-u": unix-line-discard',
396 '"\C-u": unix-line-discard',
396 ], config=True)
397 ], config=True)
397
398
398 _custom_readline_config = False
399 _custom_readline_config = False
399
400
400 def _readline_parse_and_bind_changed(self, name, old, new):
401 def _readline_parse_and_bind_changed(self, name, old, new):
401 # notice that readline config is customized
402 # notice that readline config is customized
402 # indicates that it should have higher priority than inputrc
403 # indicates that it should have higher priority than inputrc
403 self._custom_readline_config = True
404 self._custom_readline_config = True
404
405
405 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
406 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
406 default_value='last_expr', config=True,
407 default_value='last_expr', config=True,
407 help="""
408 help="""
408 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
409 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
409 run interactively (displaying output from expressions).""")
410 run interactively (displaying output from expressions).""")
410
411
411 # TODO: this part of prompt management should be moved to the frontends.
412 # TODO: this part of prompt management should be moved to the frontends.
412 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
413 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
413 separate_in = SeparateUnicode('\n', config=True)
414 separate_in = SeparateUnicode('\n', config=True)
414 separate_out = SeparateUnicode('', config=True)
415 separate_out = SeparateUnicode('', config=True)
415 separate_out2 = SeparateUnicode('', config=True)
416 separate_out2 = SeparateUnicode('', config=True)
416 wildcards_case_sensitive = CBool(True, config=True)
417 wildcards_case_sensitive = CBool(True, config=True)
417 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
418 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
418 default_value='Context', config=True)
419 default_value='Context', config=True)
419
420
420 # Subcomponents of InteractiveShell
421 # Subcomponents of InteractiveShell
421 alias_manager = Instance('IPython.core.alias.AliasManager')
422 alias_manager = Instance('IPython.core.alias.AliasManager')
422 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
423 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
423 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap')
424 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap')
424 display_trap = Instance('IPython.core.display_trap.DisplayTrap')
425 display_trap = Instance('IPython.core.display_trap.DisplayTrap')
425 extension_manager = Instance('IPython.core.extensions.ExtensionManager')
426 extension_manager = Instance('IPython.core.extensions.ExtensionManager')
426 payload_manager = Instance('IPython.core.payload.PayloadManager')
427 payload_manager = Instance('IPython.core.payload.PayloadManager')
427 history_manager = Instance('IPython.core.history.HistoryManager')
428 history_manager = Instance('IPython.core.history.HistoryAccessorBase')
428 magics_manager = Instance('IPython.core.magic.MagicsManager')
429 magics_manager = Instance('IPython.core.magic.MagicsManager')
429
430
430 profile_dir = Instance('IPython.core.application.ProfileDir')
431 profile_dir = Instance('IPython.core.application.ProfileDir')
431 @property
432 @property
432 def profile(self):
433 def profile(self):
433 if self.profile_dir is not None:
434 if self.profile_dir is not None:
434 name = os.path.basename(self.profile_dir.location)
435 name = os.path.basename(self.profile_dir.location)
435 return name.replace('profile_','')
436 return name.replace('profile_','')
436
437
437
438
438 # Private interface
439 # Private interface
439 _post_execute = Instance(dict)
440 _post_execute = Instance(dict)
440
441
441 # Tracks any GUI loop loaded for pylab
442 # Tracks any GUI loop loaded for pylab
442 pylab_gui_select = None
443 pylab_gui_select = None
443
444
444 def __init__(self, ipython_dir=None, profile_dir=None,
445 def __init__(self, ipython_dir=None, profile_dir=None,
445 user_module=None, user_ns=None,
446 user_module=None, user_ns=None,
446 custom_exceptions=((), None), **kwargs):
447 custom_exceptions=((), None), **kwargs):
447
448
448 # This is where traits with a config_key argument are updated
449 # This is where traits with a config_key argument are updated
449 # from the values on config.
450 # from the values on config.
450 super(InteractiveShell, self).__init__(**kwargs)
451 super(InteractiveShell, self).__init__(**kwargs)
451 self.configurables = [self]
452 self.configurables = [self]
452
453
453 # These are relatively independent and stateless
454 # These are relatively independent and stateless
454 self.init_ipython_dir(ipython_dir)
455 self.init_ipython_dir(ipython_dir)
455 self.init_profile_dir(profile_dir)
456 self.init_profile_dir(profile_dir)
456 self.init_instance_attrs()
457 self.init_instance_attrs()
457 self.init_environment()
458 self.init_environment()
458
459
459 # Check if we're in a virtualenv, and set up sys.path.
460 # Check if we're in a virtualenv, and set up sys.path.
460 self.init_virtualenv()
461 self.init_virtualenv()
461
462
462 # Create namespaces (user_ns, user_global_ns, etc.)
463 # Create namespaces (user_ns, user_global_ns, etc.)
463 self.init_create_namespaces(user_module, user_ns)
464 self.init_create_namespaces(user_module, user_ns)
464 # This has to be done after init_create_namespaces because it uses
465 # This has to be done after init_create_namespaces because it uses
465 # something in self.user_ns, but before init_sys_modules, which
466 # something in self.user_ns, but before init_sys_modules, which
466 # is the first thing to modify sys.
467 # is the first thing to modify sys.
467 # TODO: When we override sys.stdout and sys.stderr before this class
468 # TODO: When we override sys.stdout and sys.stderr before this class
468 # is created, we are saving the overridden ones here. Not sure if this
469 # is created, we are saving the overridden ones here. Not sure if this
469 # is what we want to do.
470 # is what we want to do.
470 self.save_sys_module_state()
471 self.save_sys_module_state()
471 self.init_sys_modules()
472 self.init_sys_modules()
472
473
473 # While we're trying to have each part of the code directly access what
474 # While we're trying to have each part of the code directly access what
474 # it needs without keeping redundant references to objects, we have too
475 # it needs without keeping redundant references to objects, we have too
475 # much legacy code that expects ip.db to exist.
476 # much legacy code that expects ip.db to exist.
476 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
477 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
477
478
478 self.init_history()
479 self.init_history()
479 self.init_encoding()
480 self.init_encoding()
480 self.init_prefilter()
481 self.init_prefilter()
481
482
482 self.init_syntax_highlighting()
483 self.init_syntax_highlighting()
483 self.init_hooks()
484 self.init_hooks()
484 self.init_events()
485 self.init_events()
485 self.init_pushd_popd_magic()
486 self.init_pushd_popd_magic()
486 # self.init_traceback_handlers use to be here, but we moved it below
487 # self.init_traceback_handlers use to be here, but we moved it below
487 # because it and init_io have to come after init_readline.
488 # because it and init_io have to come after init_readline.
488 self.init_user_ns()
489 self.init_user_ns()
489 self.init_logger()
490 self.init_logger()
490 self.init_builtins()
491 self.init_builtins()
491
492
492 # The following was in post_config_initialization
493 # The following was in post_config_initialization
493 self.init_inspector()
494 self.init_inspector()
494 # init_readline() must come before init_io(), because init_io uses
495 # init_readline() must come before init_io(), because init_io uses
495 # readline related things.
496 # readline related things.
496 self.init_readline()
497 self.init_readline()
497 # We save this here in case user code replaces raw_input, but it needs
498 # We save this here in case user code replaces raw_input, but it needs
498 # to be after init_readline(), because PyPy's readline works by replacing
499 # to be after init_readline(), because PyPy's readline works by replacing
499 # raw_input.
500 # raw_input.
500 if py3compat.PY3:
501 if py3compat.PY3:
501 self.raw_input_original = input
502 self.raw_input_original = input
502 else:
503 else:
503 self.raw_input_original = raw_input
504 self.raw_input_original = raw_input
504 # init_completer must come after init_readline, because it needs to
505 # init_completer must come after init_readline, because it needs to
505 # know whether readline is present or not system-wide to configure the
506 # know whether readline is present or not system-wide to configure the
506 # completers, since the completion machinery can now operate
507 # completers, since the completion machinery can now operate
507 # independently of readline (e.g. over the network)
508 # independently of readline (e.g. over the network)
508 self.init_completer()
509 self.init_completer()
509 # TODO: init_io() needs to happen before init_traceback handlers
510 # TODO: init_io() needs to happen before init_traceback handlers
510 # because the traceback handlers hardcode the stdout/stderr streams.
511 # because the traceback handlers hardcode the stdout/stderr streams.
511 # This logic in in debugger.Pdb and should eventually be changed.
512 # This logic in in debugger.Pdb and should eventually be changed.
512 self.init_io()
513 self.init_io()
513 self.init_traceback_handlers(custom_exceptions)
514 self.init_traceback_handlers(custom_exceptions)
514 self.init_prompts()
515 self.init_prompts()
515 self.init_display_formatter()
516 self.init_display_formatter()
516 self.init_display_pub()
517 self.init_display_pub()
517 self.init_data_pub()
518 self.init_data_pub()
518 self.init_displayhook()
519 self.init_displayhook()
519 self.init_latextool()
520 self.init_latextool()
520 self.init_magics()
521 self.init_magics()
521 self.init_alias()
522 self.init_alias()
522 self.init_logstart()
523 self.init_logstart()
523 self.init_pdb()
524 self.init_pdb()
524 self.init_extension_manager()
525 self.init_extension_manager()
525 self.init_payload()
526 self.init_payload()
526 self.init_comms()
527 self.hooks.late_startup_hook()
527 self.hooks.late_startup_hook()
528 self.events.trigger('shell_initialized', self)
528 self.events.trigger('shell_initialized', self)
529 atexit.register(self.atexit_operations)
529 atexit.register(self.atexit_operations)
530
530
531 def get_ipython(self):
531 def get_ipython(self):
532 """Return the currently running IPython instance."""
532 """Return the currently running IPython instance."""
533 return self
533 return self
534
534
535 #-------------------------------------------------------------------------
535 #-------------------------------------------------------------------------
536 # Trait changed handlers
536 # Trait changed handlers
537 #-------------------------------------------------------------------------
537 #-------------------------------------------------------------------------
538
538
539 def _ipython_dir_changed(self, name, new):
539 def _ipython_dir_changed(self, name, new):
540 ensure_dir_exists(new)
540 ensure_dir_exists(new)
541
541
542 def set_autoindent(self,value=None):
542 def set_autoindent(self,value=None):
543 """Set the autoindent flag, checking for readline support.
543 """Set the autoindent flag, checking for readline support.
544
544
545 If called with no arguments, it acts as a toggle."""
545 If called with no arguments, it acts as a toggle."""
546
546
547 if value != 0 and not self.has_readline:
547 if value != 0 and not self.has_readline:
548 if os.name == 'posix':
548 if os.name == 'posix':
549 warn("The auto-indent feature requires the readline library")
549 warn("The auto-indent feature requires the readline library")
550 self.autoindent = 0
550 self.autoindent = 0
551 return
551 return
552 if value is None:
552 if value is None:
553 self.autoindent = not self.autoindent
553 self.autoindent = not self.autoindent
554 else:
554 else:
555 self.autoindent = value
555 self.autoindent = value
556
556
557 #-------------------------------------------------------------------------
557 #-------------------------------------------------------------------------
558 # init_* methods called by __init__
558 # init_* methods called by __init__
559 #-------------------------------------------------------------------------
559 #-------------------------------------------------------------------------
560
560
561 def init_ipython_dir(self, ipython_dir):
561 def init_ipython_dir(self, ipython_dir):
562 if ipython_dir is not None:
562 if ipython_dir is not None:
563 self.ipython_dir = ipython_dir
563 self.ipython_dir = ipython_dir
564 return
564 return
565
565
566 self.ipython_dir = get_ipython_dir()
566 self.ipython_dir = get_ipython_dir()
567
567
568 def init_profile_dir(self, profile_dir):
568 def init_profile_dir(self, profile_dir):
569 if profile_dir is not None:
569 if profile_dir is not None:
570 self.profile_dir = profile_dir
570 self.profile_dir = profile_dir
571 return
571 return
572 self.profile_dir =\
572 self.profile_dir =\
573 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
573 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
574
574
575 def init_instance_attrs(self):
575 def init_instance_attrs(self):
576 self.more = False
576 self.more = False
577
577
578 # command compiler
578 # command compiler
579 self.compile = CachingCompiler()
579 self.compile = CachingCompiler()
580
580
581 # Make an empty namespace, which extension writers can rely on both
581 # Make an empty namespace, which extension writers can rely on both
582 # existing and NEVER being used by ipython itself. This gives them a
582 # existing and NEVER being used by ipython itself. This gives them a
583 # convenient location for storing additional information and state
583 # convenient location for storing additional information and state
584 # their extensions may require, without fear of collisions with other
584 # their extensions may require, without fear of collisions with other
585 # ipython names that may develop later.
585 # ipython names that may develop later.
586 self.meta = Struct()
586 self.meta = Struct()
587
587
588 # Temporary files used for various purposes. Deleted at exit.
588 # Temporary files used for various purposes. Deleted at exit.
589 self.tempfiles = []
589 self.tempfiles = []
590 self.tempdirs = []
590 self.tempdirs = []
591
591
592 # Keep track of readline usage (later set by init_readline)
592 # Keep track of readline usage (later set by init_readline)
593 self.has_readline = False
593 self.has_readline = False
594
594
595 # keep track of where we started running (mainly for crash post-mortem)
595 # keep track of where we started running (mainly for crash post-mortem)
596 # This is not being used anywhere currently.
596 # This is not being used anywhere currently.
597 self.starting_dir = py3compat.getcwd()
597 self.starting_dir = py3compat.getcwd()
598
598
599 # Indentation management
599 # Indentation management
600 self.indent_current_nsp = 0
600 self.indent_current_nsp = 0
601
601
602 # Dict to track post-execution functions that have been registered
602 # Dict to track post-execution functions that have been registered
603 self._post_execute = {}
603 self._post_execute = {}
604
604
605 def init_environment(self):
605 def init_environment(self):
606 """Any changes we need to make to the user's environment."""
606 """Any changes we need to make to the user's environment."""
607 pass
607 pass
608
608
609 def init_encoding(self):
609 def init_encoding(self):
610 # Get system encoding at startup time. Certain terminals (like Emacs
610 # Get system encoding at startup time. Certain terminals (like Emacs
611 # under Win32 have it set to None, and we need to have a known valid
611 # under Win32 have it set to None, and we need to have a known valid
612 # encoding to use in the raw_input() method
612 # encoding to use in the raw_input() method
613 try:
613 try:
614 self.stdin_encoding = sys.stdin.encoding or 'ascii'
614 self.stdin_encoding = sys.stdin.encoding or 'ascii'
615 except AttributeError:
615 except AttributeError:
616 self.stdin_encoding = 'ascii'
616 self.stdin_encoding = 'ascii'
617
617
618 def init_syntax_highlighting(self):
618 def init_syntax_highlighting(self):
619 # Python source parser/formatter for syntax highlighting
619 # Python source parser/formatter for syntax highlighting
620 pyformat = PyColorize.Parser().format
620 pyformat = PyColorize.Parser().format
621 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
621 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
622
622
623 def init_pushd_popd_magic(self):
623 def init_pushd_popd_magic(self):
624 # for pushd/popd management
624 # for pushd/popd management
625 self.home_dir = get_home_dir()
625 self.home_dir = get_home_dir()
626
626
627 self.dir_stack = []
627 self.dir_stack = []
628
628
629 def init_logger(self):
629 def init_logger(self):
630 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
630 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
631 logmode='rotate')
631 logmode='rotate')
632
632
633 def init_logstart(self):
633 def init_logstart(self):
634 """Initialize logging in case it was requested at the command line.
634 """Initialize logging in case it was requested at the command line.
635 """
635 """
636 if self.logappend:
636 if self.logappend:
637 self.magic('logstart %s append' % self.logappend)
637 self.magic('logstart %s append' % self.logappend)
638 elif self.logfile:
638 elif self.logfile:
639 self.magic('logstart %s' % self.logfile)
639 self.magic('logstart %s' % self.logfile)
640 elif self.logstart:
640 elif self.logstart:
641 self.magic('logstart')
641 self.magic('logstart')
642
642
643 def init_builtins(self):
643 def init_builtins(self):
644 # A single, static flag that we set to True. Its presence indicates
644 # A single, static flag that we set to True. Its presence indicates
645 # that an IPython shell has been created, and we make no attempts at
645 # that an IPython shell has been created, and we make no attempts at
646 # removing on exit or representing the existence of more than one
646 # removing on exit or representing the existence of more than one
647 # IPython at a time.
647 # IPython at a time.
648 builtin_mod.__dict__['__IPYTHON__'] = True
648 builtin_mod.__dict__['__IPYTHON__'] = True
649
649
650 # In 0.11 we introduced '__IPYTHON__active' as an integer we'd try to
650 # In 0.11 we introduced '__IPYTHON__active' as an integer we'd try to
651 # manage on enter/exit, but with all our shells it's virtually
651 # manage on enter/exit, but with all our shells it's virtually
652 # impossible to get all the cases right. We're leaving the name in for
652 # impossible to get all the cases right. We're leaving the name in for
653 # those who adapted their codes to check for this flag, but will
653 # those who adapted their codes to check for this flag, but will
654 # eventually remove it after a few more releases.
654 # eventually remove it after a few more releases.
655 builtin_mod.__dict__['__IPYTHON__active'] = \
655 builtin_mod.__dict__['__IPYTHON__active'] = \
656 'Deprecated, check for __IPYTHON__'
656 'Deprecated, check for __IPYTHON__'
657
657
658 self.builtin_trap = BuiltinTrap(shell=self)
658 self.builtin_trap = BuiltinTrap(shell=self)
659
659
660 def init_inspector(self):
660 def init_inspector(self):
661 # Object inspector
661 # Object inspector
662 self.inspector = oinspect.Inspector(oinspect.InspectColors,
662 self.inspector = oinspect.Inspector(oinspect.InspectColors,
663 PyColorize.ANSICodeColors,
663 PyColorize.ANSICodeColors,
664 'NoColor',
664 'NoColor',
665 self.object_info_string_level)
665 self.object_info_string_level)
666
666
667 def init_io(self):
667 def init_io(self):
668 # This will just use sys.stdout and sys.stderr. If you want to
668 # This will just use sys.stdout and sys.stderr. If you want to
669 # override sys.stdout and sys.stderr themselves, you need to do that
669 # override sys.stdout and sys.stderr themselves, you need to do that
670 # *before* instantiating this class, because io holds onto
670 # *before* instantiating this class, because io holds onto
671 # references to the underlying streams.
671 # references to the underlying streams.
672 if (sys.platform == 'win32' or sys.platform == 'cli') and self.has_readline:
672 if (sys.platform == 'win32' or sys.platform == 'cli') and self.has_readline:
673 io.stdout = io.stderr = io.IOStream(self.readline._outputfile)
673 io.stdout = io.stderr = io.IOStream(self.readline._outputfile)
674 else:
674 else:
675 io.stdout = io.IOStream(sys.stdout)
675 io.stdout = io.IOStream(sys.stdout)
676 io.stderr = io.IOStream(sys.stderr)
676 io.stderr = io.IOStream(sys.stderr)
677
677
678 def init_prompts(self):
678 def init_prompts(self):
679 self.prompt_manager = PromptManager(shell=self, parent=self)
679 self.prompt_manager = PromptManager(shell=self, parent=self)
680 self.configurables.append(self.prompt_manager)
680 self.configurables.append(self.prompt_manager)
681 # Set system prompts, so that scripts can decide if they are running
681 # Set system prompts, so that scripts can decide if they are running
682 # interactively.
682 # interactively.
683 sys.ps1 = 'In : '
683 sys.ps1 = 'In : '
684 sys.ps2 = '...: '
684 sys.ps2 = '...: '
685 sys.ps3 = 'Out: '
685 sys.ps3 = 'Out: '
686
686
687 def init_display_formatter(self):
687 def init_display_formatter(self):
688 self.display_formatter = DisplayFormatter(parent=self)
688 self.display_formatter = DisplayFormatter(parent=self)
689 self.configurables.append(self.display_formatter)
689 self.configurables.append(self.display_formatter)
690
690
691 def init_display_pub(self):
691 def init_display_pub(self):
692 self.display_pub = self.display_pub_class(parent=self)
692 self.display_pub = self.display_pub_class(parent=self)
693 self.configurables.append(self.display_pub)
693 self.configurables.append(self.display_pub)
694
694
695 def init_data_pub(self):
695 def init_data_pub(self):
696 if not self.data_pub_class:
696 if not self.data_pub_class:
697 self.data_pub = None
697 self.data_pub = None
698 return
698 return
699 self.data_pub = self.data_pub_class(parent=self)
699 self.data_pub = self.data_pub_class(parent=self)
700 self.configurables.append(self.data_pub)
700 self.configurables.append(self.data_pub)
701
701
702 def init_displayhook(self):
702 def init_displayhook(self):
703 # Initialize displayhook, set in/out prompts and printing system
703 # Initialize displayhook, set in/out prompts and printing system
704 self.displayhook = self.displayhook_class(
704 self.displayhook = self.displayhook_class(
705 parent=self,
705 parent=self,
706 shell=self,
706 shell=self,
707 cache_size=self.cache_size,
707 cache_size=self.cache_size,
708 )
708 )
709 self.configurables.append(self.displayhook)
709 self.configurables.append(self.displayhook)
710 # This is a context manager that installs/revmoes the displayhook at
710 # This is a context manager that installs/revmoes the displayhook at
711 # the appropriate time.
711 # the appropriate time.
712 self.display_trap = DisplayTrap(hook=self.displayhook)
712 self.display_trap = DisplayTrap(hook=self.displayhook)
713
713
714 def init_latextool(self):
714 def init_latextool(self):
715 """Configure LaTeXTool."""
715 """Configure LaTeXTool."""
716 cfg = LaTeXTool.instance(parent=self)
716 cfg = LaTeXTool.instance(parent=self)
717 if cfg not in self.configurables:
717 if cfg not in self.configurables:
718 self.configurables.append(cfg)
718 self.configurables.append(cfg)
719
719
720 def init_virtualenv(self):
720 def init_virtualenv(self):
721 """Add a virtualenv to sys.path so the user can import modules from it.
721 """Add a virtualenv to sys.path so the user can import modules from it.
722 This isn't perfect: it doesn't use the Python interpreter with which the
722 This isn't perfect: it doesn't use the Python interpreter with which the
723 virtualenv was built, and it ignores the --no-site-packages option. A
723 virtualenv was built, and it ignores the --no-site-packages option. A
724 warning will appear suggesting the user installs IPython in the
724 warning will appear suggesting the user installs IPython in the
725 virtualenv, but for many cases, it probably works well enough.
725 virtualenv, but for many cases, it probably works well enough.
726
726
727 Adapted from code snippets online.
727 Adapted from code snippets online.
728
728
729 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
729 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
730 """
730 """
731 if 'VIRTUAL_ENV' not in os.environ:
731 if 'VIRTUAL_ENV' not in os.environ:
732 # Not in a virtualenv
732 # Not in a virtualenv
733 return
733 return
734
734
735 # venv detection:
735 # venv detection:
736 # stdlib venv may symlink sys.executable, so we can't use realpath.
736 # stdlib venv may symlink sys.executable, so we can't use realpath.
737 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
737 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
738 # So we just check every item in the symlink tree (generally <= 3)
738 # So we just check every item in the symlink tree (generally <= 3)
739 p = os.path.normcase(sys.executable)
739 p = os.path.normcase(sys.executable)
740 paths = [p]
740 paths = [p]
741 while os.path.islink(p):
741 while os.path.islink(p):
742 p = os.path.normcase(os.path.join(os.path.dirname(p), os.readlink(p)))
742 p = os.path.normcase(os.path.join(os.path.dirname(p), os.readlink(p)))
743 paths.append(p)
743 paths.append(p)
744 p_venv = os.path.normcase(os.environ['VIRTUAL_ENV'])
744 p_venv = os.path.normcase(os.environ['VIRTUAL_ENV'])
745 if any(p.startswith(p_venv) for p in paths):
745 if any(p.startswith(p_venv) for p in paths):
746 # Running properly in the virtualenv, don't need to do anything
746 # Running properly in the virtualenv, don't need to do anything
747 return
747 return
748
748
749 warn("Attempting to work in a virtualenv. If you encounter problems, please "
749 warn("Attempting to work in a virtualenv. If you encounter problems, please "
750 "install IPython inside the virtualenv.")
750 "install IPython inside the virtualenv.")
751 if sys.platform == "win32":
751 if sys.platform == "win32":
752 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
752 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
753 else:
753 else:
754 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
754 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
755 'python%d.%d' % sys.version_info[:2], 'site-packages')
755 'python%d.%d' % sys.version_info[:2], 'site-packages')
756
756
757 import site
757 import site
758 sys.path.insert(0, virtual_env)
758 sys.path.insert(0, virtual_env)
759 site.addsitedir(virtual_env)
759 site.addsitedir(virtual_env)
760
760
761 #-------------------------------------------------------------------------
761 #-------------------------------------------------------------------------
762 # Things related to injections into the sys module
762 # Things related to injections into the sys module
763 #-------------------------------------------------------------------------
763 #-------------------------------------------------------------------------
764
764
765 def save_sys_module_state(self):
765 def save_sys_module_state(self):
766 """Save the state of hooks in the sys module.
766 """Save the state of hooks in the sys module.
767
767
768 This has to be called after self.user_module is created.
768 This has to be called after self.user_module is created.
769 """
769 """
770 self._orig_sys_module_state = {}
770 self._orig_sys_module_state = {}
771 self._orig_sys_module_state['stdin'] = sys.stdin
771 self._orig_sys_module_state['stdin'] = sys.stdin
772 self._orig_sys_module_state['stdout'] = sys.stdout
772 self._orig_sys_module_state['stdout'] = sys.stdout
773 self._orig_sys_module_state['stderr'] = sys.stderr
773 self._orig_sys_module_state['stderr'] = sys.stderr
774 self._orig_sys_module_state['excepthook'] = sys.excepthook
774 self._orig_sys_module_state['excepthook'] = sys.excepthook
775 self._orig_sys_modules_main_name = self.user_module.__name__
775 self._orig_sys_modules_main_name = self.user_module.__name__
776 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
776 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
777
777
778 def restore_sys_module_state(self):
778 def restore_sys_module_state(self):
779 """Restore the state of the sys module."""
779 """Restore the state of the sys module."""
780 try:
780 try:
781 for k, v in iteritems(self._orig_sys_module_state):
781 for k, v in iteritems(self._orig_sys_module_state):
782 setattr(sys, k, v)
782 setattr(sys, k, v)
783 except AttributeError:
783 except AttributeError:
784 pass
784 pass
785 # Reset what what done in self.init_sys_modules
785 # Reset what what done in self.init_sys_modules
786 if self._orig_sys_modules_main_mod is not None:
786 if self._orig_sys_modules_main_mod is not None:
787 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
787 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
788
788
789 #-------------------------------------------------------------------------
789 #-------------------------------------------------------------------------
790 # Things related to the banner
790 # Things related to the banner
791 #-------------------------------------------------------------------------
791 #-------------------------------------------------------------------------
792
792
793 @property
793 @property
794 def banner(self):
794 def banner(self):
795 banner = self.banner1
795 banner = self.banner1
796 if self.profile and self.profile != 'default':
796 if self.profile and self.profile != 'default':
797 banner += '\nIPython profile: %s\n' % self.profile
797 banner += '\nIPython profile: %s\n' % self.profile
798 if self.banner2:
798 if self.banner2:
799 banner += '\n' + self.banner2
799 banner += '\n' + self.banner2
800 return banner
800 return banner
801
801
802 def show_banner(self, banner=None):
802 def show_banner(self, banner=None):
803 if banner is None:
803 if banner is None:
804 banner = self.banner
804 banner = self.banner
805 self.write(banner)
805 self.write(banner)
806
806
807 #-------------------------------------------------------------------------
807 #-------------------------------------------------------------------------
808 # Things related to hooks
808 # Things related to hooks
809 #-------------------------------------------------------------------------
809 #-------------------------------------------------------------------------
810
810
811 def init_hooks(self):
811 def init_hooks(self):
812 # hooks holds pointers used for user-side customizations
812 # hooks holds pointers used for user-side customizations
813 self.hooks = Struct()
813 self.hooks = Struct()
814
814
815 self.strdispatchers = {}
815 self.strdispatchers = {}
816
816
817 # Set all default hooks, defined in the IPython.hooks module.
817 # Set all default hooks, defined in the IPython.hooks module.
818 hooks = IPython.core.hooks
818 hooks = IPython.core.hooks
819 for hook_name in hooks.__all__:
819 for hook_name in hooks.__all__:
820 # default hooks have priority 100, i.e. low; user hooks should have
820 # default hooks have priority 100, i.e. low; user hooks should have
821 # 0-100 priority
821 # 0-100 priority
822 self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
822 self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
823
823
824 def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
824 def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
825 _warn_deprecated=True):
825 _warn_deprecated=True):
826 """set_hook(name,hook) -> sets an internal IPython hook.
826 """set_hook(name,hook) -> sets an internal IPython hook.
827
827
828 IPython exposes some of its internal API as user-modifiable hooks. By
828 IPython exposes some of its internal API as user-modifiable hooks. By
829 adding your function to one of these hooks, you can modify IPython's
829 adding your function to one of these hooks, you can modify IPython's
830 behavior to call at runtime your own routines."""
830 behavior to call at runtime your own routines."""
831
831
832 # At some point in the future, this should validate the hook before it
832 # At some point in the future, this should validate the hook before it
833 # accepts it. Probably at least check that the hook takes the number
833 # accepts it. Probably at least check that the hook takes the number
834 # of args it's supposed to.
834 # of args it's supposed to.
835
835
836 f = types.MethodType(hook,self)
836 f = types.MethodType(hook,self)
837
837
838 # check if the hook is for strdispatcher first
838 # check if the hook is for strdispatcher first
839 if str_key is not None:
839 if str_key is not None:
840 sdp = self.strdispatchers.get(name, StrDispatch())
840 sdp = self.strdispatchers.get(name, StrDispatch())
841 sdp.add_s(str_key, f, priority )
841 sdp.add_s(str_key, f, priority )
842 self.strdispatchers[name] = sdp
842 self.strdispatchers[name] = sdp
843 return
843 return
844 if re_key is not None:
844 if re_key is not None:
845 sdp = self.strdispatchers.get(name, StrDispatch())
845 sdp = self.strdispatchers.get(name, StrDispatch())
846 sdp.add_re(re.compile(re_key), f, priority )
846 sdp.add_re(re.compile(re_key), f, priority )
847 self.strdispatchers[name] = sdp
847 self.strdispatchers[name] = sdp
848 return
848 return
849
849
850 dp = getattr(self.hooks, name, None)
850 dp = getattr(self.hooks, name, None)
851 if name not in IPython.core.hooks.__all__:
851 if name not in IPython.core.hooks.__all__:
852 print("Warning! Hook '%s' is not one of %s" % \
852 print("Warning! Hook '%s' is not one of %s" % \
853 (name, IPython.core.hooks.__all__ ))
853 (name, IPython.core.hooks.__all__ ))
854
854
855 if _warn_deprecated and (name in IPython.core.hooks.deprecated):
855 if _warn_deprecated and (name in IPython.core.hooks.deprecated):
856 alternative = IPython.core.hooks.deprecated[name]
856 alternative = IPython.core.hooks.deprecated[name]
857 warn("Hook {} is deprecated. Use {} instead.".format(name, alternative))
857 warn("Hook {} is deprecated. Use {} instead.".format(name, alternative))
858
858
859 if not dp:
859 if not dp:
860 dp = IPython.core.hooks.CommandChainDispatcher()
860 dp = IPython.core.hooks.CommandChainDispatcher()
861
861
862 try:
862 try:
863 dp.add(f,priority)
863 dp.add(f,priority)
864 except AttributeError:
864 except AttributeError:
865 # it was not commandchain, plain old func - replace
865 # it was not commandchain, plain old func - replace
866 dp = f
866 dp = f
867
867
868 setattr(self.hooks,name, dp)
868 setattr(self.hooks,name, dp)
869
869
870 #-------------------------------------------------------------------------
870 #-------------------------------------------------------------------------
871 # Things related to events
871 # Things related to events
872 #-------------------------------------------------------------------------
872 #-------------------------------------------------------------------------
873
873
874 def init_events(self):
874 def init_events(self):
875 self.events = EventManager(self, available_events)
875 self.events = EventManager(self, available_events)
876
876
877 self.events.register("pre_execute", self._clear_warning_registry)
878
877 def register_post_execute(self, func):
879 def register_post_execute(self, func):
878 """DEPRECATED: Use ip.events.register('post_run_cell', func)
880 """DEPRECATED: Use ip.events.register('post_run_cell', func)
879
881
880 Register a function for calling after code execution.
882 Register a function for calling after code execution.
881 """
883 """
882 warn("ip.register_post_execute is deprecated, use "
884 warn("ip.register_post_execute is deprecated, use "
883 "ip.events.register('post_run_cell', func) instead.")
885 "ip.events.register('post_run_cell', func) instead.")
884 self.events.register('post_run_cell', func)
886 self.events.register('post_run_cell', func)
885
887
888 def _clear_warning_registry(self):
889 # clear the warning registry, so that different code blocks with
890 # overlapping line number ranges don't cause spurious suppression of
891 # warnings (see gh-6611 for details)
892 if "__warningregistry__" in self.user_global_ns:
893 del self.user_global_ns["__warningregistry__"]
894
886 #-------------------------------------------------------------------------
895 #-------------------------------------------------------------------------
887 # Things related to the "main" module
896 # Things related to the "main" module
888 #-------------------------------------------------------------------------
897 #-------------------------------------------------------------------------
889
898
890 def new_main_mod(self, filename, modname):
899 def new_main_mod(self, filename, modname):
891 """Return a new 'main' module object for user code execution.
900 """Return a new 'main' module object for user code execution.
892
901
893 ``filename`` should be the path of the script which will be run in the
902 ``filename`` should be the path of the script which will be run in the
894 module. Requests with the same filename will get the same module, with
903 module. Requests with the same filename will get the same module, with
895 its namespace cleared.
904 its namespace cleared.
896
905
897 ``modname`` should be the module name - normally either '__main__' or
906 ``modname`` should be the module name - normally either '__main__' or
898 the basename of the file without the extension.
907 the basename of the file without the extension.
899
908
900 When scripts are executed via %run, we must keep a reference to their
909 When scripts are executed via %run, we must keep a reference to their
901 __main__ module around so that Python doesn't
910 __main__ module around so that Python doesn't
902 clear it, rendering references to module globals useless.
911 clear it, rendering references to module globals useless.
903
912
904 This method keeps said reference in a private dict, keyed by the
913 This method keeps said reference in a private dict, keyed by the
905 absolute path of the script. This way, for multiple executions of the
914 absolute path of the script. This way, for multiple executions of the
906 same script we only keep one copy of the namespace (the last one),
915 same script we only keep one copy of the namespace (the last one),
907 thus preventing memory leaks from old references while allowing the
916 thus preventing memory leaks from old references while allowing the
908 objects from the last execution to be accessible.
917 objects from the last execution to be accessible.
909 """
918 """
910 filename = os.path.abspath(filename)
919 filename = os.path.abspath(filename)
911 try:
920 try:
912 main_mod = self._main_mod_cache[filename]
921 main_mod = self._main_mod_cache[filename]
913 except KeyError:
922 except KeyError:
914 main_mod = self._main_mod_cache[filename] = types.ModuleType(
923 main_mod = self._main_mod_cache[filename] = types.ModuleType(
915 py3compat.cast_bytes_py2(modname),
924 py3compat.cast_bytes_py2(modname),
916 doc="Module created for script run in IPython")
925 doc="Module created for script run in IPython")
917 else:
926 else:
918 main_mod.__dict__.clear()
927 main_mod.__dict__.clear()
919 main_mod.__name__ = modname
928 main_mod.__name__ = modname
920
929
921 main_mod.__file__ = filename
930 main_mod.__file__ = filename
922 # It seems pydoc (and perhaps others) needs any module instance to
931 # It seems pydoc (and perhaps others) needs any module instance to
923 # implement a __nonzero__ method
932 # implement a __nonzero__ method
924 main_mod.__nonzero__ = lambda : True
933 main_mod.__nonzero__ = lambda : True
925
934
926 return main_mod
935 return main_mod
927
936
928 def clear_main_mod_cache(self):
937 def clear_main_mod_cache(self):
929 """Clear the cache of main modules.
938 """Clear the cache of main modules.
930
939
931 Mainly for use by utilities like %reset.
940 Mainly for use by utilities like %reset.
932
941
933 Examples
942 Examples
934 --------
943 --------
935
944
936 In [15]: import IPython
945 In [15]: import IPython
937
946
938 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
947 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
939
948
940 In [17]: len(_ip._main_mod_cache) > 0
949 In [17]: len(_ip._main_mod_cache) > 0
941 Out[17]: True
950 Out[17]: True
942
951
943 In [18]: _ip.clear_main_mod_cache()
952 In [18]: _ip.clear_main_mod_cache()
944
953
945 In [19]: len(_ip._main_mod_cache) == 0
954 In [19]: len(_ip._main_mod_cache) == 0
946 Out[19]: True
955 Out[19]: True
947 """
956 """
948 self._main_mod_cache.clear()
957 self._main_mod_cache.clear()
949
958
950 #-------------------------------------------------------------------------
959 #-------------------------------------------------------------------------
951 # Things related to debugging
960 # Things related to debugging
952 #-------------------------------------------------------------------------
961 #-------------------------------------------------------------------------
953
962
954 def init_pdb(self):
963 def init_pdb(self):
955 # Set calling of pdb on exceptions
964 # Set calling of pdb on exceptions
956 # self.call_pdb is a property
965 # self.call_pdb is a property
957 self.call_pdb = self.pdb
966 self.call_pdb = self.pdb
958
967
959 def _get_call_pdb(self):
968 def _get_call_pdb(self):
960 return self._call_pdb
969 return self._call_pdb
961
970
962 def _set_call_pdb(self,val):
971 def _set_call_pdb(self,val):
963
972
964 if val not in (0,1,False,True):
973 if val not in (0,1,False,True):
965 raise ValueError('new call_pdb value must be boolean')
974 raise ValueError('new call_pdb value must be boolean')
966
975
967 # store value in instance
976 # store value in instance
968 self._call_pdb = val
977 self._call_pdb = val
969
978
970 # notify the actual exception handlers
979 # notify the actual exception handlers
971 self.InteractiveTB.call_pdb = val
980 self.InteractiveTB.call_pdb = val
972
981
973 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
982 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
974 'Control auto-activation of pdb at exceptions')
983 'Control auto-activation of pdb at exceptions')
975
984
976 def debugger(self,force=False):
985 def debugger(self,force=False):
977 """Call the pydb/pdb debugger.
986 """Call the pydb/pdb debugger.
978
987
979 Keywords:
988 Keywords:
980
989
981 - force(False): by default, this routine checks the instance call_pdb
990 - force(False): by default, this routine checks the instance call_pdb
982 flag and does not actually invoke the debugger if the flag is false.
991 flag and does not actually invoke the debugger if the flag is false.
983 The 'force' option forces the debugger to activate even if the flag
992 The 'force' option forces the debugger to activate even if the flag
984 is false.
993 is false.
985 """
994 """
986
995
987 if not (force or self.call_pdb):
996 if not (force or self.call_pdb):
988 return
997 return
989
998
990 if not hasattr(sys,'last_traceback'):
999 if not hasattr(sys,'last_traceback'):
991 error('No traceback has been produced, nothing to debug.')
1000 error('No traceback has been produced, nothing to debug.')
992 return
1001 return
993
1002
994 # use pydb if available
1003 # use pydb if available
995 if debugger.has_pydb:
1004 if debugger.has_pydb:
996 from pydb import pm
1005 from pydb import pm
997 else:
1006 else:
998 # fallback to our internal debugger
1007 # fallback to our internal debugger
999 pm = lambda : self.InteractiveTB.debugger(force=True)
1008 pm = lambda : self.InteractiveTB.debugger(force=True)
1000
1009
1001 with self.readline_no_record:
1010 with self.readline_no_record:
1002 pm()
1011 pm()
1003
1012
1004 #-------------------------------------------------------------------------
1013 #-------------------------------------------------------------------------
1005 # Things related to IPython's various namespaces
1014 # Things related to IPython's various namespaces
1006 #-------------------------------------------------------------------------
1015 #-------------------------------------------------------------------------
1007 default_user_namespaces = True
1016 default_user_namespaces = True
1008
1017
1009 def init_create_namespaces(self, user_module=None, user_ns=None):
1018 def init_create_namespaces(self, user_module=None, user_ns=None):
1010 # Create the namespace where the user will operate. user_ns is
1019 # Create the namespace where the user will operate. user_ns is
1011 # normally the only one used, and it is passed to the exec calls as
1020 # normally the only one used, and it is passed to the exec calls as
1012 # the locals argument. But we do carry a user_global_ns namespace
1021 # the locals argument. But we do carry a user_global_ns namespace
1013 # given as the exec 'globals' argument, This is useful in embedding
1022 # given as the exec 'globals' argument, This is useful in embedding
1014 # situations where the ipython shell opens in a context where the
1023 # situations where the ipython shell opens in a context where the
1015 # distinction between locals and globals is meaningful. For
1024 # distinction between locals and globals is meaningful. For
1016 # non-embedded contexts, it is just the same object as the user_ns dict.
1025 # non-embedded contexts, it is just the same object as the user_ns dict.
1017
1026
1018 # FIXME. For some strange reason, __builtins__ is showing up at user
1027 # FIXME. For some strange reason, __builtins__ is showing up at user
1019 # level as a dict instead of a module. This is a manual fix, but I
1028 # level as a dict instead of a module. This is a manual fix, but I
1020 # should really track down where the problem is coming from. Alex
1029 # should really track down where the problem is coming from. Alex
1021 # Schmolck reported this problem first.
1030 # Schmolck reported this problem first.
1022
1031
1023 # A useful post by Alex Martelli on this topic:
1032 # A useful post by Alex Martelli on this topic:
1024 # Re: inconsistent value from __builtins__
1033 # Re: inconsistent value from __builtins__
1025 # Von: Alex Martelli <aleaxit@yahoo.com>
1034 # Von: Alex Martelli <aleaxit@yahoo.com>
1026 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1035 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1027 # Gruppen: comp.lang.python
1036 # Gruppen: comp.lang.python
1028
1037
1029 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1038 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1030 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1039 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1031 # > <type 'dict'>
1040 # > <type 'dict'>
1032 # > >>> print type(__builtins__)
1041 # > >>> print type(__builtins__)
1033 # > <type 'module'>
1042 # > <type 'module'>
1034 # > Is this difference in return value intentional?
1043 # > Is this difference in return value intentional?
1035
1044
1036 # Well, it's documented that '__builtins__' can be either a dictionary
1045 # Well, it's documented that '__builtins__' can be either a dictionary
1037 # or a module, and it's been that way for a long time. Whether it's
1046 # or a module, and it's been that way for a long time. Whether it's
1038 # intentional (or sensible), I don't know. In any case, the idea is
1047 # intentional (or sensible), I don't know. In any case, the idea is
1039 # that if you need to access the built-in namespace directly, you
1048 # that if you need to access the built-in namespace directly, you
1040 # should start with "import __builtin__" (note, no 's') which will
1049 # should start with "import __builtin__" (note, no 's') which will
1041 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1050 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1042
1051
1043 # These routines return a properly built module and dict as needed by
1052 # These routines return a properly built module and dict as needed by
1044 # the rest of the code, and can also be used by extension writers to
1053 # the rest of the code, and can also be used by extension writers to
1045 # generate properly initialized namespaces.
1054 # generate properly initialized namespaces.
1046 if (user_ns is not None) or (user_module is not None):
1055 if (user_ns is not None) or (user_module is not None):
1047 self.default_user_namespaces = False
1056 self.default_user_namespaces = False
1048 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1057 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1049
1058
1050 # A record of hidden variables we have added to the user namespace, so
1059 # A record of hidden variables we have added to the user namespace, so
1051 # we can list later only variables defined in actual interactive use.
1060 # we can list later only variables defined in actual interactive use.
1052 self.user_ns_hidden = {}
1061 self.user_ns_hidden = {}
1053
1062
1054 # Now that FakeModule produces a real module, we've run into a nasty
1063 # Now that FakeModule produces a real module, we've run into a nasty
1055 # problem: after script execution (via %run), the module where the user
1064 # problem: after script execution (via %run), the module where the user
1056 # code ran is deleted. Now that this object is a true module (needed
1065 # code ran is deleted. Now that this object is a true module (needed
1057 # so docetst and other tools work correctly), the Python module
1066 # so docetst and other tools work correctly), the Python module
1058 # teardown mechanism runs over it, and sets to None every variable
1067 # teardown mechanism runs over it, and sets to None every variable
1059 # present in that module. Top-level references to objects from the
1068 # present in that module. Top-level references to objects from the
1060 # script survive, because the user_ns is updated with them. However,
1069 # script survive, because the user_ns is updated with them. However,
1061 # calling functions defined in the script that use other things from
1070 # calling functions defined in the script that use other things from
1062 # the script will fail, because the function's closure had references
1071 # the script will fail, because the function's closure had references
1063 # to the original objects, which are now all None. So we must protect
1072 # to the original objects, which are now all None. So we must protect
1064 # these modules from deletion by keeping a cache.
1073 # these modules from deletion by keeping a cache.
1065 #
1074 #
1066 # To avoid keeping stale modules around (we only need the one from the
1075 # To avoid keeping stale modules around (we only need the one from the
1067 # last run), we use a dict keyed with the full path to the script, so
1076 # last run), we use a dict keyed with the full path to the script, so
1068 # only the last version of the module is held in the cache. Note,
1077 # only the last version of the module is held in the cache. Note,
1069 # however, that we must cache the module *namespace contents* (their
1078 # however, that we must cache the module *namespace contents* (their
1070 # __dict__). Because if we try to cache the actual modules, old ones
1079 # __dict__). Because if we try to cache the actual modules, old ones
1071 # (uncached) could be destroyed while still holding references (such as
1080 # (uncached) could be destroyed while still holding references (such as
1072 # those held by GUI objects that tend to be long-lived)>
1081 # those held by GUI objects that tend to be long-lived)>
1073 #
1082 #
1074 # The %reset command will flush this cache. See the cache_main_mod()
1083 # The %reset command will flush this cache. See the cache_main_mod()
1075 # and clear_main_mod_cache() methods for details on use.
1084 # and clear_main_mod_cache() methods for details on use.
1076
1085
1077 # This is the cache used for 'main' namespaces
1086 # This is the cache used for 'main' namespaces
1078 self._main_mod_cache = {}
1087 self._main_mod_cache = {}
1079
1088
1080 # A table holding all the namespaces IPython deals with, so that
1089 # A table holding all the namespaces IPython deals with, so that
1081 # introspection facilities can search easily.
1090 # introspection facilities can search easily.
1082 self.ns_table = {'user_global':self.user_module.__dict__,
1091 self.ns_table = {'user_global':self.user_module.__dict__,
1083 'user_local':self.user_ns,
1092 'user_local':self.user_ns,
1084 'builtin':builtin_mod.__dict__
1093 'builtin':builtin_mod.__dict__
1085 }
1094 }
1086
1095
1087 @property
1096 @property
1088 def user_global_ns(self):
1097 def user_global_ns(self):
1089 return self.user_module.__dict__
1098 return self.user_module.__dict__
1090
1099
1091 def prepare_user_module(self, user_module=None, user_ns=None):
1100 def prepare_user_module(self, user_module=None, user_ns=None):
1092 """Prepare the module and namespace in which user code will be run.
1101 """Prepare the module and namespace in which user code will be run.
1093
1102
1094 When IPython is started normally, both parameters are None: a new module
1103 When IPython is started normally, both parameters are None: a new module
1095 is created automatically, and its __dict__ used as the namespace.
1104 is created automatically, and its __dict__ used as the namespace.
1096
1105
1097 If only user_module is provided, its __dict__ is used as the namespace.
1106 If only user_module is provided, its __dict__ is used as the namespace.
1098 If only user_ns is provided, a dummy module is created, and user_ns
1107 If only user_ns is provided, a dummy module is created, and user_ns
1099 becomes the global namespace. If both are provided (as they may be
1108 becomes the global namespace. If both are provided (as they may be
1100 when embedding), user_ns is the local namespace, and user_module
1109 when embedding), user_ns is the local namespace, and user_module
1101 provides the global namespace.
1110 provides the global namespace.
1102
1111
1103 Parameters
1112 Parameters
1104 ----------
1113 ----------
1105 user_module : module, optional
1114 user_module : module, optional
1106 The current user module in which IPython is being run. If None,
1115 The current user module in which IPython is being run. If None,
1107 a clean module will be created.
1116 a clean module will be created.
1108 user_ns : dict, optional
1117 user_ns : dict, optional
1109 A namespace in which to run interactive commands.
1118 A namespace in which to run interactive commands.
1110
1119
1111 Returns
1120 Returns
1112 -------
1121 -------
1113 A tuple of user_module and user_ns, each properly initialised.
1122 A tuple of user_module and user_ns, each properly initialised.
1114 """
1123 """
1115 if user_module is None and user_ns is not None:
1124 if user_module is None and user_ns is not None:
1116 user_ns.setdefault("__name__", "__main__")
1125 user_ns.setdefault("__name__", "__main__")
1117 user_module = DummyMod()
1126 user_module = DummyMod()
1118 user_module.__dict__ = user_ns
1127 user_module.__dict__ = user_ns
1119
1128
1120 if user_module is None:
1129 if user_module is None:
1121 user_module = types.ModuleType("__main__",
1130 user_module = types.ModuleType("__main__",
1122 doc="Automatically created module for IPython interactive environment")
1131 doc="Automatically created module for IPython interactive environment")
1123
1132
1124 # We must ensure that __builtin__ (without the final 's') is always
1133 # We must ensure that __builtin__ (without the final 's') is always
1125 # available and pointing to the __builtin__ *module*. For more details:
1134 # available and pointing to the __builtin__ *module*. For more details:
1126 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1135 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1127 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1136 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1128 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1137 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1129
1138
1130 if user_ns is None:
1139 if user_ns is None:
1131 user_ns = user_module.__dict__
1140 user_ns = user_module.__dict__
1132
1141
1133 return user_module, user_ns
1142 return user_module, user_ns
1134
1143
1135 def init_sys_modules(self):
1144 def init_sys_modules(self):
1136 # We need to insert into sys.modules something that looks like a
1145 # We need to insert into sys.modules something that looks like a
1137 # module but which accesses the IPython namespace, for shelve and
1146 # module but which accesses the IPython namespace, for shelve and
1138 # pickle to work interactively. Normally they rely on getting
1147 # pickle to work interactively. Normally they rely on getting
1139 # everything out of __main__, but for embedding purposes each IPython
1148 # everything out of __main__, but for embedding purposes each IPython
1140 # instance has its own private namespace, so we can't go shoving
1149 # instance has its own private namespace, so we can't go shoving
1141 # everything into __main__.
1150 # everything into __main__.
1142
1151
1143 # note, however, that we should only do this for non-embedded
1152 # note, however, that we should only do this for non-embedded
1144 # ipythons, which really mimic the __main__.__dict__ with their own
1153 # ipythons, which really mimic the __main__.__dict__ with their own
1145 # namespace. Embedded instances, on the other hand, should not do
1154 # namespace. Embedded instances, on the other hand, should not do
1146 # this because they need to manage the user local/global namespaces
1155 # this because they need to manage the user local/global namespaces
1147 # only, but they live within a 'normal' __main__ (meaning, they
1156 # only, but they live within a 'normal' __main__ (meaning, they
1148 # shouldn't overtake the execution environment of the script they're
1157 # shouldn't overtake the execution environment of the script they're
1149 # embedded in).
1158 # embedded in).
1150
1159
1151 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1160 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1152 main_name = self.user_module.__name__
1161 main_name = self.user_module.__name__
1153 sys.modules[main_name] = self.user_module
1162 sys.modules[main_name] = self.user_module
1154
1163
1155 def init_user_ns(self):
1164 def init_user_ns(self):
1156 """Initialize all user-visible namespaces to their minimum defaults.
1165 """Initialize all user-visible namespaces to their minimum defaults.
1157
1166
1158 Certain history lists are also initialized here, as they effectively
1167 Certain history lists are also initialized here, as they effectively
1159 act as user namespaces.
1168 act as user namespaces.
1160
1169
1161 Notes
1170 Notes
1162 -----
1171 -----
1163 All data structures here are only filled in, they are NOT reset by this
1172 All data structures here are only filled in, they are NOT reset by this
1164 method. If they were not empty before, data will simply be added to
1173 method. If they were not empty before, data will simply be added to
1165 therm.
1174 therm.
1166 """
1175 """
1167 # This function works in two parts: first we put a few things in
1176 # This function works in two parts: first we put a few things in
1168 # user_ns, and we sync that contents into user_ns_hidden so that these
1177 # user_ns, and we sync that contents into user_ns_hidden so that these
1169 # initial variables aren't shown by %who. After the sync, we add the
1178 # initial variables aren't shown by %who. After the sync, we add the
1170 # rest of what we *do* want the user to see with %who even on a new
1179 # rest of what we *do* want the user to see with %who even on a new
1171 # session (probably nothing, so theye really only see their own stuff)
1180 # session (probably nothing, so theye really only see their own stuff)
1172
1181
1173 # The user dict must *always* have a __builtin__ reference to the
1182 # The user dict must *always* have a __builtin__ reference to the
1174 # Python standard __builtin__ namespace, which must be imported.
1183 # Python standard __builtin__ namespace, which must be imported.
1175 # This is so that certain operations in prompt evaluation can be
1184 # This is so that certain operations in prompt evaluation can be
1176 # reliably executed with builtins. Note that we can NOT use
1185 # reliably executed with builtins. Note that we can NOT use
1177 # __builtins__ (note the 's'), because that can either be a dict or a
1186 # __builtins__ (note the 's'), because that can either be a dict or a
1178 # module, and can even mutate at runtime, depending on the context
1187 # module, and can even mutate at runtime, depending on the context
1179 # (Python makes no guarantees on it). In contrast, __builtin__ is
1188 # (Python makes no guarantees on it). In contrast, __builtin__ is
1180 # always a module object, though it must be explicitly imported.
1189 # always a module object, though it must be explicitly imported.
1181
1190
1182 # For more details:
1191 # For more details:
1183 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1192 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1184 ns = dict()
1193 ns = dict()
1185
1194
1186 # make global variables for user access to the histories
1195 # make global variables for user access to the histories
1187 ns['_ih'] = self.history_manager.input_hist_parsed
1196 ns['_ih'] = self.history_manager.input_hist_parsed
1188 ns['_oh'] = self.history_manager.output_hist
1197 ns['_oh'] = self.history_manager.output_hist
1189 ns['_dh'] = self.history_manager.dir_hist
1198 ns['_dh'] = self.history_manager.dir_hist
1190
1199
1191 ns['_sh'] = shadowns
1200 ns['_sh'] = shadowns
1192
1201
1193 # user aliases to input and output histories. These shouldn't show up
1202 # user aliases to input and output histories. These shouldn't show up
1194 # in %who, as they can have very large reprs.
1203 # in %who, as they can have very large reprs.
1195 ns['In'] = self.history_manager.input_hist_parsed
1204 ns['In'] = self.history_manager.input_hist_parsed
1196 ns['Out'] = self.history_manager.output_hist
1205 ns['Out'] = self.history_manager.output_hist
1197
1206
1198 # Store myself as the public api!!!
1207 # Store myself as the public api!!!
1199 ns['get_ipython'] = self.get_ipython
1208 ns['get_ipython'] = self.get_ipython
1200
1209
1201 ns['exit'] = self.exiter
1210 ns['exit'] = self.exiter
1202 ns['quit'] = self.exiter
1211 ns['quit'] = self.exiter
1203
1212
1204 # Sync what we've added so far to user_ns_hidden so these aren't seen
1213 # Sync what we've added so far to user_ns_hidden so these aren't seen
1205 # by %who
1214 # by %who
1206 self.user_ns_hidden.update(ns)
1215 self.user_ns_hidden.update(ns)
1207
1216
1208 # Anything put into ns now would show up in %who. Think twice before
1217 # Anything put into ns now would show up in %who. Think twice before
1209 # putting anything here, as we really want %who to show the user their
1218 # putting anything here, as we really want %who to show the user their
1210 # stuff, not our variables.
1219 # stuff, not our variables.
1211
1220
1212 # Finally, update the real user's namespace
1221 # Finally, update the real user's namespace
1213 self.user_ns.update(ns)
1222 self.user_ns.update(ns)
1214
1223
1215 @property
1224 @property
1216 def all_ns_refs(self):
1225 def all_ns_refs(self):
1217 """Get a list of references to all the namespace dictionaries in which
1226 """Get a list of references to all the namespace dictionaries in which
1218 IPython might store a user-created object.
1227 IPython might store a user-created object.
1219
1228
1220 Note that this does not include the displayhook, which also caches
1229 Note that this does not include the displayhook, which also caches
1221 objects from the output."""
1230 objects from the output."""
1222 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1231 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1223 [m.__dict__ for m in self._main_mod_cache.values()]
1232 [m.__dict__ for m in self._main_mod_cache.values()]
1224
1233
1225 def reset(self, new_session=True):
1234 def reset(self, new_session=True):
1226 """Clear all internal namespaces, and attempt to release references to
1235 """Clear all internal namespaces, and attempt to release references to
1227 user objects.
1236 user objects.
1228
1237
1229 If new_session is True, a new history session will be opened.
1238 If new_session is True, a new history session will be opened.
1230 """
1239 """
1231 # Clear histories
1240 # Clear histories
1232 self.history_manager.reset(new_session)
1241 self.history_manager.reset(new_session)
1233 # Reset counter used to index all histories
1242 # Reset counter used to index all histories
1234 if new_session:
1243 if new_session:
1235 self.execution_count = 1
1244 self.execution_count = 1
1236
1245
1237 # Flush cached output items
1246 # Flush cached output items
1238 if self.displayhook.do_full_cache:
1247 if self.displayhook.do_full_cache:
1239 self.displayhook.flush()
1248 self.displayhook.flush()
1240
1249
1241 # The main execution namespaces must be cleared very carefully,
1250 # The main execution namespaces must be cleared very carefully,
1242 # skipping the deletion of the builtin-related keys, because doing so
1251 # skipping the deletion of the builtin-related keys, because doing so
1243 # would cause errors in many object's __del__ methods.
1252 # would cause errors in many object's __del__ methods.
1244 if self.user_ns is not self.user_global_ns:
1253 if self.user_ns is not self.user_global_ns:
1245 self.user_ns.clear()
1254 self.user_ns.clear()
1246 ns = self.user_global_ns
1255 ns = self.user_global_ns
1247 drop_keys = set(ns.keys())
1256 drop_keys = set(ns.keys())
1248 drop_keys.discard('__builtin__')
1257 drop_keys.discard('__builtin__')
1249 drop_keys.discard('__builtins__')
1258 drop_keys.discard('__builtins__')
1250 drop_keys.discard('__name__')
1259 drop_keys.discard('__name__')
1251 for k in drop_keys:
1260 for k in drop_keys:
1252 del ns[k]
1261 del ns[k]
1253
1262
1254 self.user_ns_hidden.clear()
1263 self.user_ns_hidden.clear()
1255
1264
1256 # Restore the user namespaces to minimal usability
1265 # Restore the user namespaces to minimal usability
1257 self.init_user_ns()
1266 self.init_user_ns()
1258
1267
1259 # Restore the default and user aliases
1268 # Restore the default and user aliases
1260 self.alias_manager.clear_aliases()
1269 self.alias_manager.clear_aliases()
1261 self.alias_manager.init_aliases()
1270 self.alias_manager.init_aliases()
1262
1271
1263 # Flush the private list of module references kept for script
1272 # Flush the private list of module references kept for script
1264 # execution protection
1273 # execution protection
1265 self.clear_main_mod_cache()
1274 self.clear_main_mod_cache()
1266
1275
1267 def del_var(self, varname, by_name=False):
1276 def del_var(self, varname, by_name=False):
1268 """Delete a variable from the various namespaces, so that, as
1277 """Delete a variable from the various namespaces, so that, as
1269 far as possible, we're not keeping any hidden references to it.
1278 far as possible, we're not keeping any hidden references to it.
1270
1279
1271 Parameters
1280 Parameters
1272 ----------
1281 ----------
1273 varname : str
1282 varname : str
1274 The name of the variable to delete.
1283 The name of the variable to delete.
1275 by_name : bool
1284 by_name : bool
1276 If True, delete variables with the given name in each
1285 If True, delete variables with the given name in each
1277 namespace. If False (default), find the variable in the user
1286 namespace. If False (default), find the variable in the user
1278 namespace, and delete references to it.
1287 namespace, and delete references to it.
1279 """
1288 """
1280 if varname in ('__builtin__', '__builtins__'):
1289 if varname in ('__builtin__', '__builtins__'):
1281 raise ValueError("Refusing to delete %s" % varname)
1290 raise ValueError("Refusing to delete %s" % varname)
1282
1291
1283 ns_refs = self.all_ns_refs
1292 ns_refs = self.all_ns_refs
1284
1293
1285 if by_name: # Delete by name
1294 if by_name: # Delete by name
1286 for ns in ns_refs:
1295 for ns in ns_refs:
1287 try:
1296 try:
1288 del ns[varname]
1297 del ns[varname]
1289 except KeyError:
1298 except KeyError:
1290 pass
1299 pass
1291 else: # Delete by object
1300 else: # Delete by object
1292 try:
1301 try:
1293 obj = self.user_ns[varname]
1302 obj = self.user_ns[varname]
1294 except KeyError:
1303 except KeyError:
1295 raise NameError("name '%s' is not defined" % varname)
1304 raise NameError("name '%s' is not defined" % varname)
1296 # Also check in output history
1305 # Also check in output history
1297 ns_refs.append(self.history_manager.output_hist)
1306 ns_refs.append(self.history_manager.output_hist)
1298 for ns in ns_refs:
1307 for ns in ns_refs:
1299 to_delete = [n for n, o in iteritems(ns) if o is obj]
1308 to_delete = [n for n, o in iteritems(ns) if o is obj]
1300 for name in to_delete:
1309 for name in to_delete:
1301 del ns[name]
1310 del ns[name]
1302
1311
1303 # displayhook keeps extra references, but not in a dictionary
1312 # displayhook keeps extra references, but not in a dictionary
1304 for name in ('_', '__', '___'):
1313 for name in ('_', '__', '___'):
1305 if getattr(self.displayhook, name) is obj:
1314 if getattr(self.displayhook, name) is obj:
1306 setattr(self.displayhook, name, None)
1315 setattr(self.displayhook, name, None)
1307
1316
1308 def reset_selective(self, regex=None):
1317 def reset_selective(self, regex=None):
1309 """Clear selective variables from internal namespaces based on a
1318 """Clear selective variables from internal namespaces based on a
1310 specified regular expression.
1319 specified regular expression.
1311
1320
1312 Parameters
1321 Parameters
1313 ----------
1322 ----------
1314 regex : string or compiled pattern, optional
1323 regex : string or compiled pattern, optional
1315 A regular expression pattern that will be used in searching
1324 A regular expression pattern that will be used in searching
1316 variable names in the users namespaces.
1325 variable names in the users namespaces.
1317 """
1326 """
1318 if regex is not None:
1327 if regex is not None:
1319 try:
1328 try:
1320 m = re.compile(regex)
1329 m = re.compile(regex)
1321 except TypeError:
1330 except TypeError:
1322 raise TypeError('regex must be a string or compiled pattern')
1331 raise TypeError('regex must be a string or compiled pattern')
1323 # Search for keys in each namespace that match the given regex
1332 # Search for keys in each namespace that match the given regex
1324 # If a match is found, delete the key/value pair.
1333 # If a match is found, delete the key/value pair.
1325 for ns in self.all_ns_refs:
1334 for ns in self.all_ns_refs:
1326 for var in ns:
1335 for var in ns:
1327 if m.search(var):
1336 if m.search(var):
1328 del ns[var]
1337 del ns[var]
1329
1338
1330 def push(self, variables, interactive=True):
1339 def push(self, variables, interactive=True):
1331 """Inject a group of variables into the IPython user namespace.
1340 """Inject a group of variables into the IPython user namespace.
1332
1341
1333 Parameters
1342 Parameters
1334 ----------
1343 ----------
1335 variables : dict, str or list/tuple of str
1344 variables : dict, str or list/tuple of str
1336 The variables to inject into the user's namespace. If a dict, a
1345 The variables to inject into the user's namespace. If a dict, a
1337 simple update is done. If a str, the string is assumed to have
1346 simple update is done. If a str, the string is assumed to have
1338 variable names separated by spaces. A list/tuple of str can also
1347 variable names separated by spaces. A list/tuple of str can also
1339 be used to give the variable names. If just the variable names are
1348 be used to give the variable names. If just the variable names are
1340 give (list/tuple/str) then the variable values looked up in the
1349 give (list/tuple/str) then the variable values looked up in the
1341 callers frame.
1350 callers frame.
1342 interactive : bool
1351 interactive : bool
1343 If True (default), the variables will be listed with the ``who``
1352 If True (default), the variables will be listed with the ``who``
1344 magic.
1353 magic.
1345 """
1354 """
1346 vdict = None
1355 vdict = None
1347
1356
1348 # We need a dict of name/value pairs to do namespace updates.
1357 # We need a dict of name/value pairs to do namespace updates.
1349 if isinstance(variables, dict):
1358 if isinstance(variables, dict):
1350 vdict = variables
1359 vdict = variables
1351 elif isinstance(variables, string_types+(list, tuple)):
1360 elif isinstance(variables, string_types+(list, tuple)):
1352 if isinstance(variables, string_types):
1361 if isinstance(variables, string_types):
1353 vlist = variables.split()
1362 vlist = variables.split()
1354 else:
1363 else:
1355 vlist = variables
1364 vlist = variables
1356 vdict = {}
1365 vdict = {}
1357 cf = sys._getframe(1)
1366 cf = sys._getframe(1)
1358 for name in vlist:
1367 for name in vlist:
1359 try:
1368 try:
1360 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1369 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1361 except:
1370 except:
1362 print('Could not get variable %s from %s' %
1371 print('Could not get variable %s from %s' %
1363 (name,cf.f_code.co_name))
1372 (name,cf.f_code.co_name))
1364 else:
1373 else:
1365 raise ValueError('variables must be a dict/str/list/tuple')
1374 raise ValueError('variables must be a dict/str/list/tuple')
1366
1375
1367 # Propagate variables to user namespace
1376 # Propagate variables to user namespace
1368 self.user_ns.update(vdict)
1377 self.user_ns.update(vdict)
1369
1378
1370 # And configure interactive visibility
1379 # And configure interactive visibility
1371 user_ns_hidden = self.user_ns_hidden
1380 user_ns_hidden = self.user_ns_hidden
1372 if interactive:
1381 if interactive:
1373 for name in vdict:
1382 for name in vdict:
1374 user_ns_hidden.pop(name, None)
1383 user_ns_hidden.pop(name, None)
1375 else:
1384 else:
1376 user_ns_hidden.update(vdict)
1385 user_ns_hidden.update(vdict)
1377
1386
1378 def drop_by_id(self, variables):
1387 def drop_by_id(self, variables):
1379 """Remove a dict of variables from the user namespace, if they are the
1388 """Remove a dict of variables from the user namespace, if they are the
1380 same as the values in the dictionary.
1389 same as the values in the dictionary.
1381
1390
1382 This is intended for use by extensions: variables that they've added can
1391 This is intended for use by extensions: variables that they've added can
1383 be taken back out if they are unloaded, without removing any that the
1392 be taken back out if they are unloaded, without removing any that the
1384 user has overwritten.
1393 user has overwritten.
1385
1394
1386 Parameters
1395 Parameters
1387 ----------
1396 ----------
1388 variables : dict
1397 variables : dict
1389 A dictionary mapping object names (as strings) to the objects.
1398 A dictionary mapping object names (as strings) to the objects.
1390 """
1399 """
1391 for name, obj in iteritems(variables):
1400 for name, obj in iteritems(variables):
1392 if name in self.user_ns and self.user_ns[name] is obj:
1401 if name in self.user_ns and self.user_ns[name] is obj:
1393 del self.user_ns[name]
1402 del self.user_ns[name]
1394 self.user_ns_hidden.pop(name, None)
1403 self.user_ns_hidden.pop(name, None)
1395
1404
1396 #-------------------------------------------------------------------------
1405 #-------------------------------------------------------------------------
1397 # Things related to object introspection
1406 # Things related to object introspection
1398 #-------------------------------------------------------------------------
1407 #-------------------------------------------------------------------------
1399
1408
1400 def _ofind(self, oname, namespaces=None):
1409 def _ofind(self, oname, namespaces=None):
1401 """Find an object in the available namespaces.
1410 """Find an object in the available namespaces.
1402
1411
1403 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1412 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1404
1413
1405 Has special code to detect magic functions.
1414 Has special code to detect magic functions.
1406 """
1415 """
1407 oname = oname.strip()
1416 oname = oname.strip()
1408 #print '1- oname: <%r>' % oname # dbg
1417 #print '1- oname: <%r>' % oname # dbg
1409 if not oname.startswith(ESC_MAGIC) and \
1418 if not oname.startswith(ESC_MAGIC) and \
1410 not oname.startswith(ESC_MAGIC2) and \
1419 not oname.startswith(ESC_MAGIC2) and \
1411 not py3compat.isidentifier(oname, dotted=True):
1420 not py3compat.isidentifier(oname, dotted=True):
1412 return dict(found=False)
1421 return dict(found=False)
1413
1422
1414 alias_ns = None
1423 alias_ns = None
1415 if namespaces is None:
1424 if namespaces is None:
1416 # Namespaces to search in:
1425 # Namespaces to search in:
1417 # Put them in a list. The order is important so that we
1426 # Put them in a list. The order is important so that we
1418 # find things in the same order that Python finds them.
1427 # find things in the same order that Python finds them.
1419 namespaces = [ ('Interactive', self.user_ns),
1428 namespaces = [ ('Interactive', self.user_ns),
1420 ('Interactive (global)', self.user_global_ns),
1429 ('Interactive (global)', self.user_global_ns),
1421 ('Python builtin', builtin_mod.__dict__),
1430 ('Python builtin', builtin_mod.__dict__),
1422 ]
1431 ]
1423
1432
1424 # initialize results to 'null'
1433 # initialize results to 'null'
1425 found = False; obj = None; ospace = None; ds = None;
1434 found = False; obj = None; ospace = None; ds = None;
1426 ismagic = False; isalias = False; parent = None
1435 ismagic = False; isalias = False; parent = None
1427
1436
1428 # We need to special-case 'print', which as of python2.6 registers as a
1437 # We need to special-case 'print', which as of python2.6 registers as a
1429 # function but should only be treated as one if print_function was
1438 # function but should only be treated as one if print_function was
1430 # loaded with a future import. In this case, just bail.
1439 # loaded with a future import. In this case, just bail.
1431 if (oname == 'print' and not py3compat.PY3 and not \
1440 if (oname == 'print' and not py3compat.PY3 and not \
1432 (self.compile.compiler_flags & __future__.CO_FUTURE_PRINT_FUNCTION)):
1441 (self.compile.compiler_flags & __future__.CO_FUTURE_PRINT_FUNCTION)):
1433 return {'found':found, 'obj':obj, 'namespace':ospace,
1442 return {'found':found, 'obj':obj, 'namespace':ospace,
1434 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1443 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1435
1444
1436 # Look for the given name by splitting it in parts. If the head is
1445 # Look for the given name by splitting it in parts. If the head is
1437 # found, then we look for all the remaining parts as members, and only
1446 # found, then we look for all the remaining parts as members, and only
1438 # declare success if we can find them all.
1447 # declare success if we can find them all.
1439 oname_parts = oname.split('.')
1448 oname_parts = oname.split('.')
1440 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1449 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1441 for nsname,ns in namespaces:
1450 for nsname,ns in namespaces:
1442 try:
1451 try:
1443 obj = ns[oname_head]
1452 obj = ns[oname_head]
1444 except KeyError:
1453 except KeyError:
1445 continue
1454 continue
1446 else:
1455 else:
1447 #print 'oname_rest:', oname_rest # dbg
1456 #print 'oname_rest:', oname_rest # dbg
1448 for idx, part in enumerate(oname_rest):
1457 for idx, part in enumerate(oname_rest):
1449 try:
1458 try:
1450 parent = obj
1459 parent = obj
1451 # The last part is looked up in a special way to avoid
1460 # The last part is looked up in a special way to avoid
1452 # descriptor invocation as it may raise or have side
1461 # descriptor invocation as it may raise or have side
1453 # effects.
1462 # effects.
1454 if idx == len(oname_rest) - 1:
1463 if idx == len(oname_rest) - 1:
1455 obj = self._getattr_property(obj, part)
1464 obj = self._getattr_property(obj, part)
1456 else:
1465 else:
1457 obj = getattr(obj, part)
1466 obj = getattr(obj, part)
1458 except:
1467 except:
1459 # Blanket except b/c some badly implemented objects
1468 # Blanket except b/c some badly implemented objects
1460 # allow __getattr__ to raise exceptions other than
1469 # allow __getattr__ to raise exceptions other than
1461 # AttributeError, which then crashes IPython.
1470 # AttributeError, which then crashes IPython.
1462 break
1471 break
1463 else:
1472 else:
1464 # If we finish the for loop (no break), we got all members
1473 # If we finish the for loop (no break), we got all members
1465 found = True
1474 found = True
1466 ospace = nsname
1475 ospace = nsname
1467 break # namespace loop
1476 break # namespace loop
1468
1477
1469 # Try to see if it's magic
1478 # Try to see if it's magic
1470 if not found:
1479 if not found:
1471 obj = None
1480 obj = None
1472 if oname.startswith(ESC_MAGIC2):
1481 if oname.startswith(ESC_MAGIC2):
1473 oname = oname.lstrip(ESC_MAGIC2)
1482 oname = oname.lstrip(ESC_MAGIC2)
1474 obj = self.find_cell_magic(oname)
1483 obj = self.find_cell_magic(oname)
1475 elif oname.startswith(ESC_MAGIC):
1484 elif oname.startswith(ESC_MAGIC):
1476 oname = oname.lstrip(ESC_MAGIC)
1485 oname = oname.lstrip(ESC_MAGIC)
1477 obj = self.find_line_magic(oname)
1486 obj = self.find_line_magic(oname)
1478 else:
1487 else:
1479 # search without prefix, so run? will find %run?
1488 # search without prefix, so run? will find %run?
1480 obj = self.find_line_magic(oname)
1489 obj = self.find_line_magic(oname)
1481 if obj is None:
1490 if obj is None:
1482 obj = self.find_cell_magic(oname)
1491 obj = self.find_cell_magic(oname)
1483 if obj is not None:
1492 if obj is not None:
1484 found = True
1493 found = True
1485 ospace = 'IPython internal'
1494 ospace = 'IPython internal'
1486 ismagic = True
1495 ismagic = True
1487
1496
1488 # Last try: special-case some literals like '', [], {}, etc:
1497 # Last try: special-case some literals like '', [], {}, etc:
1489 if not found and oname_head in ["''",'""','[]','{}','()']:
1498 if not found and oname_head in ["''",'""','[]','{}','()']:
1490 obj = eval(oname_head)
1499 obj = eval(oname_head)
1491 found = True
1500 found = True
1492 ospace = 'Interactive'
1501 ospace = 'Interactive'
1493
1502
1494 return {'found':found, 'obj':obj, 'namespace':ospace,
1503 return {'found':found, 'obj':obj, 'namespace':ospace,
1495 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1504 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1496
1505
1497 @staticmethod
1506 @staticmethod
1498 def _getattr_property(obj, attrname):
1507 def _getattr_property(obj, attrname):
1499 """Property-aware getattr to use in object finding.
1508 """Property-aware getattr to use in object finding.
1500
1509
1501 If attrname represents a property, return it unevaluated (in case it has
1510 If attrname represents a property, return it unevaluated (in case it has
1502 side effects or raises an error.
1511 side effects or raises an error.
1503
1512
1504 """
1513 """
1505 if not isinstance(obj, type):
1514 if not isinstance(obj, type):
1506 try:
1515 try:
1507 # `getattr(type(obj), attrname)` is not guaranteed to return
1516 # `getattr(type(obj), attrname)` is not guaranteed to return
1508 # `obj`, but does so for property:
1517 # `obj`, but does so for property:
1509 #
1518 #
1510 # property.__get__(self, None, cls) -> self
1519 # property.__get__(self, None, cls) -> self
1511 #
1520 #
1512 # The universal alternative is to traverse the mro manually
1521 # The universal alternative is to traverse the mro manually
1513 # searching for attrname in class dicts.
1522 # searching for attrname in class dicts.
1514 attr = getattr(type(obj), attrname)
1523 attr = getattr(type(obj), attrname)
1515 except AttributeError:
1524 except AttributeError:
1516 pass
1525 pass
1517 else:
1526 else:
1518 # This relies on the fact that data descriptors (with both
1527 # This relies on the fact that data descriptors (with both
1519 # __get__ & __set__ magic methods) take precedence over
1528 # __get__ & __set__ magic methods) take precedence over
1520 # instance-level attributes:
1529 # instance-level attributes:
1521 #
1530 #
1522 # class A(object):
1531 # class A(object):
1523 # @property
1532 # @property
1524 # def foobar(self): return 123
1533 # def foobar(self): return 123
1525 # a = A()
1534 # a = A()
1526 # a.__dict__['foobar'] = 345
1535 # a.__dict__['foobar'] = 345
1527 # a.foobar # == 123
1536 # a.foobar # == 123
1528 #
1537 #
1529 # So, a property may be returned right away.
1538 # So, a property may be returned right away.
1530 if isinstance(attr, property):
1539 if isinstance(attr, property):
1531 return attr
1540 return attr
1532
1541
1533 # Nothing helped, fall back.
1542 # Nothing helped, fall back.
1534 return getattr(obj, attrname)
1543 return getattr(obj, attrname)
1535
1544
1536 def _object_find(self, oname, namespaces=None):
1545 def _object_find(self, oname, namespaces=None):
1537 """Find an object and return a struct with info about it."""
1546 """Find an object and return a struct with info about it."""
1538 return Struct(self._ofind(oname, namespaces))
1547 return Struct(self._ofind(oname, namespaces))
1539
1548
1540 def _inspect(self, meth, oname, namespaces=None, **kw):
1549 def _inspect(self, meth, oname, namespaces=None, **kw):
1541 """Generic interface to the inspector system.
1550 """Generic interface to the inspector system.
1542
1551
1543 This function is meant to be called by pdef, pdoc & friends."""
1552 This function is meant to be called by pdef, pdoc & friends."""
1544 info = self._object_find(oname, namespaces)
1553 info = self._object_find(oname, namespaces)
1545 if info.found:
1554 if info.found:
1546 pmethod = getattr(self.inspector, meth)
1555 pmethod = getattr(self.inspector, meth)
1547 formatter = format_screen if info.ismagic else None
1556 formatter = format_screen if info.ismagic else None
1548 if meth == 'pdoc':
1557 if meth == 'pdoc':
1549 pmethod(info.obj, oname, formatter)
1558 pmethod(info.obj, oname, formatter)
1550 elif meth == 'pinfo':
1559 elif meth == 'pinfo':
1551 pmethod(info.obj, oname, formatter, info, **kw)
1560 pmethod(info.obj, oname, formatter, info, **kw)
1552 else:
1561 else:
1553 pmethod(info.obj, oname)
1562 pmethod(info.obj, oname)
1554 else:
1563 else:
1555 print('Object `%s` not found.' % oname)
1564 print('Object `%s` not found.' % oname)
1556 return 'not found' # so callers can take other action
1565 return 'not found' # so callers can take other action
1557
1566
1558 def object_inspect(self, oname, detail_level=0):
1567 def object_inspect(self, oname, detail_level=0):
1559 """Get object info about oname"""
1568 """Get object info about oname"""
1560 with self.builtin_trap:
1569 with self.builtin_trap:
1561 info = self._object_find(oname)
1570 info = self._object_find(oname)
1562 if info.found:
1571 if info.found:
1563 return self.inspector.info(info.obj, oname, info=info,
1572 return self.inspector.info(info.obj, oname, info=info,
1564 detail_level=detail_level
1573 detail_level=detail_level
1565 )
1574 )
1566 else:
1575 else:
1567 return oinspect.object_info(name=oname, found=False)
1576 return oinspect.object_info(name=oname, found=False)
1568
1577
1569 def object_inspect_text(self, oname, detail_level=0):
1578 def object_inspect_text(self, oname, detail_level=0):
1570 """Get object info as formatted text"""
1579 """Get object info as formatted text"""
1571 with self.builtin_trap:
1580 with self.builtin_trap:
1572 info = self._object_find(oname)
1581 info = self._object_find(oname)
1573 if info.found:
1582 if info.found:
1574 return self.inspector._format_info(info.obj, oname, info=info,
1583 return self.inspector._format_info(info.obj, oname, info=info,
1575 detail_level=detail_level
1584 detail_level=detail_level
1576 )
1585 )
1577 else:
1586 else:
1578 raise KeyError(oname)
1587 raise KeyError(oname)
1579
1588
1580 #-------------------------------------------------------------------------
1589 #-------------------------------------------------------------------------
1581 # Things related to history management
1590 # Things related to history management
1582 #-------------------------------------------------------------------------
1591 #-------------------------------------------------------------------------
1583
1592
1584 def init_history(self):
1593 def init_history(self):
1585 """Sets up the command history, and starts regular autosaves."""
1594 """Sets up the command history, and starts regular autosaves."""
1586 self.history_manager = HistoryManager(shell=self, parent=self)
1595 self.history_manager = HistoryManager(shell=self, parent=self)
1587 self.configurables.append(self.history_manager)
1596 self.configurables.append(self.history_manager)
1588
1597
1589 #-------------------------------------------------------------------------
1598 #-------------------------------------------------------------------------
1590 # Things related to exception handling and tracebacks (not debugging)
1599 # Things related to exception handling and tracebacks (not debugging)
1591 #-------------------------------------------------------------------------
1600 #-------------------------------------------------------------------------
1592
1601
1593 def init_traceback_handlers(self, custom_exceptions):
1602 def init_traceback_handlers(self, custom_exceptions):
1594 # Syntax error handler.
1603 # Syntax error handler.
1595 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor')
1604 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor')
1596
1605
1597 # The interactive one is initialized with an offset, meaning we always
1606 # The interactive one is initialized with an offset, meaning we always
1598 # want to remove the topmost item in the traceback, which is our own
1607 # want to remove the topmost item in the traceback, which is our own
1599 # internal code. Valid modes: ['Plain','Context','Verbose']
1608 # internal code. Valid modes: ['Plain','Context','Verbose']
1600 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1609 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1601 color_scheme='NoColor',
1610 color_scheme='NoColor',
1602 tb_offset = 1,
1611 tb_offset = 1,
1603 check_cache=check_linecache_ipython)
1612 check_cache=check_linecache_ipython)
1604
1613
1605 # The instance will store a pointer to the system-wide exception hook,
1614 # The instance will store a pointer to the system-wide exception hook,
1606 # so that runtime code (such as magics) can access it. This is because
1615 # so that runtime code (such as magics) can access it. This is because
1607 # during the read-eval loop, it may get temporarily overwritten.
1616 # during the read-eval loop, it may get temporarily overwritten.
1608 self.sys_excepthook = sys.excepthook
1617 self.sys_excepthook = sys.excepthook
1609
1618
1610 # and add any custom exception handlers the user may have specified
1619 # and add any custom exception handlers the user may have specified
1611 self.set_custom_exc(*custom_exceptions)
1620 self.set_custom_exc(*custom_exceptions)
1612
1621
1613 # Set the exception mode
1622 # Set the exception mode
1614 self.InteractiveTB.set_mode(mode=self.xmode)
1623 self.InteractiveTB.set_mode(mode=self.xmode)
1615
1624
1616 def set_custom_exc(self, exc_tuple, handler):
1625 def set_custom_exc(self, exc_tuple, handler):
1617 """set_custom_exc(exc_tuple,handler)
1626 """set_custom_exc(exc_tuple,handler)
1618
1627
1619 Set a custom exception handler, which will be called if any of the
1628 Set a custom exception handler, which will be called if any of the
1620 exceptions in exc_tuple occur in the mainloop (specifically, in the
1629 exceptions in exc_tuple occur in the mainloop (specifically, in the
1621 run_code() method).
1630 run_code() method).
1622
1631
1623 Parameters
1632 Parameters
1624 ----------
1633 ----------
1625
1634
1626 exc_tuple : tuple of exception classes
1635 exc_tuple : tuple of exception classes
1627 A *tuple* of exception classes, for which to call the defined
1636 A *tuple* of exception classes, for which to call the defined
1628 handler. It is very important that you use a tuple, and NOT A
1637 handler. It is very important that you use a tuple, and NOT A
1629 LIST here, because of the way Python's except statement works. If
1638 LIST here, because of the way Python's except statement works. If
1630 you only want to trap a single exception, use a singleton tuple::
1639 you only want to trap a single exception, use a singleton tuple::
1631
1640
1632 exc_tuple == (MyCustomException,)
1641 exc_tuple == (MyCustomException,)
1633
1642
1634 handler : callable
1643 handler : callable
1635 handler must have the following signature::
1644 handler must have the following signature::
1636
1645
1637 def my_handler(self, etype, value, tb, tb_offset=None):
1646 def my_handler(self, etype, value, tb, tb_offset=None):
1638 ...
1647 ...
1639 return structured_traceback
1648 return structured_traceback
1640
1649
1641 Your handler must return a structured traceback (a list of strings),
1650 Your handler must return a structured traceback (a list of strings),
1642 or None.
1651 or None.
1643
1652
1644 This will be made into an instance method (via types.MethodType)
1653 This will be made into an instance method (via types.MethodType)
1645 of IPython itself, and it will be called if any of the exceptions
1654 of IPython itself, and it will be called if any of the exceptions
1646 listed in the exc_tuple are caught. If the handler is None, an
1655 listed in the exc_tuple are caught. If the handler is None, an
1647 internal basic one is used, which just prints basic info.
1656 internal basic one is used, which just prints basic info.
1648
1657
1649 To protect IPython from crashes, if your handler ever raises an
1658 To protect IPython from crashes, if your handler ever raises an
1650 exception or returns an invalid result, it will be immediately
1659 exception or returns an invalid result, it will be immediately
1651 disabled.
1660 disabled.
1652
1661
1653 WARNING: by putting in your own exception handler into IPython's main
1662 WARNING: by putting in your own exception handler into IPython's main
1654 execution loop, you run a very good chance of nasty crashes. This
1663 execution loop, you run a very good chance of nasty crashes. This
1655 facility should only be used if you really know what you are doing."""
1664 facility should only be used if you really know what you are doing."""
1656
1665
1657 assert type(exc_tuple)==type(()) , \
1666 assert type(exc_tuple)==type(()) , \
1658 "The custom exceptions must be given AS A TUPLE."
1667 "The custom exceptions must be given AS A TUPLE."
1659
1668
1660 def dummy_handler(self,etype,value,tb,tb_offset=None):
1669 def dummy_handler(self,etype,value,tb,tb_offset=None):
1661 print('*** Simple custom exception handler ***')
1670 print('*** Simple custom exception handler ***')
1662 print('Exception type :',etype)
1671 print('Exception type :',etype)
1663 print('Exception value:',value)
1672 print('Exception value:',value)
1664 print('Traceback :',tb)
1673 print('Traceback :',tb)
1665 #print 'Source code :','\n'.join(self.buffer)
1674 #print 'Source code :','\n'.join(self.buffer)
1666
1675
1667 def validate_stb(stb):
1676 def validate_stb(stb):
1668 """validate structured traceback return type
1677 """validate structured traceback return type
1669
1678
1670 return type of CustomTB *should* be a list of strings, but allow
1679 return type of CustomTB *should* be a list of strings, but allow
1671 single strings or None, which are harmless.
1680 single strings or None, which are harmless.
1672
1681
1673 This function will *always* return a list of strings,
1682 This function will *always* return a list of strings,
1674 and will raise a TypeError if stb is inappropriate.
1683 and will raise a TypeError if stb is inappropriate.
1675 """
1684 """
1676 msg = "CustomTB must return list of strings, not %r" % stb
1685 msg = "CustomTB must return list of strings, not %r" % stb
1677 if stb is None:
1686 if stb is None:
1678 return []
1687 return []
1679 elif isinstance(stb, string_types):
1688 elif isinstance(stb, string_types):
1680 return [stb]
1689 return [stb]
1681 elif not isinstance(stb, list):
1690 elif not isinstance(stb, list):
1682 raise TypeError(msg)
1691 raise TypeError(msg)
1683 # it's a list
1692 # it's a list
1684 for line in stb:
1693 for line in stb:
1685 # check every element
1694 # check every element
1686 if not isinstance(line, string_types):
1695 if not isinstance(line, string_types):
1687 raise TypeError(msg)
1696 raise TypeError(msg)
1688 return stb
1697 return stb
1689
1698
1690 if handler is None:
1699 if handler is None:
1691 wrapped = dummy_handler
1700 wrapped = dummy_handler
1692 else:
1701 else:
1693 def wrapped(self,etype,value,tb,tb_offset=None):
1702 def wrapped(self,etype,value,tb,tb_offset=None):
1694 """wrap CustomTB handler, to protect IPython from user code
1703 """wrap CustomTB handler, to protect IPython from user code
1695
1704
1696 This makes it harder (but not impossible) for custom exception
1705 This makes it harder (but not impossible) for custom exception
1697 handlers to crash IPython.
1706 handlers to crash IPython.
1698 """
1707 """
1699 try:
1708 try:
1700 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1709 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1701 return validate_stb(stb)
1710 return validate_stb(stb)
1702 except:
1711 except:
1703 # clear custom handler immediately
1712 # clear custom handler immediately
1704 self.set_custom_exc((), None)
1713 self.set_custom_exc((), None)
1705 print("Custom TB Handler failed, unregistering", file=io.stderr)
1714 print("Custom TB Handler failed, unregistering", file=io.stderr)
1706 # show the exception in handler first
1715 # show the exception in handler first
1707 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1716 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1708 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1717 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1709 print("The original exception:", file=io.stdout)
1718 print("The original exception:", file=io.stdout)
1710 stb = self.InteractiveTB.structured_traceback(
1719 stb = self.InteractiveTB.structured_traceback(
1711 (etype,value,tb), tb_offset=tb_offset
1720 (etype,value,tb), tb_offset=tb_offset
1712 )
1721 )
1713 return stb
1722 return stb
1714
1723
1715 self.CustomTB = types.MethodType(wrapped,self)
1724 self.CustomTB = types.MethodType(wrapped,self)
1716 self.custom_exceptions = exc_tuple
1725 self.custom_exceptions = exc_tuple
1717
1726
1718 def excepthook(self, etype, value, tb):
1727 def excepthook(self, etype, value, tb):
1719 """One more defense for GUI apps that call sys.excepthook.
1728 """One more defense for GUI apps that call sys.excepthook.
1720
1729
1721 GUI frameworks like wxPython trap exceptions and call
1730 GUI frameworks like wxPython trap exceptions and call
1722 sys.excepthook themselves. I guess this is a feature that
1731 sys.excepthook themselves. I guess this is a feature that
1723 enables them to keep running after exceptions that would
1732 enables them to keep running after exceptions that would
1724 otherwise kill their mainloop. This is a bother for IPython
1733 otherwise kill their mainloop. This is a bother for IPython
1725 which excepts to catch all of the program exceptions with a try:
1734 which excepts to catch all of the program exceptions with a try:
1726 except: statement.
1735 except: statement.
1727
1736
1728 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1737 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1729 any app directly invokes sys.excepthook, it will look to the user like
1738 any app directly invokes sys.excepthook, it will look to the user like
1730 IPython crashed. In order to work around this, we can disable the
1739 IPython crashed. In order to work around this, we can disable the
1731 CrashHandler and replace it with this excepthook instead, which prints a
1740 CrashHandler and replace it with this excepthook instead, which prints a
1732 regular traceback using our InteractiveTB. In this fashion, apps which
1741 regular traceback using our InteractiveTB. In this fashion, apps which
1733 call sys.excepthook will generate a regular-looking exception from
1742 call sys.excepthook will generate a regular-looking exception from
1734 IPython, and the CrashHandler will only be triggered by real IPython
1743 IPython, and the CrashHandler will only be triggered by real IPython
1735 crashes.
1744 crashes.
1736
1745
1737 This hook should be used sparingly, only in places which are not likely
1746 This hook should be used sparingly, only in places which are not likely
1738 to be true IPython errors.
1747 to be true IPython errors.
1739 """
1748 """
1740 self.showtraceback((etype, value, tb), tb_offset=0)
1749 self.showtraceback((etype, value, tb), tb_offset=0)
1741
1750
1742 def _get_exc_info(self, exc_tuple=None):
1751 def _get_exc_info(self, exc_tuple=None):
1743 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1752 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1744
1753
1745 Ensures sys.last_type,value,traceback hold the exc_info we found,
1754 Ensures sys.last_type,value,traceback hold the exc_info we found,
1746 from whichever source.
1755 from whichever source.
1747
1756
1748 raises ValueError if none of these contain any information
1757 raises ValueError if none of these contain any information
1749 """
1758 """
1750 if exc_tuple is None:
1759 if exc_tuple is None:
1751 etype, value, tb = sys.exc_info()
1760 etype, value, tb = sys.exc_info()
1752 else:
1761 else:
1753 etype, value, tb = exc_tuple
1762 etype, value, tb = exc_tuple
1754
1763
1755 if etype is None:
1764 if etype is None:
1756 if hasattr(sys, 'last_type'):
1765 if hasattr(sys, 'last_type'):
1757 etype, value, tb = sys.last_type, sys.last_value, \
1766 etype, value, tb = sys.last_type, sys.last_value, \
1758 sys.last_traceback
1767 sys.last_traceback
1759
1768
1760 if etype is None:
1769 if etype is None:
1761 raise ValueError("No exception to find")
1770 raise ValueError("No exception to find")
1762
1771
1763 # Now store the exception info in sys.last_type etc.
1772 # Now store the exception info in sys.last_type etc.
1764 # WARNING: these variables are somewhat deprecated and not
1773 # WARNING: these variables are somewhat deprecated and not
1765 # necessarily safe to use in a threaded environment, but tools
1774 # necessarily safe to use in a threaded environment, but tools
1766 # like pdb depend on their existence, so let's set them. If we
1775 # like pdb depend on their existence, so let's set them. If we
1767 # find problems in the field, we'll need to revisit their use.
1776 # find problems in the field, we'll need to revisit their use.
1768 sys.last_type = etype
1777 sys.last_type = etype
1769 sys.last_value = value
1778 sys.last_value = value
1770 sys.last_traceback = tb
1779 sys.last_traceback = tb
1771
1780
1772 return etype, value, tb
1781 return etype, value, tb
1773
1782
1774 def show_usage_error(self, exc):
1783 def show_usage_error(self, exc):
1775 """Show a short message for UsageErrors
1784 """Show a short message for UsageErrors
1776
1785
1777 These are special exceptions that shouldn't show a traceback.
1786 These are special exceptions that shouldn't show a traceback.
1778 """
1787 """
1779 self.write_err("UsageError: %s" % exc)
1788 self.write_err("UsageError: %s" % exc)
1780
1789
1790 def get_exception_only(self, exc_tuple=None):
1791 """
1792 Return as a string (ending with a newline) the exception that
1793 just occurred, without any traceback.
1794 """
1795 etype, value, tb = self._get_exc_info(exc_tuple)
1796 msg = traceback.format_exception_only(etype, value)
1797 return ''.join(msg)
1798
1781 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1799 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1782 exception_only=False):
1800 exception_only=False):
1783 """Display the exception that just occurred.
1801 """Display the exception that just occurred.
1784
1802
1785 If nothing is known about the exception, this is the method which
1803 If nothing is known about the exception, this is the method which
1786 should be used throughout the code for presenting user tracebacks,
1804 should be used throughout the code for presenting user tracebacks,
1787 rather than directly invoking the InteractiveTB object.
1805 rather than directly invoking the InteractiveTB object.
1788
1806
1789 A specific showsyntaxerror() also exists, but this method can take
1807 A specific showsyntaxerror() also exists, but this method can take
1790 care of calling it if needed, so unless you are explicitly catching a
1808 care of calling it if needed, so unless you are explicitly catching a
1791 SyntaxError exception, don't try to analyze the stack manually and
1809 SyntaxError exception, don't try to analyze the stack manually and
1792 simply call this method."""
1810 simply call this method."""
1793
1811
1794 try:
1812 try:
1795 try:
1813 try:
1796 etype, value, tb = self._get_exc_info(exc_tuple)
1814 etype, value, tb = self._get_exc_info(exc_tuple)
1797 except ValueError:
1815 except ValueError:
1798 self.write_err('No traceback available to show.\n')
1816 self.write_err('No traceback available to show.\n')
1799 return
1817 return
1800
1818
1801 if issubclass(etype, SyntaxError):
1819 if issubclass(etype, SyntaxError):
1802 # Though this won't be called by syntax errors in the input
1820 # Though this won't be called by syntax errors in the input
1803 # line, there may be SyntaxError cases with imported code.
1821 # line, there may be SyntaxError cases with imported code.
1804 self.showsyntaxerror(filename)
1822 self.showsyntaxerror(filename)
1805 elif etype is UsageError:
1823 elif etype is UsageError:
1806 self.show_usage_error(value)
1824 self.show_usage_error(value)
1807 else:
1825 else:
1808 if exception_only:
1826 if exception_only:
1809 stb = ['An exception has occurred, use %tb to see '
1827 stb = ['An exception has occurred, use %tb to see '
1810 'the full traceback.\n']
1828 'the full traceback.\n']
1811 stb.extend(self.InteractiveTB.get_exception_only(etype,
1829 stb.extend(self.InteractiveTB.get_exception_only(etype,
1812 value))
1830 value))
1813 else:
1831 else:
1814 try:
1832 try:
1815 # Exception classes can customise their traceback - we
1833 # Exception classes can customise their traceback - we
1816 # use this in IPython.parallel for exceptions occurring
1834 # use this in IPython.parallel for exceptions occurring
1817 # in the engines. This should return a list of strings.
1835 # in the engines. This should return a list of strings.
1818 stb = value._render_traceback_()
1836 stb = value._render_traceback_()
1819 except Exception:
1837 except Exception:
1820 stb = self.InteractiveTB.structured_traceback(etype,
1838 stb = self.InteractiveTB.structured_traceback(etype,
1821 value, tb, tb_offset=tb_offset)
1839 value, tb, tb_offset=tb_offset)
1822
1840
1823 self._showtraceback(etype, value, stb)
1841 self._showtraceback(etype, value, stb)
1824 if self.call_pdb:
1842 if self.call_pdb:
1825 # drop into debugger
1843 # drop into debugger
1826 self.debugger(force=True)
1844 self.debugger(force=True)
1827 return
1845 return
1828
1846
1829 # Actually show the traceback
1847 # Actually show the traceback
1830 self._showtraceback(etype, value, stb)
1848 self._showtraceback(etype, value, stb)
1831
1849
1832 except KeyboardInterrupt:
1850 except KeyboardInterrupt:
1833 self.write_err("\nKeyboardInterrupt\n")
1851 self.write_err('\n' + self.get_exception_only())
1834
1852
1835 def _showtraceback(self, etype, evalue, stb):
1853 def _showtraceback(self, etype, evalue, stb):
1836 """Actually show a traceback.
1854 """Actually show a traceback.
1837
1855
1838 Subclasses may override this method to put the traceback on a different
1856 Subclasses may override this method to put the traceback on a different
1839 place, like a side channel.
1857 place, like a side channel.
1840 """
1858 """
1841 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1859 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1842
1860
1843 def showsyntaxerror(self, filename=None):
1861 def showsyntaxerror(self, filename=None):
1844 """Display the syntax error that just occurred.
1862 """Display the syntax error that just occurred.
1845
1863
1846 This doesn't display a stack trace because there isn't one.
1864 This doesn't display a stack trace because there isn't one.
1847
1865
1848 If a filename is given, it is stuffed in the exception instead
1866 If a filename is given, it is stuffed in the exception instead
1849 of what was there before (because Python's parser always uses
1867 of what was there before (because Python's parser always uses
1850 "<string>" when reading from a string).
1868 "<string>" when reading from a string).
1851 """
1869 """
1852 etype, value, last_traceback = self._get_exc_info()
1870 etype, value, last_traceback = self._get_exc_info()
1853
1871
1854 if filename and issubclass(etype, SyntaxError):
1872 if filename and issubclass(etype, SyntaxError):
1855 try:
1873 try:
1856 value.filename = filename
1874 value.filename = filename
1857 except:
1875 except:
1858 # Not the format we expect; leave it alone
1876 # Not the format we expect; leave it alone
1859 pass
1877 pass
1860
1878
1861 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1879 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1862 self._showtraceback(etype, value, stb)
1880 self._showtraceback(etype, value, stb)
1863
1881
1864 # This is overridden in TerminalInteractiveShell to show a message about
1882 # This is overridden in TerminalInteractiveShell to show a message about
1865 # the %paste magic.
1883 # the %paste magic.
1866 def showindentationerror(self):
1884 def showindentationerror(self):
1867 """Called by run_cell when there's an IndentationError in code entered
1885 """Called by run_cell when there's an IndentationError in code entered
1868 at the prompt.
1886 at the prompt.
1869
1887
1870 This is overridden in TerminalInteractiveShell to show a message about
1888 This is overridden in TerminalInteractiveShell to show a message about
1871 the %paste magic."""
1889 the %paste magic."""
1872 self.showsyntaxerror()
1890 self.showsyntaxerror()
1873
1891
1874 #-------------------------------------------------------------------------
1892 #-------------------------------------------------------------------------
1875 # Things related to readline
1893 # Things related to readline
1876 #-------------------------------------------------------------------------
1894 #-------------------------------------------------------------------------
1877
1895
1878 def init_readline(self):
1896 def init_readline(self):
1879 """Command history completion/saving/reloading."""
1897 """Command history completion/saving/reloading."""
1880
1898
1881 if self.readline_use:
1899 if self.readline_use:
1882 import IPython.utils.rlineimpl as readline
1900 import IPython.utils.rlineimpl as readline
1883
1901
1884 self.rl_next_input = None
1902 self.rl_next_input = None
1885 self.rl_do_indent = False
1903 self.rl_do_indent = False
1886
1904
1887 if not self.readline_use or not readline.have_readline:
1905 if not self.readline_use or not readline.have_readline:
1888 self.has_readline = False
1906 self.has_readline = False
1889 self.readline = None
1907 self.readline = None
1890 # Set a number of methods that depend on readline to be no-op
1908 # Set a number of methods that depend on readline to be no-op
1891 self.readline_no_record = no_op_context
1909 self.readline_no_record = no_op_context
1892 self.set_readline_completer = no_op
1910 self.set_readline_completer = no_op
1893 self.set_custom_completer = no_op
1911 self.set_custom_completer = no_op
1894 if self.readline_use:
1912 if self.readline_use:
1895 warn('Readline services not available or not loaded.')
1913 warn('Readline services not available or not loaded.')
1896 else:
1914 else:
1897 self.has_readline = True
1915 self.has_readline = True
1898 self.readline = readline
1916 self.readline = readline
1899 sys.modules['readline'] = readline
1917 sys.modules['readline'] = readline
1900
1918
1901 # Platform-specific configuration
1919 # Platform-specific configuration
1902 if os.name == 'nt':
1920 if os.name == 'nt':
1903 # FIXME - check with Frederick to see if we can harmonize
1921 # FIXME - check with Frederick to see if we can harmonize
1904 # naming conventions with pyreadline to avoid this
1922 # naming conventions with pyreadline to avoid this
1905 # platform-dependent check
1923 # platform-dependent check
1906 self.readline_startup_hook = readline.set_pre_input_hook
1924 self.readline_startup_hook = readline.set_pre_input_hook
1907 else:
1925 else:
1908 self.readline_startup_hook = readline.set_startup_hook
1926 self.readline_startup_hook = readline.set_startup_hook
1909
1927
1910 # Readline config order:
1928 # Readline config order:
1911 # - IPython config (default value)
1929 # - IPython config (default value)
1912 # - custom inputrc
1930 # - custom inputrc
1913 # - IPython config (user customized)
1931 # - IPython config (user customized)
1914
1932
1915 # load IPython config before inputrc if default
1933 # load IPython config before inputrc if default
1916 # skip if libedit because parse_and_bind syntax is different
1934 # skip if libedit because parse_and_bind syntax is different
1917 if not self._custom_readline_config and not readline.uses_libedit:
1935 if not self._custom_readline_config and not readline.uses_libedit:
1918 for rlcommand in self.readline_parse_and_bind:
1936 for rlcommand in self.readline_parse_and_bind:
1919 readline.parse_and_bind(rlcommand)
1937 readline.parse_and_bind(rlcommand)
1920
1938
1921 # Load user's initrc file (readline config)
1939 # Load user's initrc file (readline config)
1922 # Or if libedit is used, load editrc.
1940 # Or if libedit is used, load editrc.
1923 inputrc_name = os.environ.get('INPUTRC')
1941 inputrc_name = os.environ.get('INPUTRC')
1924 if inputrc_name is None:
1942 if inputrc_name is None:
1925 inputrc_name = '.inputrc'
1943 inputrc_name = '.inputrc'
1926 if readline.uses_libedit:
1944 if readline.uses_libedit:
1927 inputrc_name = '.editrc'
1945 inputrc_name = '.editrc'
1928 inputrc_name = os.path.join(self.home_dir, inputrc_name)
1946 inputrc_name = os.path.join(self.home_dir, inputrc_name)
1929 if os.path.isfile(inputrc_name):
1947 if os.path.isfile(inputrc_name):
1930 try:
1948 try:
1931 readline.read_init_file(inputrc_name)
1949 readline.read_init_file(inputrc_name)
1932 except:
1950 except:
1933 warn('Problems reading readline initialization file <%s>'
1951 warn('Problems reading readline initialization file <%s>'
1934 % inputrc_name)
1952 % inputrc_name)
1935
1953
1936 # load IPython config after inputrc if user has customized
1954 # load IPython config after inputrc if user has customized
1937 if self._custom_readline_config:
1955 if self._custom_readline_config:
1938 for rlcommand in self.readline_parse_and_bind:
1956 for rlcommand in self.readline_parse_and_bind:
1939 readline.parse_and_bind(rlcommand)
1957 readline.parse_and_bind(rlcommand)
1940
1958
1941 # Remove some chars from the delimiters list. If we encounter
1959 # Remove some chars from the delimiters list. If we encounter
1942 # unicode chars, discard them.
1960 # unicode chars, discard them.
1943 delims = readline.get_completer_delims()
1961 delims = readline.get_completer_delims()
1944 if not py3compat.PY3:
1962 if not py3compat.PY3:
1945 delims = delims.encode("ascii", "ignore")
1963 delims = delims.encode("ascii", "ignore")
1946 for d in self.readline_remove_delims:
1964 for d in self.readline_remove_delims:
1947 delims = delims.replace(d, "")
1965 delims = delims.replace(d, "")
1948 delims = delims.replace(ESC_MAGIC, '')
1966 delims = delims.replace(ESC_MAGIC, '')
1949 readline.set_completer_delims(delims)
1967 readline.set_completer_delims(delims)
1950 # Store these so we can restore them if something like rpy2 modifies
1968 # Store these so we can restore them if something like rpy2 modifies
1951 # them.
1969 # them.
1952 self.readline_delims = delims
1970 self.readline_delims = delims
1953 # otherwise we end up with a monster history after a while:
1971 # otherwise we end up with a monster history after a while:
1954 readline.set_history_length(self.history_length)
1972 readline.set_history_length(self.history_length)
1955
1973
1956 self.refill_readline_hist()
1974 self.refill_readline_hist()
1957 self.readline_no_record = ReadlineNoRecord(self)
1975 self.readline_no_record = ReadlineNoRecord(self)
1958
1976
1959 # Configure auto-indent for all platforms
1977 # Configure auto-indent for all platforms
1960 self.set_autoindent(self.autoindent)
1978 self.set_autoindent(self.autoindent)
1961
1979
1962 def refill_readline_hist(self):
1980 def refill_readline_hist(self):
1963 # Load the last 1000 lines from history
1981 # Load the last 1000 lines from history
1964 self.readline.clear_history()
1982 self.readline.clear_history()
1965 stdin_encoding = sys.stdin.encoding or "utf-8"
1983 stdin_encoding = sys.stdin.encoding or "utf-8"
1966 last_cell = u""
1984 last_cell = u""
1967 for _, _, cell in self.history_manager.get_tail(1000,
1985 for _, _, cell in self.history_manager.get_tail(1000,
1968 include_latest=True):
1986 include_latest=True):
1969 # Ignore blank lines and consecutive duplicates
1987 # Ignore blank lines and consecutive duplicates
1970 cell = cell.rstrip()
1988 cell = cell.rstrip()
1971 if cell and (cell != last_cell):
1989 if cell and (cell != last_cell):
1972 try:
1990 try:
1973 if self.multiline_history:
1991 if self.multiline_history:
1974 self.readline.add_history(py3compat.unicode_to_str(cell,
1992 self.readline.add_history(py3compat.unicode_to_str(cell,
1975 stdin_encoding))
1993 stdin_encoding))
1976 else:
1994 else:
1977 for line in cell.splitlines():
1995 for line in cell.splitlines():
1978 self.readline.add_history(py3compat.unicode_to_str(line,
1996 self.readline.add_history(py3compat.unicode_to_str(line,
1979 stdin_encoding))
1997 stdin_encoding))
1980 last_cell = cell
1998 last_cell = cell
1981
1999
1982 except TypeError:
2000 except TypeError:
1983 # The history DB can get corrupted so it returns strings
2001 # The history DB can get corrupted so it returns strings
1984 # containing null bytes, which readline objects to.
2002 # containing null bytes, which readline objects to.
1985 continue
2003 continue
1986
2004
1987 @skip_doctest
2005 @skip_doctest
1988 def set_next_input(self, s):
2006 def set_next_input(self, s):
1989 """ Sets the 'default' input string for the next command line.
2007 """ Sets the 'default' input string for the next command line.
1990
2008
1991 Requires readline.
2009 Requires readline.
1992
2010
1993 Example::
2011 Example::
1994
2012
1995 In [1]: _ip.set_next_input("Hello Word")
2013 In [1]: _ip.set_next_input("Hello Word")
1996 In [2]: Hello Word_ # cursor is here
2014 In [2]: Hello Word_ # cursor is here
1997 """
2015 """
1998 self.rl_next_input = py3compat.cast_bytes_py2(s)
2016 self.rl_next_input = py3compat.cast_bytes_py2(s)
1999
2017
2000 # Maybe move this to the terminal subclass?
2018 # Maybe move this to the terminal subclass?
2001 def pre_readline(self):
2019 def pre_readline(self):
2002 """readline hook to be used at the start of each line.
2020 """readline hook to be used at the start of each line.
2003
2021
2004 Currently it handles auto-indent only."""
2022 Currently it handles auto-indent only."""
2005
2023
2006 if self.rl_do_indent:
2024 if self.rl_do_indent:
2007 self.readline.insert_text(self._indent_current_str())
2025 self.readline.insert_text(self._indent_current_str())
2008 if self.rl_next_input is not None:
2026 if self.rl_next_input is not None:
2009 self.readline.insert_text(self.rl_next_input)
2027 self.readline.insert_text(self.rl_next_input)
2010 self.rl_next_input = None
2028 self.rl_next_input = None
2011
2029
2012 def _indent_current_str(self):
2030 def _indent_current_str(self):
2013 """return the current level of indentation as a string"""
2031 """return the current level of indentation as a string"""
2014 return self.input_splitter.indent_spaces * ' '
2032 return self.input_splitter.indent_spaces * ' '
2015
2033
2016 #-------------------------------------------------------------------------
2034 #-------------------------------------------------------------------------
2017 # Things related to text completion
2035 # Things related to text completion
2018 #-------------------------------------------------------------------------
2036 #-------------------------------------------------------------------------
2019
2037
2020 def init_completer(self):
2038 def init_completer(self):
2021 """Initialize the completion machinery.
2039 """Initialize the completion machinery.
2022
2040
2023 This creates completion machinery that can be used by client code,
2041 This creates completion machinery that can be used by client code,
2024 either interactively in-process (typically triggered by the readline
2042 either interactively in-process (typically triggered by the readline
2025 library), programatically (such as in test suites) or out-of-prcess
2043 library), programatically (such as in test suites) or out-of-prcess
2026 (typically over the network by remote frontends).
2044 (typically over the network by remote frontends).
2027 """
2045 """
2028 from IPython.core.completer import IPCompleter
2046 from IPython.core.completer import IPCompleter
2029 from IPython.core.completerlib import (module_completer,
2047 from IPython.core.completerlib import (module_completer,
2030 magic_run_completer, cd_completer, reset_completer)
2048 magic_run_completer, cd_completer, reset_completer)
2031
2049
2032 self.Completer = IPCompleter(shell=self,
2050 self.Completer = IPCompleter(shell=self,
2033 namespace=self.user_ns,
2051 namespace=self.user_ns,
2034 global_namespace=self.user_global_ns,
2052 global_namespace=self.user_global_ns,
2035 use_readline=self.has_readline,
2053 use_readline=self.has_readline,
2036 parent=self,
2054 parent=self,
2037 )
2055 )
2038 self.configurables.append(self.Completer)
2056 self.configurables.append(self.Completer)
2039
2057
2040 # Add custom completers to the basic ones built into IPCompleter
2058 # Add custom completers to the basic ones built into IPCompleter
2041 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2059 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2042 self.strdispatchers['complete_command'] = sdisp
2060 self.strdispatchers['complete_command'] = sdisp
2043 self.Completer.custom_completers = sdisp
2061 self.Completer.custom_completers = sdisp
2044
2062
2045 self.set_hook('complete_command', module_completer, str_key = 'import')
2063 self.set_hook('complete_command', module_completer, str_key = 'import')
2046 self.set_hook('complete_command', module_completer, str_key = 'from')
2064 self.set_hook('complete_command', module_completer, str_key = 'from')
2047 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2065 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2048 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2066 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2049 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2067 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2050
2068
2051 # Only configure readline if we truly are using readline. IPython can
2069 # Only configure readline if we truly are using readline. IPython can
2052 # do tab-completion over the network, in GUIs, etc, where readline
2070 # do tab-completion over the network, in GUIs, etc, where readline
2053 # itself may be absent
2071 # itself may be absent
2054 if self.has_readline:
2072 if self.has_readline:
2055 self.set_readline_completer()
2073 self.set_readline_completer()
2056
2074
2057 def complete(self, text, line=None, cursor_pos=None):
2075 def complete(self, text, line=None, cursor_pos=None):
2058 """Return the completed text and a list of completions.
2076 """Return the completed text and a list of completions.
2059
2077
2060 Parameters
2078 Parameters
2061 ----------
2079 ----------
2062
2080
2063 text : string
2081 text : string
2064 A string of text to be completed on. It can be given as empty and
2082 A string of text to be completed on. It can be given as empty and
2065 instead a line/position pair are given. In this case, the
2083 instead a line/position pair are given. In this case, the
2066 completer itself will split the line like readline does.
2084 completer itself will split the line like readline does.
2067
2085
2068 line : string, optional
2086 line : string, optional
2069 The complete line that text is part of.
2087 The complete line that text is part of.
2070
2088
2071 cursor_pos : int, optional
2089 cursor_pos : int, optional
2072 The position of the cursor on the input line.
2090 The position of the cursor on the input line.
2073
2091
2074 Returns
2092 Returns
2075 -------
2093 -------
2076 text : string
2094 text : string
2077 The actual text that was completed.
2095 The actual text that was completed.
2078
2096
2079 matches : list
2097 matches : list
2080 A sorted list with all possible completions.
2098 A sorted list with all possible completions.
2081
2099
2082 The optional arguments allow the completion to take more context into
2100 The optional arguments allow the completion to take more context into
2083 account, and are part of the low-level completion API.
2101 account, and are part of the low-level completion API.
2084
2102
2085 This is a wrapper around the completion mechanism, similar to what
2103 This is a wrapper around the completion mechanism, similar to what
2086 readline does at the command line when the TAB key is hit. By
2104 readline does at the command line when the TAB key is hit. By
2087 exposing it as a method, it can be used by other non-readline
2105 exposing it as a method, it can be used by other non-readline
2088 environments (such as GUIs) for text completion.
2106 environments (such as GUIs) for text completion.
2089
2107
2090 Simple usage example:
2108 Simple usage example:
2091
2109
2092 In [1]: x = 'hello'
2110 In [1]: x = 'hello'
2093
2111
2094 In [2]: _ip.complete('x.l')
2112 In [2]: _ip.complete('x.l')
2095 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2113 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2096 """
2114 """
2097
2115
2098 # Inject names into __builtin__ so we can complete on the added names.
2116 # Inject names into __builtin__ so we can complete on the added names.
2099 with self.builtin_trap:
2117 with self.builtin_trap:
2100 return self.Completer.complete(text, line, cursor_pos)
2118 return self.Completer.complete(text, line, cursor_pos)
2101
2119
2102 def set_custom_completer(self, completer, pos=0):
2120 def set_custom_completer(self, completer, pos=0):
2103 """Adds a new custom completer function.
2121 """Adds a new custom completer function.
2104
2122
2105 The position argument (defaults to 0) is the index in the completers
2123 The position argument (defaults to 0) is the index in the completers
2106 list where you want the completer to be inserted."""
2124 list where you want the completer to be inserted."""
2107
2125
2108 newcomp = types.MethodType(completer,self.Completer)
2126 newcomp = types.MethodType(completer,self.Completer)
2109 self.Completer.matchers.insert(pos,newcomp)
2127 self.Completer.matchers.insert(pos,newcomp)
2110
2128
2111 def set_readline_completer(self):
2129 def set_readline_completer(self):
2112 """Reset readline's completer to be our own."""
2130 """Reset readline's completer to be our own."""
2113 self.readline.set_completer(self.Completer.rlcomplete)
2131 self.readline.set_completer(self.Completer.rlcomplete)
2114
2132
2115 def set_completer_frame(self, frame=None):
2133 def set_completer_frame(self, frame=None):
2116 """Set the frame of the completer."""
2134 """Set the frame of the completer."""
2117 if frame:
2135 if frame:
2118 self.Completer.namespace = frame.f_locals
2136 self.Completer.namespace = frame.f_locals
2119 self.Completer.global_namespace = frame.f_globals
2137 self.Completer.global_namespace = frame.f_globals
2120 else:
2138 else:
2121 self.Completer.namespace = self.user_ns
2139 self.Completer.namespace = self.user_ns
2122 self.Completer.global_namespace = self.user_global_ns
2140 self.Completer.global_namespace = self.user_global_ns
2123
2141
2124 #-------------------------------------------------------------------------
2142 #-------------------------------------------------------------------------
2125 # Things related to magics
2143 # Things related to magics
2126 #-------------------------------------------------------------------------
2144 #-------------------------------------------------------------------------
2127
2145
2128 def init_magics(self):
2146 def init_magics(self):
2129 from IPython.core import magics as m
2147 from IPython.core import magics as m
2130 self.magics_manager = magic.MagicsManager(shell=self,
2148 self.magics_manager = magic.MagicsManager(shell=self,
2131 parent=self,
2149 parent=self,
2132 user_magics=m.UserMagics(self))
2150 user_magics=m.UserMagics(self))
2133 self.configurables.append(self.magics_manager)
2151 self.configurables.append(self.magics_manager)
2134
2152
2135 # Expose as public API from the magics manager
2153 # Expose as public API from the magics manager
2136 self.register_magics = self.magics_manager.register
2154 self.register_magics = self.magics_manager.register
2137 self.define_magic = self.magics_manager.define_magic
2155 self.define_magic = self.magics_manager.define_magic
2138
2156
2139 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2157 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2140 m.ConfigMagics, m.DeprecatedMagics, m.DisplayMagics, m.ExecutionMagics,
2158 m.ConfigMagics, m.DeprecatedMagics, m.DisplayMagics, m.ExecutionMagics,
2141 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2159 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2142 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2160 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2143 )
2161 )
2144
2162
2145 # Register Magic Aliases
2163 # Register Magic Aliases
2146 mman = self.magics_manager
2164 mman = self.magics_manager
2147 # FIXME: magic aliases should be defined by the Magics classes
2165 # FIXME: magic aliases should be defined by the Magics classes
2148 # or in MagicsManager, not here
2166 # or in MagicsManager, not here
2149 mman.register_alias('ed', 'edit')
2167 mman.register_alias('ed', 'edit')
2150 mman.register_alias('hist', 'history')
2168 mman.register_alias('hist', 'history')
2151 mman.register_alias('rep', 'recall')
2169 mman.register_alias('rep', 'recall')
2152 mman.register_alias('SVG', 'svg', 'cell')
2170 mman.register_alias('SVG', 'svg', 'cell')
2153 mman.register_alias('HTML', 'html', 'cell')
2171 mman.register_alias('HTML', 'html', 'cell')
2154 mman.register_alias('file', 'writefile', 'cell')
2172 mman.register_alias('file', 'writefile', 'cell')
2155
2173
2156 # FIXME: Move the color initialization to the DisplayHook, which
2174 # FIXME: Move the color initialization to the DisplayHook, which
2157 # should be split into a prompt manager and displayhook. We probably
2175 # should be split into a prompt manager and displayhook. We probably
2158 # even need a centralize colors management object.
2176 # even need a centralize colors management object.
2159 self.magic('colors %s' % self.colors)
2177 self.magic('colors %s' % self.colors)
2160
2178
2161 # Defined here so that it's included in the documentation
2179 # Defined here so that it's included in the documentation
2162 @functools.wraps(magic.MagicsManager.register_function)
2180 @functools.wraps(magic.MagicsManager.register_function)
2163 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2181 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2164 self.magics_manager.register_function(func,
2182 self.magics_manager.register_function(func,
2165 magic_kind=magic_kind, magic_name=magic_name)
2183 magic_kind=magic_kind, magic_name=magic_name)
2166
2184
2167 def run_line_magic(self, magic_name, line):
2185 def run_line_magic(self, magic_name, line):
2168 """Execute the given line magic.
2186 """Execute the given line magic.
2169
2187
2170 Parameters
2188 Parameters
2171 ----------
2189 ----------
2172 magic_name : str
2190 magic_name : str
2173 Name of the desired magic function, without '%' prefix.
2191 Name of the desired magic function, without '%' prefix.
2174
2192
2175 line : str
2193 line : str
2176 The rest of the input line as a single string.
2194 The rest of the input line as a single string.
2177 """
2195 """
2178 fn = self.find_line_magic(magic_name)
2196 fn = self.find_line_magic(magic_name)
2179 if fn is None:
2197 if fn is None:
2180 cm = self.find_cell_magic(magic_name)
2198 cm = self.find_cell_magic(magic_name)
2181 etpl = "Line magic function `%%%s` not found%s."
2199 etpl = "Line magic function `%%%s` not found%s."
2182 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2200 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2183 'did you mean that instead?)' % magic_name )
2201 'did you mean that instead?)' % magic_name )
2184 error(etpl % (magic_name, extra))
2202 error(etpl % (magic_name, extra))
2185 else:
2203 else:
2186 # Note: this is the distance in the stack to the user's frame.
2204 # Note: this is the distance in the stack to the user's frame.
2187 # This will need to be updated if the internal calling logic gets
2205 # This will need to be updated if the internal calling logic gets
2188 # refactored, or else we'll be expanding the wrong variables.
2206 # refactored, or else we'll be expanding the wrong variables.
2189 stack_depth = 2
2207 stack_depth = 2
2190 magic_arg_s = self.var_expand(line, stack_depth)
2208 magic_arg_s = self.var_expand(line, stack_depth)
2191 # Put magic args in a list so we can call with f(*a) syntax
2209 # Put magic args in a list so we can call with f(*a) syntax
2192 args = [magic_arg_s]
2210 args = [magic_arg_s]
2193 kwargs = {}
2211 kwargs = {}
2194 # Grab local namespace if we need it:
2212 # Grab local namespace if we need it:
2195 if getattr(fn, "needs_local_scope", False):
2213 if getattr(fn, "needs_local_scope", False):
2196 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2214 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2197 with self.builtin_trap:
2215 with self.builtin_trap:
2198 result = fn(*args,**kwargs)
2216 result = fn(*args,**kwargs)
2199 return result
2217 return result
2200
2218
2201 def run_cell_magic(self, magic_name, line, cell):
2219 def run_cell_magic(self, magic_name, line, cell):
2202 """Execute the given cell magic.
2220 """Execute the given cell magic.
2203
2221
2204 Parameters
2222 Parameters
2205 ----------
2223 ----------
2206 magic_name : str
2224 magic_name : str
2207 Name of the desired magic function, without '%' prefix.
2225 Name of the desired magic function, without '%' prefix.
2208
2226
2209 line : str
2227 line : str
2210 The rest of the first input line as a single string.
2228 The rest of the first input line as a single string.
2211
2229
2212 cell : str
2230 cell : str
2213 The body of the cell as a (possibly multiline) string.
2231 The body of the cell as a (possibly multiline) string.
2214 """
2232 """
2215 fn = self.find_cell_magic(magic_name)
2233 fn = self.find_cell_magic(magic_name)
2216 if fn is None:
2234 if fn is None:
2217 lm = self.find_line_magic(magic_name)
2235 lm = self.find_line_magic(magic_name)
2218 etpl = "Cell magic `%%{0}` not found{1}."
2236 etpl = "Cell magic `%%{0}` not found{1}."
2219 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2237 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2220 'did you mean that instead?)'.format(magic_name))
2238 'did you mean that instead?)'.format(magic_name))
2221 error(etpl.format(magic_name, extra))
2239 error(etpl.format(magic_name, extra))
2222 elif cell == '':
2240 elif cell == '':
2223 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2241 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2224 if self.find_line_magic(magic_name) is not None:
2242 if self.find_line_magic(magic_name) is not None:
2225 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2243 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2226 raise UsageError(message)
2244 raise UsageError(message)
2227 else:
2245 else:
2228 # Note: this is the distance in the stack to the user's frame.
2246 # Note: this is the distance in the stack to the user's frame.
2229 # This will need to be updated if the internal calling logic gets
2247 # This will need to be updated if the internal calling logic gets
2230 # refactored, or else we'll be expanding the wrong variables.
2248 # refactored, or else we'll be expanding the wrong variables.
2231 stack_depth = 2
2249 stack_depth = 2
2232 magic_arg_s = self.var_expand(line, stack_depth)
2250 magic_arg_s = self.var_expand(line, stack_depth)
2233 with self.builtin_trap:
2251 with self.builtin_trap:
2234 result = fn(magic_arg_s, cell)
2252 result = fn(magic_arg_s, cell)
2235 return result
2253 return result
2236
2254
2237 def find_line_magic(self, magic_name):
2255 def find_line_magic(self, magic_name):
2238 """Find and return a line magic by name.
2256 """Find and return a line magic by name.
2239
2257
2240 Returns None if the magic isn't found."""
2258 Returns None if the magic isn't found."""
2241 return self.magics_manager.magics['line'].get(magic_name)
2259 return self.magics_manager.magics['line'].get(magic_name)
2242
2260
2243 def find_cell_magic(self, magic_name):
2261 def find_cell_magic(self, magic_name):
2244 """Find and return a cell magic by name.
2262 """Find and return a cell magic by name.
2245
2263
2246 Returns None if the magic isn't found."""
2264 Returns None if the magic isn't found."""
2247 return self.magics_manager.magics['cell'].get(magic_name)
2265 return self.magics_manager.magics['cell'].get(magic_name)
2248
2266
2249 def find_magic(self, magic_name, magic_kind='line'):
2267 def find_magic(self, magic_name, magic_kind='line'):
2250 """Find and return a magic of the given type by name.
2268 """Find and return a magic of the given type by name.
2251
2269
2252 Returns None if the magic isn't found."""
2270 Returns None if the magic isn't found."""
2253 return self.magics_manager.magics[magic_kind].get(magic_name)
2271 return self.magics_manager.magics[magic_kind].get(magic_name)
2254
2272
2255 def magic(self, arg_s):
2273 def magic(self, arg_s):
2256 """DEPRECATED. Use run_line_magic() instead.
2274 """DEPRECATED. Use run_line_magic() instead.
2257
2275
2258 Call a magic function by name.
2276 Call a magic function by name.
2259
2277
2260 Input: a string containing the name of the magic function to call and
2278 Input: a string containing the name of the magic function to call and
2261 any additional arguments to be passed to the magic.
2279 any additional arguments to be passed to the magic.
2262
2280
2263 magic('name -opt foo bar') is equivalent to typing at the ipython
2281 magic('name -opt foo bar') is equivalent to typing at the ipython
2264 prompt:
2282 prompt:
2265
2283
2266 In[1]: %name -opt foo bar
2284 In[1]: %name -opt foo bar
2267
2285
2268 To call a magic without arguments, simply use magic('name').
2286 To call a magic without arguments, simply use magic('name').
2269
2287
2270 This provides a proper Python function to call IPython's magics in any
2288 This provides a proper Python function to call IPython's magics in any
2271 valid Python code you can type at the interpreter, including loops and
2289 valid Python code you can type at the interpreter, including loops and
2272 compound statements.
2290 compound statements.
2273 """
2291 """
2274 # TODO: should we issue a loud deprecation warning here?
2292 # TODO: should we issue a loud deprecation warning here?
2275 magic_name, _, magic_arg_s = arg_s.partition(' ')
2293 magic_name, _, magic_arg_s = arg_s.partition(' ')
2276 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2294 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2277 return self.run_line_magic(magic_name, magic_arg_s)
2295 return self.run_line_magic(magic_name, magic_arg_s)
2278
2296
2279 #-------------------------------------------------------------------------
2297 #-------------------------------------------------------------------------
2280 # Things related to macros
2298 # Things related to macros
2281 #-------------------------------------------------------------------------
2299 #-------------------------------------------------------------------------
2282
2300
2283 def define_macro(self, name, themacro):
2301 def define_macro(self, name, themacro):
2284 """Define a new macro
2302 """Define a new macro
2285
2303
2286 Parameters
2304 Parameters
2287 ----------
2305 ----------
2288 name : str
2306 name : str
2289 The name of the macro.
2307 The name of the macro.
2290 themacro : str or Macro
2308 themacro : str or Macro
2291 The action to do upon invoking the macro. If a string, a new
2309 The action to do upon invoking the macro. If a string, a new
2292 Macro object is created by passing the string to it.
2310 Macro object is created by passing the string to it.
2293 """
2311 """
2294
2312
2295 from IPython.core import macro
2313 from IPython.core import macro
2296
2314
2297 if isinstance(themacro, string_types):
2315 if isinstance(themacro, string_types):
2298 themacro = macro.Macro(themacro)
2316 themacro = macro.Macro(themacro)
2299 if not isinstance(themacro, macro.Macro):
2317 if not isinstance(themacro, macro.Macro):
2300 raise ValueError('A macro must be a string or a Macro instance.')
2318 raise ValueError('A macro must be a string or a Macro instance.')
2301 self.user_ns[name] = themacro
2319 self.user_ns[name] = themacro
2302
2320
2303 #-------------------------------------------------------------------------
2321 #-------------------------------------------------------------------------
2304 # Things related to the running of system commands
2322 # Things related to the running of system commands
2305 #-------------------------------------------------------------------------
2323 #-------------------------------------------------------------------------
2306
2324
2307 def system_piped(self, cmd):
2325 def system_piped(self, cmd):
2308 """Call the given cmd in a subprocess, piping stdout/err
2326 """Call the given cmd in a subprocess, piping stdout/err
2309
2327
2310 Parameters
2328 Parameters
2311 ----------
2329 ----------
2312 cmd : str
2330 cmd : str
2313 Command to execute (can not end in '&', as background processes are
2331 Command to execute (can not end in '&', as background processes are
2314 not supported. Should not be a command that expects input
2332 not supported. Should not be a command that expects input
2315 other than simple text.
2333 other than simple text.
2316 """
2334 """
2317 if cmd.rstrip().endswith('&'):
2335 if cmd.rstrip().endswith('&'):
2318 # this is *far* from a rigorous test
2336 # this is *far* from a rigorous test
2319 # We do not support backgrounding processes because we either use
2337 # We do not support backgrounding processes because we either use
2320 # pexpect or pipes to read from. Users can always just call
2338 # pexpect or pipes to read from. Users can always just call
2321 # os.system() or use ip.system=ip.system_raw
2339 # os.system() or use ip.system=ip.system_raw
2322 # if they really want a background process.
2340 # if they really want a background process.
2323 raise OSError("Background processes not supported.")
2341 raise OSError("Background processes not supported.")
2324
2342
2325 # we explicitly do NOT return the subprocess status code, because
2343 # we explicitly do NOT return the subprocess status code, because
2326 # a non-None value would trigger :func:`sys.displayhook` calls.
2344 # a non-None value would trigger :func:`sys.displayhook` calls.
2327 # Instead, we store the exit_code in user_ns.
2345 # Instead, we store the exit_code in user_ns.
2328 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2346 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2329
2347
2330 def system_raw(self, cmd):
2348 def system_raw(self, cmd):
2331 """Call the given cmd in a subprocess using os.system on Windows or
2349 """Call the given cmd in a subprocess using os.system on Windows or
2332 subprocess.call using the system shell on other platforms.
2350 subprocess.call using the system shell on other platforms.
2333
2351
2334 Parameters
2352 Parameters
2335 ----------
2353 ----------
2336 cmd : str
2354 cmd : str
2337 Command to execute.
2355 Command to execute.
2338 """
2356 """
2339 cmd = self.var_expand(cmd, depth=1)
2357 cmd = self.var_expand(cmd, depth=1)
2340 # protect os.system from UNC paths on Windows, which it can't handle:
2358 # protect os.system from UNC paths on Windows, which it can't handle:
2341 if sys.platform == 'win32':
2359 if sys.platform == 'win32':
2342 from IPython.utils._process_win32 import AvoidUNCPath
2360 from IPython.utils._process_win32 import AvoidUNCPath
2343 with AvoidUNCPath() as path:
2361 with AvoidUNCPath() as path:
2344 if path is not None:
2362 if path is not None:
2345 cmd = '"pushd %s &&"%s' % (path, cmd)
2363 cmd = '"pushd %s &&"%s' % (path, cmd)
2346 cmd = py3compat.unicode_to_str(cmd)
2364 cmd = py3compat.unicode_to_str(cmd)
2347 ec = os.system(cmd)
2365 try:
2366 ec = os.system(cmd)
2367 except KeyboardInterrupt:
2368 self.write_err('\n' + self.get_exception_only())
2369 ec = -2
2348 else:
2370 else:
2349 cmd = py3compat.unicode_to_str(cmd)
2371 cmd = py3compat.unicode_to_str(cmd)
2350 # Call the cmd using the OS shell, instead of the default /bin/sh, if set.
2372 # For posix the result of the subprocess.call() below is an exit
2351 ec = subprocess.call(cmd, shell=True, executable=os.environ.get('SHELL', None))
2373 # code, which by convention is zero for success, positive for
2352 # exit code is positive for program failure, or negative for
2374 # program failure. Exit codes above 128 are reserved for signals,
2353 # terminating signal number.
2375 # and the formula for converting a signal to an exit code is usually
2354
2376 # signal_number+128. To more easily differentiate between exit
2355 # Interpret ec > 128 as signal
2377 # codes and signals, ipython uses negative numbers. For instance
2356 # Some shells (csh, fish) don't follow sh/bash conventions for exit codes
2378 # since control-c is signal 2 but exit code 130, ipython's
2379 # _exit_code variable will read -2. Note that some shells like
2380 # csh and fish don't follow sh/bash conventions for exit codes.
2381 executable = os.environ.get('SHELL', None)
2382 try:
2383 # Use env shell instead of default /bin/sh
2384 ec = subprocess.call(cmd, shell=True, executable=executable)
2385 except KeyboardInterrupt:
2386 # intercept control-C; a long traceback is not useful here
2387 self.write_err('\n' + self.get_exception_only())
2388 ec = 130
2357 if ec > 128:
2389 if ec > 128:
2358 ec = -(ec - 128)
2390 ec = -(ec - 128)
2359
2391
2360 # We explicitly do NOT return the subprocess status code, because
2392 # We explicitly do NOT return the subprocess status code, because
2361 # a non-None value would trigger :func:`sys.displayhook` calls.
2393 # a non-None value would trigger :func:`sys.displayhook` calls.
2362 # Instead, we store the exit_code in user_ns.
2394 # Instead, we store the exit_code in user_ns. Note the semantics
2395 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2396 # but raising SystemExit(_exit_code) will give status 254!
2363 self.user_ns['_exit_code'] = ec
2397 self.user_ns['_exit_code'] = ec
2364
2398
2365 # use piped system by default, because it is better behaved
2399 # use piped system by default, because it is better behaved
2366 system = system_piped
2400 system = system_piped
2367
2401
2368 def getoutput(self, cmd, split=True, depth=0):
2402 def getoutput(self, cmd, split=True, depth=0):
2369 """Get output (possibly including stderr) from a subprocess.
2403 """Get output (possibly including stderr) from a subprocess.
2370
2404
2371 Parameters
2405 Parameters
2372 ----------
2406 ----------
2373 cmd : str
2407 cmd : str
2374 Command to execute (can not end in '&', as background processes are
2408 Command to execute (can not end in '&', as background processes are
2375 not supported.
2409 not supported.
2376 split : bool, optional
2410 split : bool, optional
2377 If True, split the output into an IPython SList. Otherwise, an
2411 If True, split the output into an IPython SList. Otherwise, an
2378 IPython LSString is returned. These are objects similar to normal
2412 IPython LSString is returned. These are objects similar to normal
2379 lists and strings, with a few convenience attributes for easier
2413 lists and strings, with a few convenience attributes for easier
2380 manipulation of line-based output. You can use '?' on them for
2414 manipulation of line-based output. You can use '?' on them for
2381 details.
2415 details.
2382 depth : int, optional
2416 depth : int, optional
2383 How many frames above the caller are the local variables which should
2417 How many frames above the caller are the local variables which should
2384 be expanded in the command string? The default (0) assumes that the
2418 be expanded in the command string? The default (0) assumes that the
2385 expansion variables are in the stack frame calling this function.
2419 expansion variables are in the stack frame calling this function.
2386 """
2420 """
2387 if cmd.rstrip().endswith('&'):
2421 if cmd.rstrip().endswith('&'):
2388 # this is *far* from a rigorous test
2422 # this is *far* from a rigorous test
2389 raise OSError("Background processes not supported.")
2423 raise OSError("Background processes not supported.")
2390 out = getoutput(self.var_expand(cmd, depth=depth+1))
2424 out = getoutput(self.var_expand(cmd, depth=depth+1))
2391 if split:
2425 if split:
2392 out = SList(out.splitlines())
2426 out = SList(out.splitlines())
2393 else:
2427 else:
2394 out = LSString(out)
2428 out = LSString(out)
2395 return out
2429 return out
2396
2430
2397 #-------------------------------------------------------------------------
2431 #-------------------------------------------------------------------------
2398 # Things related to aliases
2432 # Things related to aliases
2399 #-------------------------------------------------------------------------
2433 #-------------------------------------------------------------------------
2400
2434
2401 def init_alias(self):
2435 def init_alias(self):
2402 self.alias_manager = AliasManager(shell=self, parent=self)
2436 self.alias_manager = AliasManager(shell=self, parent=self)
2403 self.configurables.append(self.alias_manager)
2437 self.configurables.append(self.alias_manager)
2404
2438
2405 #-------------------------------------------------------------------------
2439 #-------------------------------------------------------------------------
2406 # Things related to extensions
2440 # Things related to extensions
2407 #-------------------------------------------------------------------------
2441 #-------------------------------------------------------------------------
2408
2442
2409 def init_extension_manager(self):
2443 def init_extension_manager(self):
2410 self.extension_manager = ExtensionManager(shell=self, parent=self)
2444 self.extension_manager = ExtensionManager(shell=self, parent=self)
2411 self.configurables.append(self.extension_manager)
2445 self.configurables.append(self.extension_manager)
2412
2446
2413 #-------------------------------------------------------------------------
2447 #-------------------------------------------------------------------------
2414 # Things related to payloads
2448 # Things related to payloads
2415 #-------------------------------------------------------------------------
2449 #-------------------------------------------------------------------------
2416
2450
2417 def init_payload(self):
2451 def init_payload(self):
2418 self.payload_manager = PayloadManager(parent=self)
2452 self.payload_manager = PayloadManager(parent=self)
2419 self.configurables.append(self.payload_manager)
2453 self.configurables.append(self.payload_manager)
2420
2454
2421 #-------------------------------------------------------------------------
2455 #-------------------------------------------------------------------------
2422 # Things related to widgets
2423 #-------------------------------------------------------------------------
2424
2425 def init_comms(self):
2426 # not implemented in the base class
2427 pass
2428
2429 #-------------------------------------------------------------------------
2430 # Things related to the prefilter
2456 # Things related to the prefilter
2431 #-------------------------------------------------------------------------
2457 #-------------------------------------------------------------------------
2432
2458
2433 def init_prefilter(self):
2459 def init_prefilter(self):
2434 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2460 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2435 self.configurables.append(self.prefilter_manager)
2461 self.configurables.append(self.prefilter_manager)
2436 # Ultimately this will be refactored in the new interpreter code, but
2462 # Ultimately this will be refactored in the new interpreter code, but
2437 # for now, we should expose the main prefilter method (there's legacy
2463 # for now, we should expose the main prefilter method (there's legacy
2438 # code out there that may rely on this).
2464 # code out there that may rely on this).
2439 self.prefilter = self.prefilter_manager.prefilter_lines
2465 self.prefilter = self.prefilter_manager.prefilter_lines
2440
2466
2441 def auto_rewrite_input(self, cmd):
2467 def auto_rewrite_input(self, cmd):
2442 """Print to the screen the rewritten form of the user's command.
2468 """Print to the screen the rewritten form of the user's command.
2443
2469
2444 This shows visual feedback by rewriting input lines that cause
2470 This shows visual feedback by rewriting input lines that cause
2445 automatic calling to kick in, like::
2471 automatic calling to kick in, like::
2446
2472
2447 /f x
2473 /f x
2448
2474
2449 into::
2475 into::
2450
2476
2451 ------> f(x)
2477 ------> f(x)
2452
2478
2453 after the user's input prompt. This helps the user understand that the
2479 after the user's input prompt. This helps the user understand that the
2454 input line was transformed automatically by IPython.
2480 input line was transformed automatically by IPython.
2455 """
2481 """
2456 if not self.show_rewritten_input:
2482 if not self.show_rewritten_input:
2457 return
2483 return
2458
2484
2459 rw = self.prompt_manager.render('rewrite') + cmd
2485 rw = self.prompt_manager.render('rewrite') + cmd
2460
2486
2461 try:
2487 try:
2462 # plain ascii works better w/ pyreadline, on some machines, so
2488 # plain ascii works better w/ pyreadline, on some machines, so
2463 # we use it and only print uncolored rewrite if we have unicode
2489 # we use it and only print uncolored rewrite if we have unicode
2464 rw = str(rw)
2490 rw = str(rw)
2465 print(rw, file=io.stdout)
2491 print(rw, file=io.stdout)
2466 except UnicodeEncodeError:
2492 except UnicodeEncodeError:
2467 print("------> " + cmd)
2493 print("------> " + cmd)
2468
2494
2469 #-------------------------------------------------------------------------
2495 #-------------------------------------------------------------------------
2470 # Things related to extracting values/expressions from kernel and user_ns
2496 # Things related to extracting values/expressions from kernel and user_ns
2471 #-------------------------------------------------------------------------
2497 #-------------------------------------------------------------------------
2472
2498
2473 def _user_obj_error(self):
2499 def _user_obj_error(self):
2474 """return simple exception dict
2500 """return simple exception dict
2475
2501
2476 for use in user_expressions
2502 for use in user_expressions
2477 """
2503 """
2478
2504
2479 etype, evalue, tb = self._get_exc_info()
2505 etype, evalue, tb = self._get_exc_info()
2480 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2506 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2481
2507
2482 exc_info = {
2508 exc_info = {
2483 u'status' : 'error',
2509 u'status' : 'error',
2484 u'traceback' : stb,
2510 u'traceback' : stb,
2485 u'ename' : unicode_type(etype.__name__),
2511 u'ename' : unicode_type(etype.__name__),
2486 u'evalue' : py3compat.safe_unicode(evalue),
2512 u'evalue' : py3compat.safe_unicode(evalue),
2487 }
2513 }
2488
2514
2489 return exc_info
2515 return exc_info
2490
2516
2491 def _format_user_obj(self, obj):
2517 def _format_user_obj(self, obj):
2492 """format a user object to display dict
2518 """format a user object to display dict
2493
2519
2494 for use in user_expressions
2520 for use in user_expressions
2495 """
2521 """
2496
2522
2497 data, md = self.display_formatter.format(obj)
2523 data, md = self.display_formatter.format(obj)
2498 value = {
2524 value = {
2499 'status' : 'ok',
2525 'status' : 'ok',
2500 'data' : data,
2526 'data' : data,
2501 'metadata' : md,
2527 'metadata' : md,
2502 }
2528 }
2503 return value
2529 return value
2504
2530
2505 def user_expressions(self, expressions):
2531 def user_expressions(self, expressions):
2506 """Evaluate a dict of expressions in the user's namespace.
2532 """Evaluate a dict of expressions in the user's namespace.
2507
2533
2508 Parameters
2534 Parameters
2509 ----------
2535 ----------
2510 expressions : dict
2536 expressions : dict
2511 A dict with string keys and string values. The expression values
2537 A dict with string keys and string values. The expression values
2512 should be valid Python expressions, each of which will be evaluated
2538 should be valid Python expressions, each of which will be evaluated
2513 in the user namespace.
2539 in the user namespace.
2514
2540
2515 Returns
2541 Returns
2516 -------
2542 -------
2517 A dict, keyed like the input expressions dict, with the rich mime-typed
2543 A dict, keyed like the input expressions dict, with the rich mime-typed
2518 display_data of each value.
2544 display_data of each value.
2519 """
2545 """
2520 out = {}
2546 out = {}
2521 user_ns = self.user_ns
2547 user_ns = self.user_ns
2522 global_ns = self.user_global_ns
2548 global_ns = self.user_global_ns
2523
2549
2524 for key, expr in iteritems(expressions):
2550 for key, expr in iteritems(expressions):
2525 try:
2551 try:
2526 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2552 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2527 except:
2553 except:
2528 value = self._user_obj_error()
2554 value = self._user_obj_error()
2529 out[key] = value
2555 out[key] = value
2530 return out
2556 return out
2531
2557
2532 #-------------------------------------------------------------------------
2558 #-------------------------------------------------------------------------
2533 # Things related to the running of code
2559 # Things related to the running of code
2534 #-------------------------------------------------------------------------
2560 #-------------------------------------------------------------------------
2535
2561
2536 def ex(self, cmd):
2562 def ex(self, cmd):
2537 """Execute a normal python statement in user namespace."""
2563 """Execute a normal python statement in user namespace."""
2538 with self.builtin_trap:
2564 with self.builtin_trap:
2539 exec(cmd, self.user_global_ns, self.user_ns)
2565 exec(cmd, self.user_global_ns, self.user_ns)
2540
2566
2541 def ev(self, expr):
2567 def ev(self, expr):
2542 """Evaluate python expression expr in user namespace.
2568 """Evaluate python expression expr in user namespace.
2543
2569
2544 Returns the result of evaluation
2570 Returns the result of evaluation
2545 """
2571 """
2546 with self.builtin_trap:
2572 with self.builtin_trap:
2547 return eval(expr, self.user_global_ns, self.user_ns)
2573 return eval(expr, self.user_global_ns, self.user_ns)
2548
2574
2549 def safe_execfile(self, fname, *where, **kw):
2575 def safe_execfile(self, fname, *where, **kw):
2550 """A safe version of the builtin execfile().
2576 """A safe version of the builtin execfile().
2551
2577
2552 This version will never throw an exception, but instead print
2578 This version will never throw an exception, but instead print
2553 helpful error messages to the screen. This only works on pure
2579 helpful error messages to the screen. This only works on pure
2554 Python files with the .py extension.
2580 Python files with the .py extension.
2555
2581
2556 Parameters
2582 Parameters
2557 ----------
2583 ----------
2558 fname : string
2584 fname : string
2559 The name of the file to be executed.
2585 The name of the file to be executed.
2560 where : tuple
2586 where : tuple
2561 One or two namespaces, passed to execfile() as (globals,locals).
2587 One or two namespaces, passed to execfile() as (globals,locals).
2562 If only one is given, it is passed as both.
2588 If only one is given, it is passed as both.
2563 exit_ignore : bool (False)
2589 exit_ignore : bool (False)
2564 If True, then silence SystemExit for non-zero status (it is always
2590 If True, then silence SystemExit for non-zero status (it is always
2565 silenced for zero status, as it is so common).
2591 silenced for zero status, as it is so common).
2566 raise_exceptions : bool (False)
2592 raise_exceptions : bool (False)
2567 If True raise exceptions everywhere. Meant for testing.
2593 If True raise exceptions everywhere. Meant for testing.
2594 shell_futures : bool (False)
2595 If True, the code will share future statements with the interactive
2596 shell. It will both be affected by previous __future__ imports, and
2597 any __future__ imports in the code will affect the shell. If False,
2598 __future__ imports are not shared in either direction.
2568
2599
2569 """
2600 """
2570 kw.setdefault('exit_ignore', False)
2601 kw.setdefault('exit_ignore', False)
2571 kw.setdefault('raise_exceptions', False)
2602 kw.setdefault('raise_exceptions', False)
2603 kw.setdefault('shell_futures', False)
2572
2604
2573 fname = os.path.abspath(os.path.expanduser(fname))
2605 fname = os.path.abspath(os.path.expanduser(fname))
2574
2606
2575 # Make sure we can open the file
2607 # Make sure we can open the file
2576 try:
2608 try:
2577 with open(fname) as thefile:
2609 with open(fname) as thefile:
2578 pass
2610 pass
2579 except:
2611 except:
2580 warn('Could not open file <%s> for safe execution.' % fname)
2612 warn('Could not open file <%s> for safe execution.' % fname)
2581 return
2613 return
2582
2614
2583 # Find things also in current directory. This is needed to mimic the
2615 # Find things also in current directory. This is needed to mimic the
2584 # behavior of running a script from the system command line, where
2616 # behavior of running a script from the system command line, where
2585 # Python inserts the script's directory into sys.path
2617 # Python inserts the script's directory into sys.path
2586 dname = os.path.dirname(fname)
2618 dname = os.path.dirname(fname)
2587
2619
2588 with prepended_to_syspath(dname):
2620 with prepended_to_syspath(dname):
2589 try:
2621 try:
2590 py3compat.execfile(fname,*where)
2622 glob, loc = (where + (None, ))[:2]
2623 py3compat.execfile(
2624 fname, glob, loc,
2625 self.compile if kw['shell_futures'] else None)
2591 except SystemExit as status:
2626 except SystemExit as status:
2592 # If the call was made with 0 or None exit status (sys.exit(0)
2627 # If the call was made with 0 or None exit status (sys.exit(0)
2593 # or sys.exit() ), don't bother showing a traceback, as both of
2628 # or sys.exit() ), don't bother showing a traceback, as both of
2594 # these are considered normal by the OS:
2629 # these are considered normal by the OS:
2595 # > python -c'import sys;sys.exit(0)'; echo $?
2630 # > python -c'import sys;sys.exit(0)'; echo $?
2596 # 0
2631 # 0
2597 # > python -c'import sys;sys.exit()'; echo $?
2632 # > python -c'import sys;sys.exit()'; echo $?
2598 # 0
2633 # 0
2599 # For other exit status, we show the exception unless
2634 # For other exit status, we show the exception unless
2600 # explicitly silenced, but only in short form.
2635 # explicitly silenced, but only in short form.
2601 if kw['raise_exceptions']:
2636 if kw['raise_exceptions']:
2602 raise
2637 raise
2603 if status.code and not kw['exit_ignore']:
2638 if status.code and not kw['exit_ignore']:
2604 self.showtraceback(exception_only=True)
2639 self.showtraceback(exception_only=True)
2605 except:
2640 except:
2606 if kw['raise_exceptions']:
2641 if kw['raise_exceptions']:
2607 raise
2642 raise
2608 # tb offset is 2 because we wrap execfile
2643 # tb offset is 2 because we wrap execfile
2609 self.showtraceback(tb_offset=2)
2644 self.showtraceback(tb_offset=2)
2610
2645
2611 def safe_execfile_ipy(self, fname):
2646 def safe_execfile_ipy(self, fname, shell_futures=False):
2612 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2647 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2613
2648
2614 Parameters
2649 Parameters
2615 ----------
2650 ----------
2616 fname : str
2651 fname : str
2617 The name of the file to execute. The filename must have a
2652 The name of the file to execute. The filename must have a
2618 .ipy or .ipynb extension.
2653 .ipy or .ipynb extension.
2654 shell_futures : bool (False)
2655 If True, the code will share future statements with the interactive
2656 shell. It will both be affected by previous __future__ imports, and
2657 any __future__ imports in the code will affect the shell. If False,
2658 __future__ imports are not shared in either direction.
2619 """
2659 """
2620 fname = os.path.abspath(os.path.expanduser(fname))
2660 fname = os.path.abspath(os.path.expanduser(fname))
2621
2661
2622 # Make sure we can open the file
2662 # Make sure we can open the file
2623 try:
2663 try:
2624 with open(fname) as thefile:
2664 with open(fname) as thefile:
2625 pass
2665 pass
2626 except:
2666 except:
2627 warn('Could not open file <%s> for safe execution.' % fname)
2667 warn('Could not open file <%s> for safe execution.' % fname)
2628 return
2668 return
2629
2669
2630 # Find things also in current directory. This is needed to mimic the
2670 # Find things also in current directory. This is needed to mimic the
2631 # behavior of running a script from the system command line, where
2671 # behavior of running a script from the system command line, where
2632 # Python inserts the script's directory into sys.path
2672 # Python inserts the script's directory into sys.path
2633 dname = os.path.dirname(fname)
2673 dname = os.path.dirname(fname)
2634
2674
2635 def get_cells():
2675 def get_cells():
2636 """generator for sequence of code blocks to run"""
2676 """generator for sequence of code blocks to run"""
2637 if fname.endswith('.ipynb'):
2677 if fname.endswith('.ipynb'):
2638 from IPython.nbformat import current
2678 from IPython.nbformat import read
2639 with open(fname) as f:
2679 with io_open(fname) as f:
2640 nb = current.read(f, 'json')
2680 nb = read(f, as_version=4)
2641 if not nb.worksheets:
2681 if not nb.cells:
2642 return
2682 return
2643 for cell in nb.worksheets[0].cells:
2683 for cell in nb.cells:
2644 if cell.cell_type == 'code':
2684 if cell.cell_type == 'code':
2645 yield cell.input
2685 yield cell.source
2646 else:
2686 else:
2647 with open(fname) as f:
2687 with open(fname) as f:
2648 yield f.read()
2688 yield f.read()
2649
2689
2650 with prepended_to_syspath(dname):
2690 with prepended_to_syspath(dname):
2651 try:
2691 try:
2652 for cell in get_cells():
2692 for cell in get_cells():
2653 # self.run_cell currently captures all exceptions
2693 # self.run_cell currently captures all exceptions
2654 # raised in user code. It would be nice if there were
2694 # raised in user code. It would be nice if there were
2655 # versions of run_cell that did raise, so
2695 # versions of run_cell that did raise, so
2656 # we could catch the errors.
2696 # we could catch the errors.
2657 self.run_cell(cell, silent=True, shell_futures=False)
2697 self.run_cell(cell, silent=True, shell_futures=shell_futures)
2658 except:
2698 except:
2659 self.showtraceback()
2699 self.showtraceback()
2660 warn('Unknown failure executing file: <%s>' % fname)
2700 warn('Unknown failure executing file: <%s>' % fname)
2661
2701
2662 def safe_run_module(self, mod_name, where):
2702 def safe_run_module(self, mod_name, where):
2663 """A safe version of runpy.run_module().
2703 """A safe version of runpy.run_module().
2664
2704
2665 This version will never throw an exception, but instead print
2705 This version will never throw an exception, but instead print
2666 helpful error messages to the screen.
2706 helpful error messages to the screen.
2667
2707
2668 `SystemExit` exceptions with status code 0 or None are ignored.
2708 `SystemExit` exceptions with status code 0 or None are ignored.
2669
2709
2670 Parameters
2710 Parameters
2671 ----------
2711 ----------
2672 mod_name : string
2712 mod_name : string
2673 The name of the module to be executed.
2713 The name of the module to be executed.
2674 where : dict
2714 where : dict
2675 The globals namespace.
2715 The globals namespace.
2676 """
2716 """
2677 try:
2717 try:
2678 try:
2718 try:
2679 where.update(
2719 where.update(
2680 runpy.run_module(str(mod_name), run_name="__main__",
2720 runpy.run_module(str(mod_name), run_name="__main__",
2681 alter_sys=True)
2721 alter_sys=True)
2682 )
2722 )
2683 except SystemExit as status:
2723 except SystemExit as status:
2684 if status.code:
2724 if status.code:
2685 raise
2725 raise
2686 except:
2726 except:
2687 self.showtraceback()
2727 self.showtraceback()
2688 warn('Unknown failure executing module: <%s>' % mod_name)
2728 warn('Unknown failure executing module: <%s>' % mod_name)
2689
2729
2690 def _run_cached_cell_magic(self, magic_name, line):
2730 def _run_cached_cell_magic(self, magic_name, line):
2691 """Special method to call a cell magic with the data stored in self.
2731 """Special method to call a cell magic with the data stored in self.
2692 """
2732 """
2693 cell = self._current_cell_magic_body
2733 cell = self._current_cell_magic_body
2694 self._current_cell_magic_body = None
2734 self._current_cell_magic_body = None
2695 return self.run_cell_magic(magic_name, line, cell)
2735 return self.run_cell_magic(magic_name, line, cell)
2696
2736
2697 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2737 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2698 """Run a complete IPython cell.
2738 """Run a complete IPython cell.
2699
2739
2700 Parameters
2740 Parameters
2701 ----------
2741 ----------
2702 raw_cell : str
2742 raw_cell : str
2703 The code (including IPython code such as %magic functions) to run.
2743 The code (including IPython code such as %magic functions) to run.
2704 store_history : bool
2744 store_history : bool
2705 If True, the raw and translated cell will be stored in IPython's
2745 If True, the raw and translated cell will be stored in IPython's
2706 history. For user code calling back into IPython's machinery, this
2746 history. For user code calling back into IPython's machinery, this
2707 should be set to False.
2747 should be set to False.
2708 silent : bool
2748 silent : bool
2709 If True, avoid side-effects, such as implicit displayhooks and
2749 If True, avoid side-effects, such as implicit displayhooks and
2710 and logging. silent=True forces store_history=False.
2750 and logging. silent=True forces store_history=False.
2711 shell_futures : bool
2751 shell_futures : bool
2712 If True, the code will share future statements with the interactive
2752 If True, the code will share future statements with the interactive
2713 shell. It will both be affected by previous __future__ imports, and
2753 shell. It will both be affected by previous __future__ imports, and
2714 any __future__ imports in the code will affect the shell. If False,
2754 any __future__ imports in the code will affect the shell. If False,
2715 __future__ imports are not shared in either direction.
2755 __future__ imports are not shared in either direction.
2716 """
2756 """
2717 if (not raw_cell) or raw_cell.isspace():
2757 if (not raw_cell) or raw_cell.isspace():
2718 return
2758 return
2719
2759
2720 if silent:
2760 if silent:
2721 store_history = False
2761 store_history = False
2722
2762
2723 self.events.trigger('pre_execute')
2763 self.events.trigger('pre_execute')
2724 if not silent:
2764 if not silent:
2725 self.events.trigger('pre_run_cell')
2765 self.events.trigger('pre_run_cell')
2726
2766
2727 # If any of our input transformation (input_transformer_manager or
2767 # If any of our input transformation (input_transformer_manager or
2728 # prefilter_manager) raises an exception, we store it in this variable
2768 # prefilter_manager) raises an exception, we store it in this variable
2729 # so that we can display the error after logging the input and storing
2769 # so that we can display the error after logging the input and storing
2730 # it in the history.
2770 # it in the history.
2731 preprocessing_exc_tuple = None
2771 preprocessing_exc_tuple = None
2732 try:
2772 try:
2733 # Static input transformations
2773 # Static input transformations
2734 cell = self.input_transformer_manager.transform_cell(raw_cell)
2774 cell = self.input_transformer_manager.transform_cell(raw_cell)
2735 except SyntaxError:
2775 except SyntaxError:
2736 preprocessing_exc_tuple = sys.exc_info()
2776 preprocessing_exc_tuple = sys.exc_info()
2737 cell = raw_cell # cell has to exist so it can be stored/logged
2777 cell = raw_cell # cell has to exist so it can be stored/logged
2738 else:
2778 else:
2739 if len(cell.splitlines()) == 1:
2779 if len(cell.splitlines()) == 1:
2740 # Dynamic transformations - only applied for single line commands
2780 # Dynamic transformations - only applied for single line commands
2741 with self.builtin_trap:
2781 with self.builtin_trap:
2742 try:
2782 try:
2743 # use prefilter_lines to handle trailing newlines
2783 # use prefilter_lines to handle trailing newlines
2744 # restore trailing newline for ast.parse
2784 # restore trailing newline for ast.parse
2745 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2785 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2746 except Exception:
2786 except Exception:
2747 # don't allow prefilter errors to crash IPython
2787 # don't allow prefilter errors to crash IPython
2748 preprocessing_exc_tuple = sys.exc_info()
2788 preprocessing_exc_tuple = sys.exc_info()
2749
2789
2750 # Store raw and processed history
2790 # Store raw and processed history
2751 if store_history:
2791 if store_history:
2752 self.history_manager.store_inputs(self.execution_count,
2792 self.history_manager.store_inputs(self.execution_count,
2753 cell, raw_cell)
2793 cell, raw_cell)
2754 if not silent:
2794 if not silent:
2755 self.logger.log(cell, raw_cell)
2795 self.logger.log(cell, raw_cell)
2756
2796
2757 # Display the exception if input processing failed.
2797 # Display the exception if input processing failed.
2758 if preprocessing_exc_tuple is not None:
2798 if preprocessing_exc_tuple is not None:
2759 self.showtraceback(preprocessing_exc_tuple)
2799 self.showtraceback(preprocessing_exc_tuple)
2760 if store_history:
2800 if store_history:
2761 self.execution_count += 1
2801 self.execution_count += 1
2762 return
2802 return
2763
2803
2764 # Our own compiler remembers the __future__ environment. If we want to
2804 # Our own compiler remembers the __future__ environment. If we want to
2765 # run code with a separate __future__ environment, use the default
2805 # run code with a separate __future__ environment, use the default
2766 # compiler
2806 # compiler
2767 compiler = self.compile if shell_futures else CachingCompiler()
2807 compiler = self.compile if shell_futures else CachingCompiler()
2768
2808
2769 with self.builtin_trap:
2809 with self.builtin_trap:
2770 cell_name = self.compile.cache(cell, self.execution_count)
2810 cell_name = self.compile.cache(cell, self.execution_count)
2771
2811
2772 with self.display_trap:
2812 with self.display_trap:
2773 # Compile to bytecode
2813 # Compile to bytecode
2774 try:
2814 try:
2775 code_ast = compiler.ast_parse(cell, filename=cell_name)
2815 code_ast = compiler.ast_parse(cell, filename=cell_name)
2776 except IndentationError:
2816 except IndentationError:
2777 self.showindentationerror()
2817 self.showindentationerror()
2778 if store_history:
2818 if store_history:
2779 self.execution_count += 1
2819 self.execution_count += 1
2780 return None
2820 return None
2781 except (OverflowError, SyntaxError, ValueError, TypeError,
2821 except (OverflowError, SyntaxError, ValueError, TypeError,
2782 MemoryError):
2822 MemoryError):
2783 self.showsyntaxerror()
2823 self.showsyntaxerror()
2784 if store_history:
2824 if store_history:
2785 self.execution_count += 1
2825 self.execution_count += 1
2786 return None
2826 return None
2787
2827
2788 # Apply AST transformations
2828 # Apply AST transformations
2789 try:
2829 try:
2790 code_ast = self.transform_ast(code_ast)
2830 code_ast = self.transform_ast(code_ast)
2791 except InputRejected:
2831 except InputRejected:
2792 self.showtraceback()
2832 self.showtraceback()
2793 if store_history:
2833 if store_history:
2794 self.execution_count += 1
2834 self.execution_count += 1
2795 return None
2835 return None
2796
2836
2797 # Execute the user code
2837 # Execute the user code
2798 interactivity = "none" if silent else self.ast_node_interactivity
2838 interactivity = "none" if silent else self.ast_node_interactivity
2799 self.run_ast_nodes(code_ast.body, cell_name,
2839 self.run_ast_nodes(code_ast.body, cell_name,
2800 interactivity=interactivity, compiler=compiler)
2840 interactivity=interactivity, compiler=compiler)
2801
2841
2802 self.events.trigger('post_execute')
2842 self.events.trigger('post_execute')
2803 if not silent:
2843 if not silent:
2804 self.events.trigger('post_run_cell')
2844 self.events.trigger('post_run_cell')
2805
2845
2806 if store_history:
2846 if store_history:
2807 # Write output to the database. Does nothing unless
2847 # Write output to the database. Does nothing unless
2808 # history output logging is enabled.
2848 # history output logging is enabled.
2809 self.history_manager.store_output(self.execution_count)
2849 self.history_manager.store_output(self.execution_count)
2810 # Each cell is a *single* input, regardless of how many lines it has
2850 # Each cell is a *single* input, regardless of how many lines it has
2811 self.execution_count += 1
2851 self.execution_count += 1
2812
2852
2813 def transform_ast(self, node):
2853 def transform_ast(self, node):
2814 """Apply the AST transformations from self.ast_transformers
2854 """Apply the AST transformations from self.ast_transformers
2815
2855
2816 Parameters
2856 Parameters
2817 ----------
2857 ----------
2818 node : ast.Node
2858 node : ast.Node
2819 The root node to be transformed. Typically called with the ast.Module
2859 The root node to be transformed. Typically called with the ast.Module
2820 produced by parsing user input.
2860 produced by parsing user input.
2821
2861
2822 Returns
2862 Returns
2823 -------
2863 -------
2824 An ast.Node corresponding to the node it was called with. Note that it
2864 An ast.Node corresponding to the node it was called with. Note that it
2825 may also modify the passed object, so don't rely on references to the
2865 may also modify the passed object, so don't rely on references to the
2826 original AST.
2866 original AST.
2827 """
2867 """
2828 for transformer in self.ast_transformers:
2868 for transformer in self.ast_transformers:
2829 try:
2869 try:
2830 node = transformer.visit(node)
2870 node = transformer.visit(node)
2831 except InputRejected:
2871 except InputRejected:
2832 # User-supplied AST transformers can reject an input by raising
2872 # User-supplied AST transformers can reject an input by raising
2833 # an InputRejected. Short-circuit in this case so that we
2873 # an InputRejected. Short-circuit in this case so that we
2834 # don't unregister the transform.
2874 # don't unregister the transform.
2835 raise
2875 raise
2836 except Exception:
2876 except Exception:
2837 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
2877 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
2838 self.ast_transformers.remove(transformer)
2878 self.ast_transformers.remove(transformer)
2839
2879
2840 if self.ast_transformers:
2880 if self.ast_transformers:
2841 ast.fix_missing_locations(node)
2881 ast.fix_missing_locations(node)
2842 return node
2882 return node
2843
2883
2844
2884
2845 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2885 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2846 compiler=compile):
2886 compiler=compile):
2847 """Run a sequence of AST nodes. The execution mode depends on the
2887 """Run a sequence of AST nodes. The execution mode depends on the
2848 interactivity parameter.
2888 interactivity parameter.
2849
2889
2850 Parameters
2890 Parameters
2851 ----------
2891 ----------
2852 nodelist : list
2892 nodelist : list
2853 A sequence of AST nodes to run.
2893 A sequence of AST nodes to run.
2854 cell_name : str
2894 cell_name : str
2855 Will be passed to the compiler as the filename of the cell. Typically
2895 Will be passed to the compiler as the filename of the cell. Typically
2856 the value returned by ip.compile.cache(cell).
2896 the value returned by ip.compile.cache(cell).
2857 interactivity : str
2897 interactivity : str
2858 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2898 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2859 run interactively (displaying output from expressions). 'last_expr'
2899 run interactively (displaying output from expressions). 'last_expr'
2860 will run the last node interactively only if it is an expression (i.e.
2900 will run the last node interactively only if it is an expression (i.e.
2861 expressions in loops or other blocks are not displayed. Other values
2901 expressions in loops or other blocks are not displayed. Other values
2862 for this parameter will raise a ValueError.
2902 for this parameter will raise a ValueError.
2863 compiler : callable
2903 compiler : callable
2864 A function with the same interface as the built-in compile(), to turn
2904 A function with the same interface as the built-in compile(), to turn
2865 the AST nodes into code objects. Default is the built-in compile().
2905 the AST nodes into code objects. Default is the built-in compile().
2866 """
2906 """
2867 if not nodelist:
2907 if not nodelist:
2868 return
2908 return
2869
2909
2870 if interactivity == 'last_expr':
2910 if interactivity == 'last_expr':
2871 if isinstance(nodelist[-1], ast.Expr):
2911 if isinstance(nodelist[-1], ast.Expr):
2872 interactivity = "last"
2912 interactivity = "last"
2873 else:
2913 else:
2874 interactivity = "none"
2914 interactivity = "none"
2875
2915
2876 if interactivity == 'none':
2916 if interactivity == 'none':
2877 to_run_exec, to_run_interactive = nodelist, []
2917 to_run_exec, to_run_interactive = nodelist, []
2878 elif interactivity == 'last':
2918 elif interactivity == 'last':
2879 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2919 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2880 elif interactivity == 'all':
2920 elif interactivity == 'all':
2881 to_run_exec, to_run_interactive = [], nodelist
2921 to_run_exec, to_run_interactive = [], nodelist
2882 else:
2922 else:
2883 raise ValueError("Interactivity was %r" % interactivity)
2923 raise ValueError("Interactivity was %r" % interactivity)
2884
2924
2885 exec_count = self.execution_count
2925 exec_count = self.execution_count
2886
2926
2887 try:
2927 try:
2888 for i, node in enumerate(to_run_exec):
2928 for i, node in enumerate(to_run_exec):
2889 mod = ast.Module([node])
2929 mod = ast.Module([node])
2890 code = compiler(mod, cell_name, "exec")
2930 code = compiler(mod, cell_name, "exec")
2891 if self.run_code(code):
2931 if self.run_code(code):
2892 return True
2932 return True
2893
2933
2894 for i, node in enumerate(to_run_interactive):
2934 for i, node in enumerate(to_run_interactive):
2895 mod = ast.Interactive([node])
2935 mod = ast.Interactive([node])
2896 code = compiler(mod, cell_name, "single")
2936 code = compiler(mod, cell_name, "single")
2897 if self.run_code(code):
2937 if self.run_code(code):
2898 return True
2938 return True
2899
2939
2900 # Flush softspace
2940 # Flush softspace
2901 if softspace(sys.stdout, 0):
2941 if softspace(sys.stdout, 0):
2902 print()
2942 print()
2903
2943
2904 except:
2944 except:
2905 # It's possible to have exceptions raised here, typically by
2945 # It's possible to have exceptions raised here, typically by
2906 # compilation of odd code (such as a naked 'return' outside a
2946 # compilation of odd code (such as a naked 'return' outside a
2907 # function) that did parse but isn't valid. Typically the exception
2947 # function) that did parse but isn't valid. Typically the exception
2908 # is a SyntaxError, but it's safest just to catch anything and show
2948 # is a SyntaxError, but it's safest just to catch anything and show
2909 # the user a traceback.
2949 # the user a traceback.
2910
2950
2911 # We do only one try/except outside the loop to minimize the impact
2951 # We do only one try/except outside the loop to minimize the impact
2912 # on runtime, and also because if any node in the node list is
2952 # on runtime, and also because if any node in the node list is
2913 # broken, we should stop execution completely.
2953 # broken, we should stop execution completely.
2914 self.showtraceback()
2954 self.showtraceback()
2915
2955
2916 return False
2956 return False
2917
2957
2918 def run_code(self, code_obj):
2958 def run_code(self, code_obj):
2919 """Execute a code object.
2959 """Execute a code object.
2920
2960
2921 When an exception occurs, self.showtraceback() is called to display a
2961 When an exception occurs, self.showtraceback() is called to display a
2922 traceback.
2962 traceback.
2923
2963
2924 Parameters
2964 Parameters
2925 ----------
2965 ----------
2926 code_obj : code object
2966 code_obj : code object
2927 A compiled code object, to be executed
2967 A compiled code object, to be executed
2928
2968
2929 Returns
2969 Returns
2930 -------
2970 -------
2931 False : successful execution.
2971 False : successful execution.
2932 True : an error occurred.
2972 True : an error occurred.
2933 """
2973 """
2934 # Set our own excepthook in case the user code tries to call it
2974 # Set our own excepthook in case the user code tries to call it
2935 # directly, so that the IPython crash handler doesn't get triggered
2975 # directly, so that the IPython crash handler doesn't get triggered
2936 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2976 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2937
2977
2938 # we save the original sys.excepthook in the instance, in case config
2978 # we save the original sys.excepthook in the instance, in case config
2939 # code (such as magics) needs access to it.
2979 # code (such as magics) needs access to it.
2940 self.sys_excepthook = old_excepthook
2980 self.sys_excepthook = old_excepthook
2941 outflag = 1 # happens in more places, so it's easier as default
2981 outflag = 1 # happens in more places, so it's easier as default
2942 try:
2982 try:
2943 try:
2983 try:
2944 self.hooks.pre_run_code_hook()
2984 self.hooks.pre_run_code_hook()
2945 #rprint('Running code', repr(code_obj)) # dbg
2985 #rprint('Running code', repr(code_obj)) # dbg
2946 exec(code_obj, self.user_global_ns, self.user_ns)
2986 exec(code_obj, self.user_global_ns, self.user_ns)
2947 finally:
2987 finally:
2948 # Reset our crash handler in place
2988 # Reset our crash handler in place
2949 sys.excepthook = old_excepthook
2989 sys.excepthook = old_excepthook
2950 except SystemExit:
2990 except SystemExit:
2951 self.showtraceback(exception_only=True)
2991 self.showtraceback(exception_only=True)
2952 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2992 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2953 except self.custom_exceptions:
2993 except self.custom_exceptions:
2954 etype, value, tb = sys.exc_info()
2994 etype, value, tb = sys.exc_info()
2955 self.CustomTB(etype, value, tb)
2995 self.CustomTB(etype, value, tb)
2956 except:
2996 except:
2957 self.showtraceback()
2997 self.showtraceback()
2958 else:
2998 else:
2959 outflag = 0
2999 outflag = 0
2960 return outflag
3000 return outflag
2961
3001
2962 # For backwards compatibility
3002 # For backwards compatibility
2963 runcode = run_code
3003 runcode = run_code
2964
3004
2965 #-------------------------------------------------------------------------
3005 #-------------------------------------------------------------------------
2966 # Things related to GUI support and pylab
3006 # Things related to GUI support and pylab
2967 #-------------------------------------------------------------------------
3007 #-------------------------------------------------------------------------
2968
3008
2969 def enable_gui(self, gui=None):
3009 def enable_gui(self, gui=None):
2970 raise NotImplementedError('Implement enable_gui in a subclass')
3010 raise NotImplementedError('Implement enable_gui in a subclass')
2971
3011
2972 def enable_matplotlib(self, gui=None):
3012 def enable_matplotlib(self, gui=None):
2973 """Enable interactive matplotlib and inline figure support.
3013 """Enable interactive matplotlib and inline figure support.
2974
3014
2975 This takes the following steps:
3015 This takes the following steps:
2976
3016
2977 1. select the appropriate eventloop and matplotlib backend
3017 1. select the appropriate eventloop and matplotlib backend
2978 2. set up matplotlib for interactive use with that backend
3018 2. set up matplotlib for interactive use with that backend
2979 3. configure formatters for inline figure display
3019 3. configure formatters for inline figure display
2980 4. enable the selected gui eventloop
3020 4. enable the selected gui eventloop
2981
3021
2982 Parameters
3022 Parameters
2983 ----------
3023 ----------
2984 gui : optional, string
3024 gui : optional, string
2985 If given, dictates the choice of matplotlib GUI backend to use
3025 If given, dictates the choice of matplotlib GUI backend to use
2986 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3026 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2987 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3027 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2988 matplotlib (as dictated by the matplotlib build-time options plus the
3028 matplotlib (as dictated by the matplotlib build-time options plus the
2989 user's matplotlibrc configuration file). Note that not all backends
3029 user's matplotlibrc configuration file). Note that not all backends
2990 make sense in all contexts, for example a terminal ipython can't
3030 make sense in all contexts, for example a terminal ipython can't
2991 display figures inline.
3031 display figures inline.
2992 """
3032 """
2993 from IPython.core import pylabtools as pt
3033 from IPython.core import pylabtools as pt
2994 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3034 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
2995
3035
2996 if gui != 'inline':
3036 if gui != 'inline':
2997 # If we have our first gui selection, store it
3037 # If we have our first gui selection, store it
2998 if self.pylab_gui_select is None:
3038 if self.pylab_gui_select is None:
2999 self.pylab_gui_select = gui
3039 self.pylab_gui_select = gui
3000 # Otherwise if they are different
3040 # Otherwise if they are different
3001 elif gui != self.pylab_gui_select:
3041 elif gui != self.pylab_gui_select:
3002 print ('Warning: Cannot change to a different GUI toolkit: %s.'
3042 print ('Warning: Cannot change to a different GUI toolkit: %s.'
3003 ' Using %s instead.' % (gui, self.pylab_gui_select))
3043 ' Using %s instead.' % (gui, self.pylab_gui_select))
3004 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3044 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3005
3045
3006 pt.activate_matplotlib(backend)
3046 pt.activate_matplotlib(backend)
3007 pt.configure_inline_support(self, backend)
3047 pt.configure_inline_support(self, backend)
3008
3048
3009 # Now we must activate the gui pylab wants to use, and fix %run to take
3049 # Now we must activate the gui pylab wants to use, and fix %run to take
3010 # plot updates into account
3050 # plot updates into account
3011 self.enable_gui(gui)
3051 self.enable_gui(gui)
3012 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3052 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3013 pt.mpl_runner(self.safe_execfile)
3053 pt.mpl_runner(self.safe_execfile)
3014
3054
3015 return gui, backend
3055 return gui, backend
3016
3056
3017 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3057 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3018 """Activate pylab support at runtime.
3058 """Activate pylab support at runtime.
3019
3059
3020 This turns on support for matplotlib, preloads into the interactive
3060 This turns on support for matplotlib, preloads into the interactive
3021 namespace all of numpy and pylab, and configures IPython to correctly
3061 namespace all of numpy and pylab, and configures IPython to correctly
3022 interact with the GUI event loop. The GUI backend to be used can be
3062 interact with the GUI event loop. The GUI backend to be used can be
3023 optionally selected with the optional ``gui`` argument.
3063 optionally selected with the optional ``gui`` argument.
3024
3064
3025 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3065 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3026
3066
3027 Parameters
3067 Parameters
3028 ----------
3068 ----------
3029 gui : optional, string
3069 gui : optional, string
3030 If given, dictates the choice of matplotlib GUI backend to use
3070 If given, dictates the choice of matplotlib GUI backend to use
3031 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3071 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3032 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3072 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3033 matplotlib (as dictated by the matplotlib build-time options plus the
3073 matplotlib (as dictated by the matplotlib build-time options plus the
3034 user's matplotlibrc configuration file). Note that not all backends
3074 user's matplotlibrc configuration file). Note that not all backends
3035 make sense in all contexts, for example a terminal ipython can't
3075 make sense in all contexts, for example a terminal ipython can't
3036 display figures inline.
3076 display figures inline.
3037 import_all : optional, bool, default: True
3077 import_all : optional, bool, default: True
3038 Whether to do `from numpy import *` and `from pylab import *`
3078 Whether to do `from numpy import *` and `from pylab import *`
3039 in addition to module imports.
3079 in addition to module imports.
3040 welcome_message : deprecated
3080 welcome_message : deprecated
3041 This argument is ignored, no welcome message will be displayed.
3081 This argument is ignored, no welcome message will be displayed.
3042 """
3082 """
3043 from IPython.core.pylabtools import import_pylab
3083 from IPython.core.pylabtools import import_pylab
3044
3084
3045 gui, backend = self.enable_matplotlib(gui)
3085 gui, backend = self.enable_matplotlib(gui)
3046
3086
3047 # We want to prevent the loading of pylab to pollute the user's
3087 # We want to prevent the loading of pylab to pollute the user's
3048 # namespace as shown by the %who* magics, so we execute the activation
3088 # namespace as shown by the %who* magics, so we execute the activation
3049 # code in an empty namespace, and we update *both* user_ns and
3089 # code in an empty namespace, and we update *both* user_ns and
3050 # user_ns_hidden with this information.
3090 # user_ns_hidden with this information.
3051 ns = {}
3091 ns = {}
3052 import_pylab(ns, import_all)
3092 import_pylab(ns, import_all)
3053 # warn about clobbered names
3093 # warn about clobbered names
3054 ignored = set(["__builtins__"])
3094 ignored = set(["__builtins__"])
3055 both = set(ns).intersection(self.user_ns).difference(ignored)
3095 both = set(ns).intersection(self.user_ns).difference(ignored)
3056 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3096 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3057 self.user_ns.update(ns)
3097 self.user_ns.update(ns)
3058 self.user_ns_hidden.update(ns)
3098 self.user_ns_hidden.update(ns)
3059 return gui, backend, clobbered
3099 return gui, backend, clobbered
3060
3100
3061 #-------------------------------------------------------------------------
3101 #-------------------------------------------------------------------------
3062 # Utilities
3102 # Utilities
3063 #-------------------------------------------------------------------------
3103 #-------------------------------------------------------------------------
3064
3104
3065 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3105 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3066 """Expand python variables in a string.
3106 """Expand python variables in a string.
3067
3107
3068 The depth argument indicates how many frames above the caller should
3108 The depth argument indicates how many frames above the caller should
3069 be walked to look for the local namespace where to expand variables.
3109 be walked to look for the local namespace where to expand variables.
3070
3110
3071 The global namespace for expansion is always the user's interactive
3111 The global namespace for expansion is always the user's interactive
3072 namespace.
3112 namespace.
3073 """
3113 """
3074 ns = self.user_ns.copy()
3114 ns = self.user_ns.copy()
3075 ns.update(sys._getframe(depth+1).f_locals)
3115 try:
3116 frame = sys._getframe(depth+1)
3117 except ValueError:
3118 # This is thrown if there aren't that many frames on the stack,
3119 # e.g. if a script called run_line_magic() directly.
3120 pass
3121 else:
3122 ns.update(frame.f_locals)
3123
3076 try:
3124 try:
3077 # We have to use .vformat() here, because 'self' is a valid and common
3125 # We have to use .vformat() here, because 'self' is a valid and common
3078 # name, and expanding **ns for .format() would make it collide with
3126 # name, and expanding **ns for .format() would make it collide with
3079 # the 'self' argument of the method.
3127 # the 'self' argument of the method.
3080 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3128 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3081 except Exception:
3129 except Exception:
3082 # if formatter couldn't format, just let it go untransformed
3130 # if formatter couldn't format, just let it go untransformed
3083 pass
3131 pass
3084 return cmd
3132 return cmd
3085
3133
3086 def mktempfile(self, data=None, prefix='ipython_edit_'):
3134 def mktempfile(self, data=None, prefix='ipython_edit_'):
3087 """Make a new tempfile and return its filename.
3135 """Make a new tempfile and return its filename.
3088
3136
3089 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3137 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3090 but it registers the created filename internally so ipython cleans it up
3138 but it registers the created filename internally so ipython cleans it up
3091 at exit time.
3139 at exit time.
3092
3140
3093 Optional inputs:
3141 Optional inputs:
3094
3142
3095 - data(None): if data is given, it gets written out to the temp file
3143 - data(None): if data is given, it gets written out to the temp file
3096 immediately, and the file is closed again."""
3144 immediately, and the file is closed again."""
3097
3145
3098 dirname = tempfile.mkdtemp(prefix=prefix)
3146 dirname = tempfile.mkdtemp(prefix=prefix)
3099 self.tempdirs.append(dirname)
3147 self.tempdirs.append(dirname)
3100
3148
3101 handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
3149 handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
3102 os.close(handle) # On Windows, there can only be one open handle on a file
3150 os.close(handle) # On Windows, there can only be one open handle on a file
3103 self.tempfiles.append(filename)
3151 self.tempfiles.append(filename)
3104
3152
3105 if data:
3153 if data:
3106 tmp_file = open(filename,'w')
3154 tmp_file = open(filename,'w')
3107 tmp_file.write(data)
3155 tmp_file.write(data)
3108 tmp_file.close()
3156 tmp_file.close()
3109 return filename
3157 return filename
3110
3158
3111 # TODO: This should be removed when Term is refactored.
3159 # TODO: This should be removed when Term is refactored.
3112 def write(self,data):
3160 def write(self,data):
3113 """Write a string to the default output"""
3161 """Write a string to the default output"""
3114 io.stdout.write(data)
3162 io.stdout.write(data)
3115
3163
3116 # TODO: This should be removed when Term is refactored.
3164 # TODO: This should be removed when Term is refactored.
3117 def write_err(self,data):
3165 def write_err(self,data):
3118 """Write a string to the default error output"""
3166 """Write a string to the default error output"""
3119 io.stderr.write(data)
3167 io.stderr.write(data)
3120
3168
3121 def ask_yes_no(self, prompt, default=None):
3169 def ask_yes_no(self, prompt, default=None):
3122 if self.quiet:
3170 if self.quiet:
3123 return True
3171 return True
3124 return ask_yes_no(prompt,default)
3172 return ask_yes_no(prompt,default)
3125
3173
3126 def show_usage(self):
3174 def show_usage(self):
3127 """Show a usage message"""
3175 """Show a usage message"""
3128 page.page(IPython.core.usage.interactive_usage)
3176 page.page(IPython.core.usage.interactive_usage)
3129
3177
3130 def extract_input_lines(self, range_str, raw=False):
3178 def extract_input_lines(self, range_str, raw=False):
3131 """Return as a string a set of input history slices.
3179 """Return as a string a set of input history slices.
3132
3180
3133 Parameters
3181 Parameters
3134 ----------
3182 ----------
3135 range_str : string
3183 range_str : string
3136 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3184 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3137 since this function is for use by magic functions which get their
3185 since this function is for use by magic functions which get their
3138 arguments as strings. The number before the / is the session
3186 arguments as strings. The number before the / is the session
3139 number: ~n goes n back from the current session.
3187 number: ~n goes n back from the current session.
3140
3188
3141 raw : bool, optional
3189 raw : bool, optional
3142 By default, the processed input is used. If this is true, the raw
3190 By default, the processed input is used. If this is true, the raw
3143 input history is used instead.
3191 input history is used instead.
3144
3192
3145 Notes
3193 Notes
3146 -----
3194 -----
3147
3195
3148 Slices can be described with two notations:
3196 Slices can be described with two notations:
3149
3197
3150 * ``N:M`` -> standard python form, means including items N...(M-1).
3198 * ``N:M`` -> standard python form, means including items N...(M-1).
3151 * ``N-M`` -> include items N..M (closed endpoint).
3199 * ``N-M`` -> include items N..M (closed endpoint).
3152 """
3200 """
3153 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3201 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3154 return "\n".join(x for _, _, x in lines)
3202 return "\n".join(x for _, _, x in lines)
3155
3203
3156 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3204 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3157 """Get a code string from history, file, url, or a string or macro.
3205 """Get a code string from history, file, url, or a string or macro.
3158
3206
3159 This is mainly used by magic functions.
3207 This is mainly used by magic functions.
3160
3208
3161 Parameters
3209 Parameters
3162 ----------
3210 ----------
3163
3211
3164 target : str
3212 target : str
3165
3213
3166 A string specifying code to retrieve. This will be tried respectively
3214 A string specifying code to retrieve. This will be tried respectively
3167 as: ranges of input history (see %history for syntax), url,
3215 as: ranges of input history (see %history for syntax), url,
3168 correspnding .py file, filename, or an expression evaluating to a
3216 correspnding .py file, filename, or an expression evaluating to a
3169 string or Macro in the user namespace.
3217 string or Macro in the user namespace.
3170
3218
3171 raw : bool
3219 raw : bool
3172 If true (default), retrieve raw history. Has no effect on the other
3220 If true (default), retrieve raw history. Has no effect on the other
3173 retrieval mechanisms.
3221 retrieval mechanisms.
3174
3222
3175 py_only : bool (default False)
3223 py_only : bool (default False)
3176 Only try to fetch python code, do not try alternative methods to decode file
3224 Only try to fetch python code, do not try alternative methods to decode file
3177 if unicode fails.
3225 if unicode fails.
3178
3226
3179 Returns
3227 Returns
3180 -------
3228 -------
3181 A string of code.
3229 A string of code.
3182
3230
3183 ValueError is raised if nothing is found, and TypeError if it evaluates
3231 ValueError is raised if nothing is found, and TypeError if it evaluates
3184 to an object of another type. In each case, .args[0] is a printable
3232 to an object of another type. In each case, .args[0] is a printable
3185 message.
3233 message.
3186 """
3234 """
3187 code = self.extract_input_lines(target, raw=raw) # Grab history
3235 code = self.extract_input_lines(target, raw=raw) # Grab history
3188 if code:
3236 if code:
3189 return code
3237 return code
3190 utarget = unquote_filename(target)
3238 utarget = unquote_filename(target)
3191 try:
3239 try:
3192 if utarget.startswith(('http://', 'https://')):
3240 if utarget.startswith(('http://', 'https://')):
3193 return openpy.read_py_url(utarget, skip_encoding_cookie=skip_encoding_cookie)
3241 return openpy.read_py_url(utarget, skip_encoding_cookie=skip_encoding_cookie)
3194 except UnicodeDecodeError:
3242 except UnicodeDecodeError:
3195 if not py_only :
3243 if not py_only :
3196 # Deferred import
3244 # Deferred import
3197 try:
3245 try:
3198 from urllib.request import urlopen # Py3
3246 from urllib.request import urlopen # Py3
3199 except ImportError:
3247 except ImportError:
3200 from urllib import urlopen
3248 from urllib import urlopen
3201 response = urlopen(target)
3249 response = urlopen(target)
3202 return response.read().decode('latin1')
3250 return response.read().decode('latin1')
3203 raise ValueError(("'%s' seem to be unreadable.") % utarget)
3251 raise ValueError(("'%s' seem to be unreadable.") % utarget)
3204
3252
3205 potential_target = [target]
3253 potential_target = [target]
3206 try :
3254 try :
3207 potential_target.insert(0,get_py_filename(target))
3255 potential_target.insert(0,get_py_filename(target))
3208 except IOError:
3256 except IOError:
3209 pass
3257 pass
3210
3258
3211 for tgt in potential_target :
3259 for tgt in potential_target :
3212 if os.path.isfile(tgt): # Read file
3260 if os.path.isfile(tgt): # Read file
3213 try :
3261 try :
3214 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3262 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3215 except UnicodeDecodeError :
3263 except UnicodeDecodeError :
3216 if not py_only :
3264 if not py_only :
3217 with io_open(tgt,'r', encoding='latin1') as f :
3265 with io_open(tgt,'r', encoding='latin1') as f :
3218 return f.read()
3266 return f.read()
3219 raise ValueError(("'%s' seem to be unreadable.") % target)
3267 raise ValueError(("'%s' seem to be unreadable.") % target)
3220 elif os.path.isdir(os.path.expanduser(tgt)):
3268 elif os.path.isdir(os.path.expanduser(tgt)):
3221 raise ValueError("'%s' is a directory, not a regular file." % target)
3269 raise ValueError("'%s' is a directory, not a regular file." % target)
3222
3270
3223 if search_ns:
3271 if search_ns:
3224 # Inspect namespace to load object source
3272 # Inspect namespace to load object source
3225 object_info = self.object_inspect(target, detail_level=1)
3273 object_info = self.object_inspect(target, detail_level=1)
3226 if object_info['found'] and object_info['source']:
3274 if object_info['found'] and object_info['source']:
3227 return object_info['source']
3275 return object_info['source']
3228
3276
3229 try: # User namespace
3277 try: # User namespace
3230 codeobj = eval(target, self.user_ns)
3278 codeobj = eval(target, self.user_ns)
3231 except Exception:
3279 except Exception:
3232 raise ValueError(("'%s' was not found in history, as a file, url, "
3280 raise ValueError(("'%s' was not found in history, as a file, url, "
3233 "nor in the user namespace.") % target)
3281 "nor in the user namespace.") % target)
3234
3282
3235 if isinstance(codeobj, string_types):
3283 if isinstance(codeobj, string_types):
3236 return codeobj
3284 return codeobj
3237 elif isinstance(codeobj, Macro):
3285 elif isinstance(codeobj, Macro):
3238 return codeobj.value
3286 return codeobj.value
3239
3287
3240 raise TypeError("%s is neither a string nor a macro." % target,
3288 raise TypeError("%s is neither a string nor a macro." % target,
3241 codeobj)
3289 codeobj)
3242
3290
3243 #-------------------------------------------------------------------------
3291 #-------------------------------------------------------------------------
3244 # Things related to IPython exiting
3292 # Things related to IPython exiting
3245 #-------------------------------------------------------------------------
3293 #-------------------------------------------------------------------------
3246 def atexit_operations(self):
3294 def atexit_operations(self):
3247 """This will be executed at the time of exit.
3295 """This will be executed at the time of exit.
3248
3296
3249 Cleanup operations and saving of persistent data that is done
3297 Cleanup operations and saving of persistent data that is done
3250 unconditionally by IPython should be performed here.
3298 unconditionally by IPython should be performed here.
3251
3299
3252 For things that may depend on startup flags or platform specifics (such
3300 For things that may depend on startup flags or platform specifics (such
3253 as having readline or not), register a separate atexit function in the
3301 as having readline or not), register a separate atexit function in the
3254 code that has the appropriate information, rather than trying to
3302 code that has the appropriate information, rather than trying to
3255 clutter
3303 clutter
3256 """
3304 """
3257 # Close the history session (this stores the end time and line count)
3305 # Close the history session (this stores the end time and line count)
3258 # this must be *before* the tempfile cleanup, in case of temporary
3306 # this must be *before* the tempfile cleanup, in case of temporary
3259 # history db
3307 # history db
3260 self.history_manager.end_session()
3308 self.history_manager.end_session()
3261
3309
3262 # Cleanup all tempfiles and folders left around
3310 # Cleanup all tempfiles and folders left around
3263 for tfile in self.tempfiles:
3311 for tfile in self.tempfiles:
3264 try:
3312 try:
3265 os.unlink(tfile)
3313 os.unlink(tfile)
3266 except OSError:
3314 except OSError:
3267 pass
3315 pass
3268
3316
3269 for tdir in self.tempdirs:
3317 for tdir in self.tempdirs:
3270 try:
3318 try:
3271 os.rmdir(tdir)
3319 os.rmdir(tdir)
3272 except OSError:
3320 except OSError:
3273 pass
3321 pass
3274
3322
3275 # Clear all user namespaces to release all references cleanly.
3323 # Clear all user namespaces to release all references cleanly.
3276 self.reset(new_session=False)
3324 self.reset(new_session=False)
3277
3325
3278 # Run user hooks
3326 # Run user hooks
3279 self.hooks.shutdown_hook()
3327 self.hooks.shutdown_hook()
3280
3328
3281 def cleanup(self):
3329 def cleanup(self):
3282 self.restore_sys_module_state()
3330 self.restore_sys_module_state()
3283
3331
3284
3332
3285 class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)):
3333 class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)):
3286 """An abstract base class for InteractiveShell."""
3334 """An abstract base class for InteractiveShell."""
3287
3335
3288 InteractiveShellABC.register(InteractiveShell)
3336 InteractiveShellABC.register(InteractiveShell)
@@ -1,656 +1,611 b''
1 """Implementation of basic magic functions.
1 """Implementation of basic magic functions."""
2 """
2
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
5 #
6 # Distributed under the terms of the Modified BSD License.
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14 from __future__ import print_function
3 from __future__ import print_function
15
4
16 # Stdlib
17 import io
5 import io
18 import json
6 import json
19 import sys
7 import sys
20 from pprint import pformat
8 from pprint import pformat
21
9
22 # Our own packages
23 from IPython.core import magic_arguments, page
10 from IPython.core import magic_arguments, page
24 from IPython.core.error import UsageError
11 from IPython.core.error import UsageError
25 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
26 from IPython.utils.text import format_screen, dedent, indent
13 from IPython.utils.text import format_screen, dedent, indent
27 from IPython.testing.skipdoctest import skip_doctest
14 from IPython.testing.skipdoctest import skip_doctest
28 from IPython.utils.ipstruct import Struct
15 from IPython.utils.ipstruct import Struct
29 from IPython.utils.path import unquote_filename
16 from IPython.utils.path import unquote_filename
30 from IPython.utils.py3compat import unicode_type
17 from IPython.utils.py3compat import unicode_type
31 from IPython.utils.warn import warn, error
18 from IPython.utils.warn import warn, error
32
19
33 #-----------------------------------------------------------------------------
34 # Magics class implementation
35 #-----------------------------------------------------------------------------
36
20
37 class MagicsDisplay(object):
21 class MagicsDisplay(object):
38 def __init__(self, magics_manager):
22 def __init__(self, magics_manager):
39 self.magics_manager = magics_manager
23 self.magics_manager = magics_manager
40
24
41 def _lsmagic(self):
25 def _lsmagic(self):
42 """The main implementation of the %lsmagic"""
26 """The main implementation of the %lsmagic"""
43 mesc = magic_escapes['line']
27 mesc = magic_escapes['line']
44 cesc = magic_escapes['cell']
28 cesc = magic_escapes['cell']
45 mman = self.magics_manager
29 mman = self.magics_manager
46 magics = mman.lsmagic()
30 magics = mman.lsmagic()
47 out = ['Available line magics:',
31 out = ['Available line magics:',
48 mesc + (' '+mesc).join(sorted(magics['line'])),
32 mesc + (' '+mesc).join(sorted(magics['line'])),
49 '',
33 '',
50 'Available cell magics:',
34 'Available cell magics:',
51 cesc + (' '+cesc).join(sorted(magics['cell'])),
35 cesc + (' '+cesc).join(sorted(magics['cell'])),
52 '',
36 '',
53 mman.auto_status()]
37 mman.auto_status()]
54 return '\n'.join(out)
38 return '\n'.join(out)
55
39
56 def _repr_pretty_(self, p, cycle):
40 def _repr_pretty_(self, p, cycle):
57 p.text(self._lsmagic())
41 p.text(self._lsmagic())
58
42
59 def __str__(self):
43 def __str__(self):
60 return self._lsmagic()
44 return self._lsmagic()
61
45
62 def _jsonable(self):
46 def _jsonable(self):
63 """turn magics dict into jsonable dict of the same structure
47 """turn magics dict into jsonable dict of the same structure
64
48
65 replaces object instances with their class names as strings
49 replaces object instances with their class names as strings
66 """
50 """
67 magic_dict = {}
51 magic_dict = {}
68 mman = self.magics_manager
52 mman = self.magics_manager
69 magics = mman.lsmagic()
53 magics = mman.lsmagic()
70 for key, subdict in magics.items():
54 for key, subdict in magics.items():
71 d = {}
55 d = {}
72 magic_dict[key] = d
56 magic_dict[key] = d
73 for name, obj in subdict.items():
57 for name, obj in subdict.items():
74 try:
58 try:
75 classname = obj.__self__.__class__.__name__
59 classname = obj.__self__.__class__.__name__
76 except AttributeError:
60 except AttributeError:
77 classname = 'Other'
61 classname = 'Other'
78
62
79 d[name] = classname
63 d[name] = classname
80 return magic_dict
64 return magic_dict
81
65
82 def _repr_json_(self):
66 def _repr_json_(self):
83 return json.dumps(self._jsonable())
67 return json.dumps(self._jsonable())
84
68
85
69
86 @magics_class
70 @magics_class
87 class BasicMagics(Magics):
71 class BasicMagics(Magics):
88 """Magics that provide central IPython functionality.
72 """Magics that provide central IPython functionality.
89
73
90 These are various magics that don't fit into specific categories but that
74 These are various magics that don't fit into specific categories but that
91 are all part of the base 'IPython experience'."""
75 are all part of the base 'IPython experience'."""
92
76
93 @magic_arguments.magic_arguments()
77 @magic_arguments.magic_arguments()
94 @magic_arguments.argument(
78 @magic_arguments.argument(
95 '-l', '--line', action='store_true',
79 '-l', '--line', action='store_true',
96 help="""Create a line magic alias."""
80 help="""Create a line magic alias."""
97 )
81 )
98 @magic_arguments.argument(
82 @magic_arguments.argument(
99 '-c', '--cell', action='store_true',
83 '-c', '--cell', action='store_true',
100 help="""Create a cell magic alias."""
84 help="""Create a cell magic alias."""
101 )
85 )
102 @magic_arguments.argument(
86 @magic_arguments.argument(
103 'name',
87 'name',
104 help="""Name of the magic to be created."""
88 help="""Name of the magic to be created."""
105 )
89 )
106 @magic_arguments.argument(
90 @magic_arguments.argument(
107 'target',
91 'target',
108 help="""Name of the existing line or cell magic."""
92 help="""Name of the existing line or cell magic."""
109 )
93 )
110 @line_magic
94 @line_magic
111 def alias_magic(self, line=''):
95 def alias_magic(self, line=''):
112 """Create an alias for an existing line or cell magic.
96 """Create an alias for an existing line or cell magic.
113
97
114 Examples
98 Examples
115 --------
99 --------
116 ::
100 ::
117
101
118 In [1]: %alias_magic t timeit
102 In [1]: %alias_magic t timeit
119 Created `%t` as an alias for `%timeit`.
103 Created `%t` as an alias for `%timeit`.
120 Created `%%t` as an alias for `%%timeit`.
104 Created `%%t` as an alias for `%%timeit`.
121
105
122 In [2]: %t -n1 pass
106 In [2]: %t -n1 pass
123 1 loops, best of 3: 954 ns per loop
107 1 loops, best of 3: 954 ns per loop
124
108
125 In [3]: %%t -n1
109 In [3]: %%t -n1
126 ...: pass
110 ...: pass
127 ...:
111 ...:
128 1 loops, best of 3: 954 ns per loop
112 1 loops, best of 3: 954 ns per loop
129
113
130 In [4]: %alias_magic --cell whereami pwd
114 In [4]: %alias_magic --cell whereami pwd
131 UsageError: Cell magic function `%%pwd` not found.
115 UsageError: Cell magic function `%%pwd` not found.
132 In [5]: %alias_magic --line whereami pwd
116 In [5]: %alias_magic --line whereami pwd
133 Created `%whereami` as an alias for `%pwd`.
117 Created `%whereami` as an alias for `%pwd`.
134
118
135 In [6]: %whereami
119 In [6]: %whereami
136 Out[6]: u'/home/testuser'
120 Out[6]: u'/home/testuser'
137 """
121 """
138 args = magic_arguments.parse_argstring(self.alias_magic, line)
122 args = magic_arguments.parse_argstring(self.alias_magic, line)
139 shell = self.shell
123 shell = self.shell
140 mman = self.shell.magics_manager
124 mman = self.shell.magics_manager
141 escs = ''.join(magic_escapes.values())
125 escs = ''.join(magic_escapes.values())
142
126
143 target = args.target.lstrip(escs)
127 target = args.target.lstrip(escs)
144 name = args.name.lstrip(escs)
128 name = args.name.lstrip(escs)
145
129
146 # Find the requested magics.
130 # Find the requested magics.
147 m_line = shell.find_magic(target, 'line')
131 m_line = shell.find_magic(target, 'line')
148 m_cell = shell.find_magic(target, 'cell')
132 m_cell = shell.find_magic(target, 'cell')
149 if args.line and m_line is None:
133 if args.line and m_line is None:
150 raise UsageError('Line magic function `%s%s` not found.' %
134 raise UsageError('Line magic function `%s%s` not found.' %
151 (magic_escapes['line'], target))
135 (magic_escapes['line'], target))
152 if args.cell and m_cell is None:
136 if args.cell and m_cell is None:
153 raise UsageError('Cell magic function `%s%s` not found.' %
137 raise UsageError('Cell magic function `%s%s` not found.' %
154 (magic_escapes['cell'], target))
138 (magic_escapes['cell'], target))
155
139
156 # If --line and --cell are not specified, default to the ones
140 # If --line and --cell are not specified, default to the ones
157 # that are available.
141 # that are available.
158 if not args.line and not args.cell:
142 if not args.line and not args.cell:
159 if not m_line and not m_cell:
143 if not m_line and not m_cell:
160 raise UsageError(
144 raise UsageError(
161 'No line or cell magic with name `%s` found.' % target
145 'No line or cell magic with name `%s` found.' % target
162 )
146 )
163 args.line = bool(m_line)
147 args.line = bool(m_line)
164 args.cell = bool(m_cell)
148 args.cell = bool(m_cell)
165
149
166 if args.line:
150 if args.line:
167 mman.register_alias(name, target, 'line')
151 mman.register_alias(name, target, 'line')
168 print('Created `%s%s` as an alias for `%s%s`.' % (
152 print('Created `%s%s` as an alias for `%s%s`.' % (
169 magic_escapes['line'], name,
153 magic_escapes['line'], name,
170 magic_escapes['line'], target))
154 magic_escapes['line'], target))
171
155
172 if args.cell:
156 if args.cell:
173 mman.register_alias(name, target, 'cell')
157 mman.register_alias(name, target, 'cell')
174 print('Created `%s%s` as an alias for `%s%s`.' % (
158 print('Created `%s%s` as an alias for `%s%s`.' % (
175 magic_escapes['cell'], name,
159 magic_escapes['cell'], name,
176 magic_escapes['cell'], target))
160 magic_escapes['cell'], target))
177
161
178 @line_magic
162 @line_magic
179 def lsmagic(self, parameter_s=''):
163 def lsmagic(self, parameter_s=''):
180 """List currently available magic functions."""
164 """List currently available magic functions."""
181 return MagicsDisplay(self.shell.magics_manager)
165 return MagicsDisplay(self.shell.magics_manager)
182
166
183 def _magic_docs(self, brief=False, rest=False):
167 def _magic_docs(self, brief=False, rest=False):
184 """Return docstrings from magic functions."""
168 """Return docstrings from magic functions."""
185 mman = self.shell.magics_manager
169 mman = self.shell.magics_manager
186 docs = mman.lsmagic_docs(brief, missing='No documentation')
170 docs = mman.lsmagic_docs(brief, missing='No documentation')
187
171
188 if rest:
172 if rest:
189 format_string = '**%s%s**::\n\n%s\n\n'
173 format_string = '**%s%s**::\n\n%s\n\n'
190 else:
174 else:
191 format_string = '%s%s:\n%s\n'
175 format_string = '%s%s:\n%s\n'
192
176
193 return ''.join(
177 return ''.join(
194 [format_string % (magic_escapes['line'], fname,
178 [format_string % (magic_escapes['line'], fname,
195 indent(dedent(fndoc)))
179 indent(dedent(fndoc)))
196 for fname, fndoc in sorted(docs['line'].items())]
180 for fname, fndoc in sorted(docs['line'].items())]
197 +
181 +
198 [format_string % (magic_escapes['cell'], fname,
182 [format_string % (magic_escapes['cell'], fname,
199 indent(dedent(fndoc)))
183 indent(dedent(fndoc)))
200 for fname, fndoc in sorted(docs['cell'].items())]
184 for fname, fndoc in sorted(docs['cell'].items())]
201 )
185 )
202
186
203 @line_magic
187 @line_magic
204 def magic(self, parameter_s=''):
188 def magic(self, parameter_s=''):
205 """Print information about the magic function system.
189 """Print information about the magic function system.
206
190
207 Supported formats: -latex, -brief, -rest
191 Supported formats: -latex, -brief, -rest
208 """
192 """
209
193
210 mode = ''
194 mode = ''
211 try:
195 try:
212 mode = parameter_s.split()[0][1:]
196 mode = parameter_s.split()[0][1:]
213 if mode == 'rest':
197 if mode == 'rest':
214 rest_docs = []
198 rest_docs = []
215 except IndexError:
199 except IndexError:
216 pass
200 pass
217
201
218 brief = (mode == 'brief')
202 brief = (mode == 'brief')
219 rest = (mode == 'rest')
203 rest = (mode == 'rest')
220 magic_docs = self._magic_docs(brief, rest)
204 magic_docs = self._magic_docs(brief, rest)
221
205
222 if mode == 'latex':
206 if mode == 'latex':
223 print(self.format_latex(magic_docs))
207 print(self.format_latex(magic_docs))
224 return
208 return
225 else:
209 else:
226 magic_docs = format_screen(magic_docs)
210 magic_docs = format_screen(magic_docs)
227
211
228 out = ["""
212 out = ["""
229 IPython's 'magic' functions
213 IPython's 'magic' functions
230 ===========================
214 ===========================
231
215
232 The magic function system provides a series of functions which allow you to
216 The magic function system provides a series of functions which allow you to
233 control the behavior of IPython itself, plus a lot of system-type
217 control the behavior of IPython itself, plus a lot of system-type
234 features. There are two kinds of magics, line-oriented and cell-oriented.
218 features. There are two kinds of magics, line-oriented and cell-oriented.
235
219
236 Line magics are prefixed with the % character and work much like OS
220 Line magics are prefixed with the % character and work much like OS
237 command-line calls: they get as an argument the rest of the line, where
221 command-line calls: they get as an argument the rest of the line, where
238 arguments are passed without parentheses or quotes. For example, this will
222 arguments are passed without parentheses or quotes. For example, this will
239 time the given statement::
223 time the given statement::
240
224
241 %timeit range(1000)
225 %timeit range(1000)
242
226
243 Cell magics are prefixed with a double %%, and they are functions that get as
227 Cell magics are prefixed with a double %%, and they are functions that get as
244 an argument not only the rest of the line, but also the lines below it in a
228 an argument not only the rest of the line, but also the lines below it in a
245 separate argument. These magics are called with two arguments: the rest of the
229 separate argument. These magics are called with two arguments: the rest of the
246 call line and the body of the cell, consisting of the lines below the first.
230 call line and the body of the cell, consisting of the lines below the first.
247 For example::
231 For example::
248
232
249 %%timeit x = numpy.random.randn((100, 100))
233 %%timeit x = numpy.random.randn((100, 100))
250 numpy.linalg.svd(x)
234 numpy.linalg.svd(x)
251
235
252 will time the execution of the numpy svd routine, running the assignment of x
236 will time the execution of the numpy svd routine, running the assignment of x
253 as part of the setup phase, which is not timed.
237 as part of the setup phase, which is not timed.
254
238
255 In a line-oriented client (the terminal or Qt console IPython), starting a new
239 In a line-oriented client (the terminal or Qt console IPython), starting a new
256 input with %% will automatically enter cell mode, and IPython will continue
240 input with %% will automatically enter cell mode, and IPython will continue
257 reading input until a blank line is given. In the notebook, simply type the
241 reading input until a blank line is given. In the notebook, simply type the
258 whole cell as one entity, but keep in mind that the %% escape can only be at
242 whole cell as one entity, but keep in mind that the %% escape can only be at
259 the very start of the cell.
243 the very start of the cell.
260
244
261 NOTE: If you have 'automagic' enabled (via the command line option or with the
245 NOTE: If you have 'automagic' enabled (via the command line option or with the
262 %automagic function), you don't need to type in the % explicitly for line
246 %automagic function), you don't need to type in the % explicitly for line
263 magics; cell magics always require an explicit '%%' escape. By default,
247 magics; cell magics always require an explicit '%%' escape. By default,
264 IPython ships with automagic on, so you should only rarely need the % escape.
248 IPython ships with automagic on, so you should only rarely need the % escape.
265
249
266 Example: typing '%cd mydir' (without the quotes) changes you working directory
250 Example: typing '%cd mydir' (without the quotes) changes you working directory
267 to 'mydir', if it exists.
251 to 'mydir', if it exists.
268
252
269 For a list of the available magic functions, use %lsmagic. For a description
253 For a list of the available magic functions, use %lsmagic. For a description
270 of any of them, type %magic_name?, e.g. '%cd?'.
254 of any of them, type %magic_name?, e.g. '%cd?'.
271
255
272 Currently the magic system has the following functions:""",
256 Currently the magic system has the following functions:""",
273 magic_docs,
257 magic_docs,
274 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
258 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
275 str(self.lsmagic()),
259 str(self.lsmagic()),
276 ]
260 ]
277 page.page('\n'.join(out))
261 page.page('\n'.join(out))
278
262
279
263
280 @line_magic
264 @line_magic
281 def page(self, parameter_s=''):
265 def page(self, parameter_s=''):
282 """Pretty print the object and display it through a pager.
266 """Pretty print the object and display it through a pager.
283
267
284 %page [options] OBJECT
268 %page [options] OBJECT
285
269
286 If no object is given, use _ (last output).
270 If no object is given, use _ (last output).
287
271
288 Options:
272 Options:
289
273
290 -r: page str(object), don't pretty-print it."""
274 -r: page str(object), don't pretty-print it."""
291
275
292 # After a function contributed by Olivier Aubert, slightly modified.
276 # After a function contributed by Olivier Aubert, slightly modified.
293
277
294 # Process options/args
278 # Process options/args
295 opts, args = self.parse_options(parameter_s, 'r')
279 opts, args = self.parse_options(parameter_s, 'r')
296 raw = 'r' in opts
280 raw = 'r' in opts
297
281
298 oname = args and args or '_'
282 oname = args and args or '_'
299 info = self.shell._ofind(oname)
283 info = self.shell._ofind(oname)
300 if info['found']:
284 if info['found']:
301 txt = (raw and str or pformat)( info['obj'] )
285 txt = (raw and str or pformat)( info['obj'] )
302 page.page(txt)
286 page.page(txt)
303 else:
287 else:
304 print('Object `%s` not found' % oname)
288 print('Object `%s` not found' % oname)
305
289
306 @line_magic
290 @line_magic
307 def profile(self, parameter_s=''):
291 def profile(self, parameter_s=''):
308 """Print your currently active IPython profile.
292 """Print your currently active IPython profile.
309
293
310 See Also
294 See Also
311 --------
295 --------
312 prun : run code using the Python profiler
296 prun : run code using the Python profiler
313 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
297 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
314 """
298 """
315 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
299 warn("%profile is now deprecated. Please use get_ipython().profile instead.")
316 from IPython.core.application import BaseIPythonApplication
300 from IPython.core.application import BaseIPythonApplication
317 if BaseIPythonApplication.initialized():
301 if BaseIPythonApplication.initialized():
318 print(BaseIPythonApplication.instance().profile)
302 print(BaseIPythonApplication.instance().profile)
319 else:
303 else:
320 error("profile is an application-level value, but you don't appear to be in an IPython application")
304 error("profile is an application-level value, but you don't appear to be in an IPython application")
321
305
322 @line_magic
306 @line_magic
323 def pprint(self, parameter_s=''):
307 def pprint(self, parameter_s=''):
324 """Toggle pretty printing on/off."""
308 """Toggle pretty printing on/off."""
325 ptformatter = self.shell.display_formatter.formatters['text/plain']
309 ptformatter = self.shell.display_formatter.formatters['text/plain']
326 ptformatter.pprint = bool(1 - ptformatter.pprint)
310 ptformatter.pprint = bool(1 - ptformatter.pprint)
327 print('Pretty printing has been turned',
311 print('Pretty printing has been turned',
328 ['OFF','ON'][ptformatter.pprint])
312 ['OFF','ON'][ptformatter.pprint])
329
313
330 @line_magic
314 @line_magic
331 def colors(self, parameter_s=''):
315 def colors(self, parameter_s=''):
332 """Switch color scheme for prompts, info system and exception handlers.
316 """Switch color scheme for prompts, info system and exception handlers.
333
317
334 Currently implemented schemes: NoColor, Linux, LightBG.
318 Currently implemented schemes: NoColor, Linux, LightBG.
335
319
336 Color scheme names are not case-sensitive.
320 Color scheme names are not case-sensitive.
337
321
338 Examples
322 Examples
339 --------
323 --------
340 To get a plain black and white terminal::
324 To get a plain black and white terminal::
341
325
342 %colors nocolor
326 %colors nocolor
343 """
327 """
344 def color_switch_err(name):
328 def color_switch_err(name):
345 warn('Error changing %s color schemes.\n%s' %
329 warn('Error changing %s color schemes.\n%s' %
346 (name, sys.exc_info()[1]))
330 (name, sys.exc_info()[1]))
347
331
348
332
349 new_scheme = parameter_s.strip()
333 new_scheme = parameter_s.strip()
350 if not new_scheme:
334 if not new_scheme:
351 raise UsageError(
335 raise UsageError(
352 "%colors: you must specify a color scheme. See '%colors?'")
336 "%colors: you must specify a color scheme. See '%colors?'")
353 # local shortcut
337 # local shortcut
354 shell = self.shell
338 shell = self.shell
355
339
356 import IPython.utils.rlineimpl as readline
340 import IPython.utils.rlineimpl as readline
357
341
358 if not shell.colors_force and \
342 if not shell.colors_force and \
359 not readline.have_readline and \
343 not readline.have_readline and \
360 (sys.platform == "win32" or sys.platform == "cli"):
344 (sys.platform == "win32" or sys.platform == "cli"):
361 msg = """\
345 msg = """\
362 Proper color support under MS Windows requires the pyreadline library.
346 Proper color support under MS Windows requires the pyreadline library.
363 You can find it at:
347 You can find it at:
364 http://ipython.org/pyreadline.html
348 http://ipython.org/pyreadline.html
365 Gary's readline needs the ctypes module, from:
366 http://starship.python.net/crew/theller/ctypes
367 (Note that ctypes is already part of Python versions 2.5 and newer).
368
349
369 Defaulting color scheme to 'NoColor'"""
350 Defaulting color scheme to 'NoColor'"""
370 new_scheme = 'NoColor'
351 new_scheme = 'NoColor'
371 warn(msg)
352 warn(msg)
372
353
373 # readline option is 0
354 # readline option is 0
374 if not shell.colors_force and not shell.has_readline:
355 if not shell.colors_force and not shell.has_readline:
375 new_scheme = 'NoColor'
356 new_scheme = 'NoColor'
376
357
377 # Set prompt colors
358 # Set prompt colors
378 try:
359 try:
379 shell.prompt_manager.color_scheme = new_scheme
360 shell.prompt_manager.color_scheme = new_scheme
380 except:
361 except:
381 color_switch_err('prompt')
362 color_switch_err('prompt')
382 else:
363 else:
383 shell.colors = \
364 shell.colors = \
384 shell.prompt_manager.color_scheme_table.active_scheme_name
365 shell.prompt_manager.color_scheme_table.active_scheme_name
385 # Set exception colors
366 # Set exception colors
386 try:
367 try:
387 shell.InteractiveTB.set_colors(scheme = new_scheme)
368 shell.InteractiveTB.set_colors(scheme = new_scheme)
388 shell.SyntaxTB.set_colors(scheme = new_scheme)
369 shell.SyntaxTB.set_colors(scheme = new_scheme)
389 except:
370 except:
390 color_switch_err('exception')
371 color_switch_err('exception')
391
372
392 # Set info (for 'object?') colors
373 # Set info (for 'object?') colors
393 if shell.color_info:
374 if shell.color_info:
394 try:
375 try:
395 shell.inspector.set_active_scheme(new_scheme)
376 shell.inspector.set_active_scheme(new_scheme)
396 except:
377 except:
397 color_switch_err('object inspector')
378 color_switch_err('object inspector')
398 else:
379 else:
399 shell.inspector.set_active_scheme('NoColor')
380 shell.inspector.set_active_scheme('NoColor')
400
381
401 @line_magic
382 @line_magic
402 def xmode(self, parameter_s=''):
383 def xmode(self, parameter_s=''):
403 """Switch modes for the exception handlers.
384 """Switch modes for the exception handlers.
404
385
405 Valid modes: Plain, Context and Verbose.
386 Valid modes: Plain, Context and Verbose.
406
387
407 If called without arguments, acts as a toggle."""
388 If called without arguments, acts as a toggle."""
408
389
409 def xmode_switch_err(name):
390 def xmode_switch_err(name):
410 warn('Error changing %s exception modes.\n%s' %
391 warn('Error changing %s exception modes.\n%s' %
411 (name,sys.exc_info()[1]))
392 (name,sys.exc_info()[1]))
412
393
413 shell = self.shell
394 shell = self.shell
414 new_mode = parameter_s.strip().capitalize()
395 new_mode = parameter_s.strip().capitalize()
415 try:
396 try:
416 shell.InteractiveTB.set_mode(mode=new_mode)
397 shell.InteractiveTB.set_mode(mode=new_mode)
417 print('Exception reporting mode:',shell.InteractiveTB.mode)
398 print('Exception reporting mode:',shell.InteractiveTB.mode)
418 except:
399 except:
419 xmode_switch_err('user')
400 xmode_switch_err('user')
420
401
421 @line_magic
402 @line_magic
422 def quickref(self,arg):
403 def quickref(self,arg):
423 """ Show a quick reference sheet """
404 """ Show a quick reference sheet """
424 from IPython.core.usage import quick_reference
405 from IPython.core.usage import quick_reference
425 qr = quick_reference + self._magic_docs(brief=True)
406 qr = quick_reference + self._magic_docs(brief=True)
426 page.page(qr)
407 page.page(qr)
427
408
428 @line_magic
409 @line_magic
429 def doctest_mode(self, parameter_s=''):
410 def doctest_mode(self, parameter_s=''):
430 """Toggle doctest mode on and off.
411 """Toggle doctest mode on and off.
431
412
432 This mode is intended to make IPython behave as much as possible like a
413 This mode is intended to make IPython behave as much as possible like a
433 plain Python shell, from the perspective of how its prompts, exceptions
414 plain Python shell, from the perspective of how its prompts, exceptions
434 and output look. This makes it easy to copy and paste parts of a
415 and output look. This makes it easy to copy and paste parts of a
435 session into doctests. It does so by:
416 session into doctests. It does so by:
436
417
437 - Changing the prompts to the classic ``>>>`` ones.
418 - Changing the prompts to the classic ``>>>`` ones.
438 - Changing the exception reporting mode to 'Plain'.
419 - Changing the exception reporting mode to 'Plain'.
439 - Disabling pretty-printing of output.
420 - Disabling pretty-printing of output.
440
421
441 Note that IPython also supports the pasting of code snippets that have
422 Note that IPython also supports the pasting of code snippets that have
442 leading '>>>' and '...' prompts in them. This means that you can paste
423 leading '>>>' and '...' prompts in them. This means that you can paste
443 doctests from files or docstrings (even if they have leading
424 doctests from files or docstrings (even if they have leading
444 whitespace), and the code will execute correctly. You can then use
425 whitespace), and the code will execute correctly. You can then use
445 '%history -t' to see the translated history; this will give you the
426 '%history -t' to see the translated history; this will give you the
446 input after removal of all the leading prompts and whitespace, which
427 input after removal of all the leading prompts and whitespace, which
447 can be pasted back into an editor.
428 can be pasted back into an editor.
448
429
449 With these features, you can switch into this mode easily whenever you
430 With these features, you can switch into this mode easily whenever you
450 need to do testing and changes to doctests, without having to leave
431 need to do testing and changes to doctests, without having to leave
451 your existing IPython session.
432 your existing IPython session.
452 """
433 """
453
434
454 # Shorthands
435 # Shorthands
455 shell = self.shell
436 shell = self.shell
456 pm = shell.prompt_manager
437 pm = shell.prompt_manager
457 meta = shell.meta
438 meta = shell.meta
458 disp_formatter = self.shell.display_formatter
439 disp_formatter = self.shell.display_formatter
459 ptformatter = disp_formatter.formatters['text/plain']
440 ptformatter = disp_formatter.formatters['text/plain']
460 # dstore is a data store kept in the instance metadata bag to track any
441 # dstore is a data store kept in the instance metadata bag to track any
461 # changes we make, so we can undo them later.
442 # changes we make, so we can undo them later.
462 dstore = meta.setdefault('doctest_mode',Struct())
443 dstore = meta.setdefault('doctest_mode',Struct())
463 save_dstore = dstore.setdefault
444 save_dstore = dstore.setdefault
464
445
465 # save a few values we'll need to recover later
446 # save a few values we'll need to recover later
466 mode = save_dstore('mode',False)
447 mode = save_dstore('mode',False)
467 save_dstore('rc_pprint',ptformatter.pprint)
448 save_dstore('rc_pprint',ptformatter.pprint)
468 save_dstore('xmode',shell.InteractiveTB.mode)
449 save_dstore('xmode',shell.InteractiveTB.mode)
469 save_dstore('rc_separate_out',shell.separate_out)
450 save_dstore('rc_separate_out',shell.separate_out)
470 save_dstore('rc_separate_out2',shell.separate_out2)
451 save_dstore('rc_separate_out2',shell.separate_out2)
471 save_dstore('rc_prompts_pad_left',pm.justify)
452 save_dstore('rc_prompts_pad_left',pm.justify)
472 save_dstore('rc_separate_in',shell.separate_in)
453 save_dstore('rc_separate_in',shell.separate_in)
473 save_dstore('rc_active_types',disp_formatter.active_types)
454 save_dstore('rc_active_types',disp_formatter.active_types)
474 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
455 save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template))
475
456
476 if mode == False:
457 if mode == False:
477 # turn on
458 # turn on
478 pm.in_template = '>>> '
459 pm.in_template = '>>> '
479 pm.in2_template = '... '
460 pm.in2_template = '... '
480 pm.out_template = ''
461 pm.out_template = ''
481
462
482 # Prompt separators like plain python
463 # Prompt separators like plain python
483 shell.separate_in = ''
464 shell.separate_in = ''
484 shell.separate_out = ''
465 shell.separate_out = ''
485 shell.separate_out2 = ''
466 shell.separate_out2 = ''
486
467
487 pm.justify = False
468 pm.justify = False
488
469
489 ptformatter.pprint = False
470 ptformatter.pprint = False
490 disp_formatter.active_types = ['text/plain']
471 disp_formatter.active_types = ['text/plain']
491
472
492 shell.magic('xmode Plain')
473 shell.magic('xmode Plain')
493 else:
474 else:
494 # turn off
475 # turn off
495 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
476 pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates
496
477
497 shell.separate_in = dstore.rc_separate_in
478 shell.separate_in = dstore.rc_separate_in
498
479
499 shell.separate_out = dstore.rc_separate_out
480 shell.separate_out = dstore.rc_separate_out
500 shell.separate_out2 = dstore.rc_separate_out2
481 shell.separate_out2 = dstore.rc_separate_out2
501
482
502 pm.justify = dstore.rc_prompts_pad_left
483 pm.justify = dstore.rc_prompts_pad_left
503
484
504 ptformatter.pprint = dstore.rc_pprint
485 ptformatter.pprint = dstore.rc_pprint
505 disp_formatter.active_types = dstore.rc_active_types
486 disp_formatter.active_types = dstore.rc_active_types
506
487
507 shell.magic('xmode ' + dstore.xmode)
488 shell.magic('xmode ' + dstore.xmode)
508
489
509 # Store new mode and inform
490 # Store new mode and inform
510 dstore.mode = bool(1-int(mode))
491 dstore.mode = bool(1-int(mode))
511 mode_label = ['OFF','ON'][dstore.mode]
492 mode_label = ['OFF','ON'][dstore.mode]
512 print('Doctest mode is:', mode_label)
493 print('Doctest mode is:', mode_label)
513
494
514 @line_magic
495 @line_magic
515 def gui(self, parameter_s=''):
496 def gui(self, parameter_s=''):
516 """Enable or disable IPython GUI event loop integration.
497 """Enable or disable IPython GUI event loop integration.
517
498
518 %gui [GUINAME]
499 %gui [GUINAME]
519
500
520 This magic replaces IPython's threaded shells that were activated
501 This magic replaces IPython's threaded shells that were activated
521 using the (pylab/wthread/etc.) command line flags. GUI toolkits
502 using the (pylab/wthread/etc.) command line flags. GUI toolkits
522 can now be enabled at runtime and keyboard
503 can now be enabled at runtime and keyboard
523 interrupts should work without any problems. The following toolkits
504 interrupts should work without any problems. The following toolkits
524 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
505 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
525
506
526 %gui wx # enable wxPython event loop integration
507 %gui wx # enable wxPython event loop integration
527 %gui qt4|qt # enable PyQt4 event loop integration
508 %gui qt4|qt # enable PyQt4 event loop integration
528 %gui qt5 # enable PyQt5 event loop integration
509 %gui qt5 # enable PyQt5 event loop integration
529 %gui gtk # enable PyGTK event loop integration
510 %gui gtk # enable PyGTK event loop integration
530 %gui gtk3 # enable Gtk3 event loop integration
511 %gui gtk3 # enable Gtk3 event loop integration
531 %gui tk # enable Tk event loop integration
512 %gui tk # enable Tk event loop integration
532 %gui osx # enable Cocoa event loop integration
513 %gui osx # enable Cocoa event loop integration
533 # (requires %matplotlib 1.1)
514 # (requires %matplotlib 1.1)
534 %gui # disable all event loop integration
515 %gui # disable all event loop integration
535
516
536 WARNING: after any of these has been called you can simply create
517 WARNING: after any of these has been called you can simply create
537 an application object, but DO NOT start the event loop yourself, as
518 an application object, but DO NOT start the event loop yourself, as
538 we have already handled that.
519 we have already handled that.
539 """
520 """
540 opts, arg = self.parse_options(parameter_s, '')
521 opts, arg = self.parse_options(parameter_s, '')
541 if arg=='': arg = None
522 if arg=='': arg = None
542 try:
523 try:
543 return self.shell.enable_gui(arg)
524 return self.shell.enable_gui(arg)
544 except Exception as e:
525 except Exception as e:
545 # print simple error message, rather than traceback if we can't
526 # print simple error message, rather than traceback if we can't
546 # hook up the GUI
527 # hook up the GUI
547 error(str(e))
528 error(str(e))
548
529
549 @skip_doctest
530 @skip_doctest
550 @line_magic
531 @line_magic
551 def precision(self, s=''):
532 def precision(self, s=''):
552 """Set floating point precision for pretty printing.
533 """Set floating point precision for pretty printing.
553
534
554 Can set either integer precision or a format string.
535 Can set either integer precision or a format string.
555
536
556 If numpy has been imported and precision is an int,
537 If numpy has been imported and precision is an int,
557 numpy display precision will also be set, via ``numpy.set_printoptions``.
538 numpy display precision will also be set, via ``numpy.set_printoptions``.
558
539
559 If no argument is given, defaults will be restored.
540 If no argument is given, defaults will be restored.
560
541
561 Examples
542 Examples
562 --------
543 --------
563 ::
544 ::
564
545
565 In [1]: from math import pi
546 In [1]: from math import pi
566
547
567 In [2]: %precision 3
548 In [2]: %precision 3
568 Out[2]: u'%.3f'
549 Out[2]: u'%.3f'
569
550
570 In [3]: pi
551 In [3]: pi
571 Out[3]: 3.142
552 Out[3]: 3.142
572
553
573 In [4]: %precision %i
554 In [4]: %precision %i
574 Out[4]: u'%i'
555 Out[4]: u'%i'
575
556
576 In [5]: pi
557 In [5]: pi
577 Out[5]: 3
558 Out[5]: 3
578
559
579 In [6]: %precision %e
560 In [6]: %precision %e
580 Out[6]: u'%e'
561 Out[6]: u'%e'
581
562
582 In [7]: pi**10
563 In [7]: pi**10
583 Out[7]: 9.364805e+04
564 Out[7]: 9.364805e+04
584
565
585 In [8]: %precision
566 In [8]: %precision
586 Out[8]: u'%r'
567 Out[8]: u'%r'
587
568
588 In [9]: pi**10
569 In [9]: pi**10
589 Out[9]: 93648.047476082982
570 Out[9]: 93648.047476082982
590 """
571 """
591 ptformatter = self.shell.display_formatter.formatters['text/plain']
572 ptformatter = self.shell.display_formatter.formatters['text/plain']
592 ptformatter.float_precision = s
573 ptformatter.float_precision = s
593 return ptformatter.float_format
574 return ptformatter.float_format
594
575
595 @magic_arguments.magic_arguments()
576 @magic_arguments.magic_arguments()
596 @magic_arguments.argument(
577 @magic_arguments.argument(
597 '-e', '--export', action='store_true', default=False,
578 '-e', '--export', action='store_true', default=False,
598 help='Export IPython history as a notebook. The filename argument '
579 help='Export IPython history as a notebook. The filename argument '
599 'is used to specify the notebook name and format. For example '
580 'is used to specify the notebook name and format. For example '
600 'a filename of notebook.ipynb will result in a notebook name '
581 'a filename of notebook.ipynb will result in a notebook name '
601 'of "notebook" and a format of "json". Likewise using a ".py" '
582 'of "notebook" and a format of "json". Likewise using a ".py" '
602 'file extension will write the notebook as a Python script'
583 'file extension will write the notebook as a Python script'
603 )
584 )
604 @magic_arguments.argument(
585 @magic_arguments.argument(
605 '-f', '--format',
606 help='Convert an existing IPython notebook to a new format. This option '
607 'specifies the new format and can have the values: json, py. '
608 'The target filename is chosen automatically based on the new '
609 'format. The filename argument gives the name of the source file.'
610 )
611 @magic_arguments.argument(
612 'filename', type=unicode_type,
586 'filename', type=unicode_type,
613 help='Notebook name or filename'
587 help='Notebook name or filename'
614 )
588 )
615 @line_magic
589 @line_magic
616 def notebook(self, s):
590 def notebook(self, s):
617 """Export and convert IPython notebooks.
591 """Export and convert IPython notebooks.
618
592
619 This function can export the current IPython history to a notebook file
593 This function can export the current IPython history to a notebook file.
620 or can convert an existing notebook file into a different format. For
594 For example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
621 example, to export the history to "foo.ipynb" do "%notebook -e foo.ipynb".
595 To export the history to "foo.py" do "%notebook -e foo.py".
622 To export the history to "foo.py" do "%notebook -e foo.py". To convert
623 "foo.ipynb" to "foo.json" do "%notebook -f json foo.ipynb". Possible
624 formats include (json/ipynb, py).
625 """
596 """
626 args = magic_arguments.parse_argstring(self.notebook, s)
597 args = magic_arguments.parse_argstring(self.notebook, s)
627
598
628 from IPython.nbformat import current
599 from IPython.nbformat import write, v4
629 args.filename = unquote_filename(args.filename)
600 args.filename = unquote_filename(args.filename)
630 if args.export:
601 if args.export:
631 fname, name, format = current.parse_filename(args.filename)
632 cells = []
602 cells = []
633 hist = list(self.shell.history_manager.get_range())
603 hist = list(self.shell.history_manager.get_range())
634 for session, prompt_number, input in hist[:-1]:
604 for session, execution_count, input in hist[:-1]:
635 cells.append(current.new_code_cell(prompt_number=prompt_number,
605 cells.append(v4.new_code_cell(
636 input=input))
606 execution_count=execution_count,
637 worksheet = current.new_worksheet(cells=cells)
607 source=source
638 nb = current.new_notebook(name=name,worksheets=[worksheet])
608 ))
639 with io.open(fname, 'w', encoding='utf-8') as f:
609 nb = v4.new_notebook(cells=cells)
640 current.write(nb, f, format);
610 with io.open(args.filename, 'w', encoding='utf-8') as f:
641 elif args.format is not None:
611 write(nb, f, version=4)
642 old_fname, old_name, old_format = current.parse_filename(args.filename)
643 new_format = args.format
644 if new_format == u'xml':
645 raise ValueError('Notebooks cannot be written as xml.')
646 elif new_format == u'ipynb' or new_format == u'json':
647 new_fname = old_name + u'.ipynb'
648 new_format = u'json'
649 elif new_format == u'py':
650 new_fname = old_name + u'.py'
651 else:
652 raise ValueError('Invalid notebook format: %s' % new_format)
653 with io.open(old_fname, 'r', encoding='utf-8') as f:
654 nb = current.read(f, old_format)
655 with io.open(new_fname, 'w', encoding='utf-8') as f:
656 current.write(nb, f, new_format)
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from IPython/html/static/notebook/js/notificationwidget.js to IPython/html/static/base/js/notificationwidget.js
NO CONTENT: file renamed from IPython/html/static/notebook/js/notificationwidget.js to IPython/html/static/base/js/notificationwidget.js
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from IPython/html/static/services/kernels/js/comm.js to IPython/html/static/services/kernels/comm.js
NO CONTENT: file renamed from IPython/html/static/services/kernels/js/comm.js to IPython/html/static/services/kernels/comm.js
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from IPython/html/fabfile.py to IPython/html/tasks.py
NO CONTENT: file renamed from IPython/html/fabfile.py to IPython/html/tasks.py
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from IPython/nbformat/convert.py to IPython/nbformat/converter.py
NO CONTENT: file renamed from IPython/nbformat/convert.py to IPython/nbformat/converter.py
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file renamed from IPython/nbformat/v4/v4.withref.json to IPython/nbformat/v3/nbformat.v3.schema.json
NO CONTENT: file renamed from IPython/nbformat/v4/v4.withref.json to IPython/nbformat/v3/nbformat.v3.schema.json
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now