##// END OF EJS Templates
remove trio from test requirement and skipp if not there
Matthias Bussonnier -
Show More
@@ -1,252 +1,255 b''
1 1 """
2 2 Test for async helpers.
3 3
4 4 Should only trigger on python 3.5+ or will have syntax errors.
5 5 """
6 6
7 7 import sys
8 8 from itertools import chain, repeat
9 9 import nose.tools as nt
10 10 from textwrap import dedent, indent
11 11 from unittest import TestCase
12 from IPython.testing.decorators import skip_without
12 13
13 14 ip = get_ipython()
14 15 iprc = lambda x: ip.run_cell(dedent(x)).raise_error()
15 16
16 17 if sys.version_info > (3, 5):
17 18 from IPython.core.async_helpers import _should_be_async
18 19
19 20 class AsyncTest(TestCase):
20 21 def test_should_be_async(self):
21 22 nt.assert_false(_should_be_async("False"))
22 23 nt.assert_true(_should_be_async("await bar()"))
23 24 nt.assert_true(_should_be_async("x = await bar()"))
24 25 nt.assert_false(
25 26 _should_be_async(
26 27 dedent(
27 28 """
28 29 async def awaitable():
29 30 pass
30 31 """
31 32 )
32 33 )
33 34 )
34 35
35 36 def _get_top_level_cases(self):
36 37 # These are test cases that should be valid in a function
37 38 # but invalid outside of a function.
38 39 test_cases = []
39 40 test_cases.append(('basic', "{val}"))
40 41
41 42 # Note, in all conditional cases, I use True instead of
42 43 # False so that the peephole optimizer won't optimize away
43 44 # the return, so CPython will see this as a syntax error:
44 45 #
45 46 # while True:
46 47 # break
47 48 # return
48 49 #
49 50 # But not this:
50 51 #
51 52 # while False:
52 53 # return
53 54 #
54 55 # See https://bugs.python.org/issue1875
55 56
56 57 test_cases.append(('if', dedent("""
57 58 if True:
58 59 {val}
59 60 """)))
60 61
61 62 test_cases.append(('while', dedent("""
62 63 while True:
63 64 {val}
64 65 break
65 66 """)))
66 67
67 68 test_cases.append(('try', dedent("""
68 69 try:
69 70 {val}
70 71 except:
71 72 pass
72 73 """)))
73 74
74 75 test_cases.append(('except', dedent("""
75 76 try:
76 77 pass
77 78 except:
78 79 {val}
79 80 """)))
80 81
81 82 test_cases.append(('finally', dedent("""
82 83 try:
83 84 pass
84 85 except:
85 86 pass
86 87 finally:
87 88 {val}
88 89 """)))
89 90
90 91 test_cases.append(('for', dedent("""
91 92 for _ in range(4):
92 93 {val}
93 94 """)))
94 95
95 96
96 97 test_cases.append(('nested', dedent("""
97 98 if True:
98 99 while True:
99 100 {val}
100 101 break
101 102 """)))
102 103
103 104 test_cases.append(('deep-nested', dedent("""
104 105 if True:
105 106 while True:
106 107 break
107 108 for x in range(3):
108 109 if True:
109 110 while True:
110 111 for x in range(3):
111 112 {val}
112 113 """)))
113 114
114 115 return test_cases
115 116
116 117 def _get_ry_syntax_errors(self):
117 118 # This is a mix of tests that should be a syntax error if
118 119 # return or yield whether or not they are in a function
119 120
120 121 test_cases = []
121 122
122 123 test_cases.append(('class', dedent("""
123 124 class V:
124 125 {val}
125 126 """)))
126 127
127 128 test_cases.append(('nested-class', dedent("""
128 129 class V:
129 130 class C:
130 131 {val}
131 132 """)))
132 133
133 134 return test_cases
134 135
135 136
136 137 def test_top_level_return_error(self):
137 138 tl_err_test_cases = self._get_top_level_cases()
138 139 tl_err_test_cases.extend(self._get_ry_syntax_errors())
139 140
140 141 vals = ('return', 'yield', 'yield from (_ for _ in range(3))')
141 142
142 143 for test_name, test_case in tl_err_test_cases:
143 144 # This example should work if 'pass' is used as the value
144 145 with self.subTest((test_name, 'pass')):
145 146 iprc(test_case.format(val='pass'))
146 147
147 148 # It should fail with all the values
148 149 for val in vals:
149 150 with self.subTest((test_name, val)):
150 151 msg = "Syntax error not raised for %s, %s" % (test_name, val)
151 152 with self.assertRaises(SyntaxError, msg=msg):
152 153 iprc(test_case.format(val=val))
153 154
154 155 def test_in_func_no_error(self):
155 156 # Test that the implementation of top-level return/yield
156 157 # detection isn't *too* aggressive, and works inside a function
157 158 func_contexts = []
158 159
159 160 func_contexts.append(('func', False, dedent("""
160 161 def f():""")))
161 162
162 163 func_contexts.append(('method', False, dedent("""
163 164 class MyClass:
164 165 def __init__(self):
165 166 """)))
166 167
167 168 func_contexts.append(('async-func', True, dedent("""
168 169 async def f():""")))
169 170
170 171 func_contexts.append(('async-method', True, dedent("""
171 172 class MyClass:
172 173 async def f(self):""")))
173 174
174 175 func_contexts.append(('closure', False, dedent("""
175 176 def f():
176 177 def g():
177 178 """)))
178 179
179 180 def nest_case(context, case):
180 181 # Detect indentation
181 182 lines = context.strip().splitlines()
182 183 prefix_len = 0
183 184 for c in lines[-1]:
184 185 if c != ' ':
185 186 break
186 187 prefix_len += 1
187 188
188 189 indented_case = indent(case, ' ' * (prefix_len + 4))
189 190 return context + '\n' + indented_case
190 191
191 192 # Gather and run the tests
192 193
193 194 # yield is allowed in async functions, starting in Python 3.6,
194 195 # and yield from is not allowed in any version
195 196 vals = ('return', 'yield', 'yield from (_ for _ in range(3))')
196 197 async_safe = (True,
197 198 sys.version_info >= (3, 6),
198 199 False)
199 200 vals = tuple(zip(vals, async_safe))
200 201
201 202 success_tests = zip(self._get_top_level_cases(), repeat(False))
202 203 failure_tests = zip(self._get_ry_syntax_errors(), repeat(True))
203 204
204 205 tests = chain(success_tests, failure_tests)
205 206
206 207 for context_name, async_func, context in func_contexts:
207 208 for (test_name, test_case), should_fail in tests:
208 209 nested_case = nest_case(context, test_case)
209 210
210 211 for val, async_safe in vals:
211 212 val_should_fail = (should_fail or
212 213 (async_func and not async_safe))
213 214
214 215 test_id = (context_name, test_name, val)
215 216 cell = nested_case.format(val=val)
216 217
217 218 with self.subTest(test_id):
218 219 if val_should_fail:
219 220 msg = ("SyntaxError not raised for %s" %
220 221 str(test_id))
221 222 with self.assertRaises(SyntaxError, msg=msg):
222 223 iprc(cell)
223 224
224 225 print(cell)
225 226 else:
226 227 iprc(cell)
227 228
228 229
229 230 def test_execute(self):
230 231 iprc("""
231 232 import asyncio
232 233 await asyncio.sleep(0.001)
233 234 """
234 235 )
235 236
236 237 def test_autoawait(self):
237 238 iprc("%autoawait False")
238 239 iprc("%autoawait True")
239 240 iprc("""
240 241 from asyncio import sleep
241 242 await sleep(0.1)
242 243 """
243 244 )
244 245
246 @skip_without('curio')
245 247 def test_autoawait_curio(self):
246 248 iprc("%autoawait curio")
247 249
250 @skip_without('trio')
248 251 def test_autoawait_trio(self):
249 252 iprc("%autoawait trio")
250 253
251 254 def tearDown(self):
252 255 ip.loop_runner = "asyncio"
@@ -1,264 +1,264 b''
1 1 #!/usr/bin/env python3
2 2 # -*- coding: utf-8 -*-
3 3 """Setup script for IPython.
4 4
5 5 Under Posix environments it works like a typical setup.py script.
6 6 Under Windows, the command sdist is not supported, since IPython
7 7 requires utilities which are not available under Windows."""
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (c) 2008-2011, IPython Development Team.
11 11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 14 #
15 15 # Distributed under the terms of the Modified BSD License.
16 16 #
17 17 # The full license is in the file COPYING.rst, distributed with this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 from __future__ import print_function
21 21
22 22 import os
23 23 import sys
24 24
25 25 # **Python version check**
26 26 #
27 27 # This check is also made in IPython/__init__, don't forget to update both when
28 28 # changing Python version requirements.
29 29 if sys.version_info < (3, 5):
30 30 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
31 31 try:
32 32 import pip
33 33 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
34 34 if pip_version < (9, 0, 1) :
35 35 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
36 36 'pip {} detected.'.format(pip.__version__)
37 37 else:
38 38 # pip is new enough - it must be something else
39 39 pip_message = ''
40 40 except Exception:
41 41 pass
42 42
43 43
44 44 error = """
45 45 IPython 7.0+ supports Python 3.5 and above.
46 46 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
47 47 Python 3.3 and 3.4 were supported up to IPython 6.x.
48 48
49 49 See IPython `README.rst` file for more information:
50 50
51 51 https://github.com/ipython/ipython/blob/master/README.rst
52 52
53 53 Python {py} detected.
54 54 {pip}
55 55 """.format(py=sys.version_info, pip=pip_message )
56 56
57 57 print(error, file=sys.stderr)
58 58 sys.exit(1)
59 59
60 60 # At least we're on the python version we need, move on.
61 61
62 62 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
63 63 # update it when the contents of directories change.
64 64 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
65 65
66 66 from distutils.core import setup
67 67
68 68 # Our own imports
69 69 from setupbase import target_update
70 70
71 71 from setupbase import (
72 72 setup_args,
73 73 find_packages,
74 74 find_package_data,
75 75 check_package_data_first,
76 76 find_entry_points,
77 77 build_scripts_entrypt,
78 78 find_data_files,
79 79 git_prebuild,
80 80 install_symlinked,
81 81 install_lib_symlink,
82 82 install_scripts_for_symlink,
83 83 unsymlink,
84 84 )
85 85
86 86 isfile = os.path.isfile
87 87 pjoin = os.path.join
88 88
89 89 #-------------------------------------------------------------------------------
90 90 # Handle OS specific things
91 91 #-------------------------------------------------------------------------------
92 92
93 93 if os.name in ('nt','dos'):
94 94 os_name = 'windows'
95 95 else:
96 96 os_name = os.name
97 97
98 98 # Under Windows, 'sdist' has not been supported. Now that the docs build with
99 99 # Sphinx it might work, but let's not turn it on until someone confirms that it
100 100 # actually works.
101 101 if os_name == 'windows' and 'sdist' in sys.argv:
102 102 print('The sdist command is not available under Windows. Exiting.')
103 103 sys.exit(1)
104 104
105 105
106 106 #-------------------------------------------------------------------------------
107 107 # Things related to the IPython documentation
108 108 #-------------------------------------------------------------------------------
109 109
110 110 # update the manuals when building a source dist
111 111 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
112 112
113 113 # List of things to be updated. Each entry is a triplet of args for
114 114 # target_update()
115 115 to_update = [
116 116 ('docs/man/ipython.1.gz',
117 117 ['docs/man/ipython.1'],
118 118 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
119 119 ]
120 120
121 121
122 122 [ target_update(*t) for t in to_update ]
123 123
124 124 #---------------------------------------------------------------------------
125 125 # Find all the packages, package data, and data_files
126 126 #---------------------------------------------------------------------------
127 127
128 128 packages = find_packages()
129 129 package_data = find_package_data()
130 130
131 131 data_files = find_data_files()
132 132
133 133 setup_args['packages'] = packages
134 134 setup_args['package_data'] = package_data
135 135 setup_args['data_files'] = data_files
136 136
137 137 #---------------------------------------------------------------------------
138 138 # custom distutils commands
139 139 #---------------------------------------------------------------------------
140 140 # imports here, so they are after setuptools import if there was one
141 141 from distutils.command.sdist import sdist
142 142
143 143 setup_args['cmdclass'] = {
144 144 'build_py': \
145 145 check_package_data_first(git_prebuild('IPython')),
146 146 'sdist' : git_prebuild('IPython', sdist),
147 147 'symlink': install_symlinked,
148 148 'install_lib_symlink': install_lib_symlink,
149 149 'install_scripts_sym': install_scripts_for_symlink,
150 150 'unsymlink': unsymlink,
151 151 }
152 152
153 153
154 154 #---------------------------------------------------------------------------
155 155 # Handle scripts, dependencies, and setuptools specific things
156 156 #---------------------------------------------------------------------------
157 157
158 158 # For some commands, use setuptools. Note that we do NOT list install here!
159 159 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
160 160 needs_setuptools = {'develop', 'release', 'bdist_egg', 'bdist_rpm',
161 161 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
162 162 'egg_info', 'easy_install', 'upload', 'install_egg_info',
163 163 }
164 164
165 165 if len(needs_setuptools.intersection(sys.argv)) > 0:
166 166 import setuptools
167 167
168 168 # This dict is used for passing extra arguments that are setuptools
169 169 # specific to setup
170 170 setuptools_extra_args = {}
171 171
172 172 # setuptools requirements
173 173
174 174 extras_require = dict(
175 175 parallel = ['ipyparallel'],
176 176 qtconsole = ['qtconsole'],
177 177 doc = ['Sphinx>=1.3'],
178 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy', 'trio'],
178 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments', 'nbformat', 'ipykernel', 'numpy'],
179 179 terminal = [],
180 180 kernel = ['ipykernel'],
181 181 nbformat = ['nbformat'],
182 182 notebook = ['notebook', 'ipywidgets'],
183 183 nbconvert = ['nbconvert'],
184 184 )
185 185
186 186 install_requires = [
187 187 'setuptools>=18.5',
188 188 'jedi>=0.10',
189 189 'decorator',
190 190 'pickleshare',
191 191 'simplegeneric>0.8',
192 192 'traitlets>=4.2',
193 193 'prompt_toolkit>=2.0.0,<2.1.0',
194 194 'pygments',
195 195 'backcall',
196 196 ]
197 197
198 198 # Platform-specific dependencies:
199 199 # This is the correct way to specify these,
200 200 # but requires pip >= 6. pip < 6 ignores these.
201 201
202 202 extras_require.update({
203 203 ':python_version == "3.4"': ['typing'],
204 204 ':sys_platform != "win32"': ['pexpect'],
205 205 ':sys_platform == "darwin"': ['appnope'],
206 206 ':sys_platform == "win32"': ['colorama'],
207 207 ':sys_platform == "win32" and python_version < "3.6"': ['win_unicode_console>=0.5'],
208 208 })
209 209 # FIXME: re-specify above platform dependencies for pip < 6
210 210 # These would result in non-portable bdists.
211 211 if not any(arg.startswith('bdist') for arg in sys.argv):
212 212 if sys.platform == 'darwin':
213 213 install_requires.extend(['appnope'])
214 214
215 215 if not sys.platform.startswith('win'):
216 216 install_requires.append('pexpect')
217 217
218 218 # workaround pypa/setuptools#147, where setuptools misspells
219 219 # platform_python_implementation as python_implementation
220 220 if 'setuptools' in sys.modules:
221 221 for key in list(extras_require):
222 222 if 'platform_python_implementation' in key:
223 223 new_key = key.replace('platform_python_implementation', 'python_implementation')
224 224 extras_require[new_key] = extras_require.pop(key)
225 225
226 226 everything = set()
227 227 for key, deps in extras_require.items():
228 228 if ':' not in key:
229 229 everything.update(deps)
230 230 extras_require['all'] = everything
231 231
232 232 if 'setuptools' in sys.modules:
233 233 setuptools_extra_args['python_requires'] = '>=3.5'
234 234 setuptools_extra_args['zip_safe'] = False
235 235 setuptools_extra_args['entry_points'] = {
236 236 'console_scripts': find_entry_points(),
237 237 'pygments.lexers': [
238 238 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
239 239 'ipython = IPython.lib.lexers:IPythonLexer',
240 240 'ipython3 = IPython.lib.lexers:IPython3Lexer',
241 241 ],
242 242 }
243 243 setup_args['extras_require'] = extras_require
244 244 setup_args['install_requires'] = install_requires
245 245
246 246 else:
247 247 # scripts has to be a non-empty list, or install_scripts isn't called
248 248 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
249 249
250 250 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
251 251
252 252 #---------------------------------------------------------------------------
253 253 # Do the actual setup now
254 254 #---------------------------------------------------------------------------
255 255
256 256 setup_args.update(setuptools_extra_args)
257 257
258 258
259 259
260 260 def main():
261 261 setup(**setup_args)
262 262
263 263 if __name__ == '__main__':
264 264 main()
General Comments 0
You need to be logged in to leave comments. Login now