##// END OF EJS Templates
Revert 3.7 AST fix...
Matthias Bussonnier -
Show More
@@ -1,58 +1,59 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.6
4 - 3.6
5 - 3.5
5 - 3.5
6 sudo: false
6 sudo: false
7 env:
7 env:
8 global:
8 global:
9 - PATH=$TRAVIS_BUILD_DIR/pandoc:$PATH
9 - PATH=$TRAVIS_BUILD_DIR/pandoc:$PATH
10 group: edge
10 group: edge
11 before_install:
11 before_install:
12 - 'if [[ $GROUP != js* ]]; then COVERAGE=""; fi'
12 - 'if [[ $GROUP != js* ]]; then COVERAGE=""; fi'
13 install:
13 install:
14 - pip install pip --upgrade
14 - pip install pip --upgrade
15 - pip install setuptools --upgrade
15 - pip install setuptools --upgrade
16 - pip install -e file://$PWD#egg=ipython[test] --upgrade
16 - pip install -e file://$PWD#egg=ipython[test] --upgrade
17 - pip install trio curio
17 - pip install trio curio
18 - pip install codecov check-manifest --upgrade
18 - pip install codecov check-manifest --upgrade
19 - sudo apt-get install graphviz
19 - sudo apt-get install graphviz
20 script:
20 script:
21 - check-manifest
21 - check-manifest
22 - cd /tmp && iptest --coverage xml && cd -
22 - cd /tmp && iptest --coverage xml && cd -
23 # On the latest Python only, make sure that the docs build.
23 # On the latest Python only, make sure that the docs build.
24 - |
24 - |
25 if [[ "$TRAVIS_PYTHON_VERSION" == "3.6" ]]; then
25 if [[ "$TRAVIS_PYTHON_VERSION" == "3.7" ]]; then
26 pip install -r docs/requirements.txt
26 pip install -r docs/requirements.txt
27 python tools/fixup_whats_new_pr.py
27 python tools/fixup_whats_new_pr.py
28 make -C docs/ html SPHINXOPTS="-W"
28 make -C docs/ html SPHINXOPTS="-W"
29 fi
29 fi
30 after_success:
30 after_success:
31 - cp /tmp/ipy_coverage.xml ./
31 - cp /tmp/ipy_coverage.xml ./
32 - cp /tmp/.coverage ./
32 - cp /tmp/.coverage ./
33 - codecov
33 - codecov
34
34
35 matrix:
35 matrix:
36 include:
36 include:
37 - { python: "3.7", dist: xenial, sudo: true }
37 - { python: "3.7", dist: xenial, sudo: true }
38 - { python: "3.7-dev", dist: xenial, sudo: true }
38 - { python: "nightly", dist: xenial, sudo: true }
39 - { python: "nightly", dist: xenial, sudo: true }
39 allow_failures:
40 allow_failures:
40 - python: nightly
41 - python: nightly
41
42
42 before_deploy:
43 before_deploy:
43 - rm -rf dist/
44 - rm -rf dist/
44 - python setup.py sdist
45 - python setup.py sdist
45 - python setup.py bdist_wheel
46 - python setup.py bdist_wheel
46
47
47 deploy:
48 deploy:
48 provider: releases
49 provider: releases
49 api_key:
50 api_key:
50 secure: Y/Ae9tYs5aoBU8bDjN2YrwGG6tCbezj/h3Lcmtx8HQavSbBgXnhnZVRb2snOKD7auqnqjfT/7QMm4ZyKvaOEgyggGktKqEKYHC8KOZ7yp8I5/UMDtk6j9TnXpSqqBxPiud4MDV76SfRYEQiaDoG4tGGvSfPJ9KcNjKrNvSyyxns=
51 secure: Y/Ae9tYs5aoBU8bDjN2YrwGG6tCbezj/h3Lcmtx8HQavSbBgXnhnZVRb2snOKD7auqnqjfT/7QMm4ZyKvaOEgyggGktKqEKYHC8KOZ7yp8I5/UMDtk6j9TnXpSqqBxPiud4MDV76SfRYEQiaDoG4tGGvSfPJ9KcNjKrNvSyyxns=
51 file: dist/*
52 file: dist/*
52 file_glob: true
53 file_glob: true
53 skip_cleanup: true
54 skip_cleanup: true
54 on:
55 on:
55 repo: ipython/ipython
56 repo: ipython/ipython
56 all_branches: true # Backports are released from e.g. 5.x branch
57 all_branches: true # Backports are released from e.g. 5.x branch
57 tags: true
58 tags: true
58 python: 3.6 # Any version should work, but we only need one
59 python: 3.6 # Any version should work, but we only need one
@@ -1,161 +1,144 b''
1 """Compiler tools with improved interactive support.
1 """Compiler tools with improved interactive support.
2
2
3 Provides compilation machinery similar to codeop, but with caching support so
3 Provides compilation machinery similar to codeop, but with caching support so
4 we can provide interactive tracebacks.
4 we can provide interactive tracebacks.
5
5
6 Authors
6 Authors
7 -------
7 -------
8 * Robert Kern
8 * Robert Kern
9 * Fernando Perez
9 * Fernando Perez
10 * Thomas Kluyver
10 * Thomas Kluyver
11 """
11 """
12
12
13 # Note: though it might be more natural to name this module 'compiler', that
13 # Note: though it might be more natural to name this module 'compiler', that
14 # name is in the stdlib and name collisions with the stdlib tend to produce
14 # name is in the stdlib and name collisions with the stdlib tend to produce
15 # weird problems (often with third-party tools).
15 # weird problems (often with third-party tools).
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Copyright (C) 2010-2011 The IPython Development Team.
18 # Copyright (C) 2010-2011 The IPython Development Team.
19 #
19 #
20 # Distributed under the terms of the BSD License.
20 # Distributed under the terms of the BSD License.
21 #
21 #
22 # The full license is in the file COPYING.txt, distributed with this software.
22 # The full license is in the file COPYING.txt, distributed with this software.
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Imports
26 # Imports
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 # Stdlib imports
29 # Stdlib imports
30 import __future__
30 import __future__
31 from ast import PyCF_ONLY_AST
31 from ast import PyCF_ONLY_AST
32 import codeop
32 import codeop
33 import functools
33 import functools
34 import hashlib
34 import hashlib
35 import linecache
35 import linecache
36 import operator
36 import operator
37 import time
37 import time
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Constants
40 # Constants
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42
42
43 # Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
43 # Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
44 # this is used as a bitmask to extract future-related code flags.
44 # this is used as a bitmask to extract future-related code flags.
45 PyCF_MASK = functools.reduce(operator.or_,
45 PyCF_MASK = functools.reduce(operator.or_,
46 (getattr(__future__, fname).compiler_flag
46 (getattr(__future__, fname).compiler_flag
47 for fname in __future__.all_feature_names))
47 for fname in __future__.all_feature_names))
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Local utilities
50 # Local utilities
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 def code_name(code, number=0):
53 def code_name(code, number=0):
54 """ Compute a (probably) unique name for code for caching.
54 """ Compute a (probably) unique name for code for caching.
55
55
56 This now expects code to be unicode.
56 This now expects code to be unicode.
57 """
57 """
58 hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
58 hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
59 # Include the number and 12 characters of the hash in the name. It's
59 # Include the number and 12 characters of the hash in the name. It's
60 # pretty much impossible that in a single session we'll have collisions
60 # pretty much impossible that in a single session we'll have collisions
61 # even with truncated hashes, and the full one makes tracebacks too long
61 # even with truncated hashes, and the full one makes tracebacks too long
62 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
62 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
63
63
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 # Classes and functions
65 # Classes and functions
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67
67
68 class CachingCompiler(codeop.Compile):
68 class CachingCompiler(codeop.Compile):
69 """A compiler that caches code compiled from interactive statements.
69 """A compiler that caches code compiled from interactive statements.
70 """
70 """
71
71
72 def __init__(self):
72 def __init__(self):
73 codeop.Compile.__init__(self)
73 codeop.Compile.__init__(self)
74
74
75 # This is ugly, but it must be done this way to allow multiple
75 # This is ugly, but it must be done this way to allow multiple
76 # simultaneous ipython instances to coexist. Since Python itself
76 # simultaneous ipython instances to coexist. Since Python itself
77 # directly accesses the data structures in the linecache module, and
77 # directly accesses the data structures in the linecache module, and
78 # the cache therein is global, we must work with that data structure.
78 # the cache therein is global, we must work with that data structure.
79 # We must hold a reference to the original checkcache routine and call
79 # We must hold a reference to the original checkcache routine and call
80 # that in our own check_cache() below, but the special IPython cache
80 # that in our own check_cache() below, but the special IPython cache
81 # must also be shared by all IPython instances. If we were to hold
81 # must also be shared by all IPython instances. If we were to hold
82 # separate caches (one in each CachingCompiler instance), any call made
82 # separate caches (one in each CachingCompiler instance), any call made
83 # by Python itself to linecache.checkcache() would obliterate the
83 # by Python itself to linecache.checkcache() would obliterate the
84 # cached data from the other IPython instances.
84 # cached data from the other IPython instances.
85 if not hasattr(linecache, '_ipython_cache'):
85 if not hasattr(linecache, '_ipython_cache'):
86 linecache._ipython_cache = {}
86 linecache._ipython_cache = {}
87 if not hasattr(linecache, '_checkcache_ori'):
87 if not hasattr(linecache, '_checkcache_ori'):
88 linecache._checkcache_ori = linecache.checkcache
88 linecache._checkcache_ori = linecache.checkcache
89 # Now, we must monkeypatch the linecache directly so that parts of the
89 # Now, we must monkeypatch the linecache directly so that parts of the
90 # stdlib that call it outside our control go through our codepath
90 # stdlib that call it outside our control go through our codepath
91 # (otherwise we'd lose our tracebacks).
91 # (otherwise we'd lose our tracebacks).
92 linecache.checkcache = check_linecache_ipython
92 linecache.checkcache = check_linecache_ipython
93
93
94
94
95 def _fix_module_ds(self, module):
96 """
97 Starting in python 3.7 the AST for mule have changed, and if
98 the first expressions encountered is a string it is attached to the
99 `docstring` attribute of the `Module` ast node.
100
101 This breaks IPython, as if this string is the only expression, IPython
102 will not return it as the result of the current cell.
103 """
104 from ast import Str, Expr, Module, fix_missing_locations
105 docstring = getattr(module, 'docstring', None)
106 if not docstring:
107 return module
108 new_body=[Expr(Str(docstring, lineno=1, col_offset=0), lineno=1, col_offset=0)]
109 new_body.extend(module.body)
110 return fix_missing_locations(Module(new_body))
111
112 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
95 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
113 """Parse code to an AST with the current compiler flags active.
96 """Parse code to an AST with the current compiler flags active.
114
97
115 Arguments are exactly the same as ast.parse (in the standard library),
98 Arguments are exactly the same as ast.parse (in the standard library),
116 and are passed to the built-in compile function."""
99 and are passed to the built-in compile function."""
117 return self._fix_module_ds(compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1))
100 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
118
101
119 def reset_compiler_flags(self):
102 def reset_compiler_flags(self):
120 """Reset compiler flags to default state."""
103 """Reset compiler flags to default state."""
121 # This value is copied from codeop.Compile.__init__, so if that ever
104 # This value is copied from codeop.Compile.__init__, so if that ever
122 # changes, it will need to be updated.
105 # changes, it will need to be updated.
123 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
106 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
124
107
125 @property
108 @property
126 def compiler_flags(self):
109 def compiler_flags(self):
127 """Flags currently active in the compilation process.
110 """Flags currently active in the compilation process.
128 """
111 """
129 return self.flags
112 return self.flags
130
113
131 def cache(self, code, number=0):
114 def cache(self, code, number=0):
132 """Make a name for a block of code, and cache the code.
115 """Make a name for a block of code, and cache the code.
133
116
134 Parameters
117 Parameters
135 ----------
118 ----------
136 code : str
119 code : str
137 The Python source code to cache.
120 The Python source code to cache.
138 number : int
121 number : int
139 A number which forms part of the code's name. Used for the execution
122 A number which forms part of the code's name. Used for the execution
140 counter.
123 counter.
141
124
142 Returns
125 Returns
143 -------
126 -------
144 The name of the cached code (as a string). Pass this as the filename
127 The name of the cached code (as a string). Pass this as the filename
145 argument to compilation, so that tracebacks are correctly hooked up.
128 argument to compilation, so that tracebacks are correctly hooked up.
146 """
129 """
147 name = code_name(code, number)
130 name = code_name(code, number)
148 entry = (len(code), time.time(),
131 entry = (len(code), time.time(),
149 [line+'\n' for line in code.splitlines()], name)
132 [line+'\n' for line in code.splitlines()], name)
150 linecache.cache[name] = entry
133 linecache.cache[name] = entry
151 linecache._ipython_cache[name] = entry
134 linecache._ipython_cache[name] = entry
152 return name
135 return name
153
136
154 def check_linecache_ipython(*args):
137 def check_linecache_ipython(*args):
155 """Call linecache.checkcache() safely protecting our cached values.
138 """Call linecache.checkcache() safely protecting our cached values.
156 """
139 """
157 # First call the original checkcache as intended
140 # First call the original checkcache as intended
158 linecache._checkcache_ori(*args)
141 linecache._checkcache_ori(*args)
159 # Then, update back the cache with our data, so that tracebacks related
142 # Then, update back the cache with our data, so that tracebacks related
160 # to our compiled codes can be produced.
143 # to our compiled codes can be produced.
161 linecache.cache.update(linecache._ipython_cache)
144 linecache.cache.update(linecache._ipython_cache)
General Comments 0
You need to be logged in to leave comments. Login now