##// END OF EJS Templates
Remove unneeded `ipykernel` tests requirement
Nikita Kniazev -
Show More
@@ -1,515 +1,513
1 # Copyright (c) IPython Development Team.
1 # Copyright (c) IPython Development Team.
2 # Distributed under the terms of the Modified BSD License.
2 # Distributed under the terms of the Modified BSD License.
3
3
4 import json
4 import json
5 import os
5 import os
6 import warnings
6 import warnings
7
7
8 from unittest import mock
8 from unittest import mock
9
9
10 import pytest
10 import pytest
11
11
12 from IPython import display
12 from IPython import display
13 from IPython.core.getipython import get_ipython
13 from IPython.core.getipython import get_ipython
14 from IPython.utils.io import capture_output
14 from IPython.utils.io import capture_output
15 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
15 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
16 from IPython import paths as ipath
16 from IPython import paths as ipath
17 from IPython.testing.tools import AssertNotPrints
17 from IPython.testing.tools import AssertNotPrints
18
18
19 import IPython.testing.decorators as dec
19 import IPython.testing.decorators as dec
20
20
21 def test_image_size():
21 def test_image_size():
22 """Simple test for display.Image(args, width=x,height=y)"""
22 """Simple test for display.Image(args, width=x,height=y)"""
23 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
23 thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
24 img = display.Image(url=thisurl, width=200, height=200)
24 img = display.Image(url=thisurl, width=200, height=200)
25 assert '<img src="%s" width="200" height="200"/>' % (thisurl) == img._repr_html_()
25 assert '<img src="%s" width="200" height="200"/>' % (thisurl) == img._repr_html_()
26 img = display.Image(url=thisurl, metadata={'width':200, 'height':200})
26 img = display.Image(url=thisurl, metadata={'width':200, 'height':200})
27 assert '<img src="%s" width="200" height="200"/>' % (thisurl) == img._repr_html_()
27 assert '<img src="%s" width="200" height="200"/>' % (thisurl) == img._repr_html_()
28 img = display.Image(url=thisurl, width=200)
28 img = display.Image(url=thisurl, width=200)
29 assert '<img src="%s" width="200"/>' % (thisurl) == img._repr_html_()
29 assert '<img src="%s" width="200"/>' % (thisurl) == img._repr_html_()
30 img = display.Image(url=thisurl)
30 img = display.Image(url=thisurl)
31 assert '<img src="%s"/>' % (thisurl) == img._repr_html_()
31 assert '<img src="%s"/>' % (thisurl) == img._repr_html_()
32 img = display.Image(url=thisurl, unconfined=True)
32 img = display.Image(url=thisurl, unconfined=True)
33 assert '<img src="%s" class="unconfined"/>' % (thisurl) == img._repr_html_()
33 assert '<img src="%s" class="unconfined"/>' % (thisurl) == img._repr_html_()
34
34
35
35
36 def test_image_mimes():
36 def test_image_mimes():
37 fmt = get_ipython().display_formatter.format
37 fmt = get_ipython().display_formatter.format
38 for format in display.Image._ACCEPTABLE_EMBEDDINGS:
38 for format in display.Image._ACCEPTABLE_EMBEDDINGS:
39 mime = display.Image._MIMETYPES[format]
39 mime = display.Image._MIMETYPES[format]
40 img = display.Image(b'garbage', format=format)
40 img = display.Image(b'garbage', format=format)
41 data, metadata = fmt(img)
41 data, metadata = fmt(img)
42 assert sorted(data) == sorted([mime, "text/plain"])
42 assert sorted(data) == sorted([mime, "text/plain"])
43
43
44
44
45 def test_geojson():
45 def test_geojson():
46
46
47 gj = display.GeoJSON(data={
47 gj = display.GeoJSON(data={
48 "type": "Feature",
48 "type": "Feature",
49 "geometry": {
49 "geometry": {
50 "type": "Point",
50 "type": "Point",
51 "coordinates": [-81.327, 296.038]
51 "coordinates": [-81.327, 296.038]
52 },
52 },
53 "properties": {
53 "properties": {
54 "name": "Inca City"
54 "name": "Inca City"
55 }
55 }
56 },
56 },
57 url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
57 url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
58 layer_options={
58 layer_options={
59 "basemap_id": "celestia_mars-shaded-16k_global",
59 "basemap_id": "celestia_mars-shaded-16k_global",
60 "attribution": "Celestia/praesepe",
60 "attribution": "Celestia/praesepe",
61 "minZoom": 0,
61 "minZoom": 0,
62 "maxZoom": 18,
62 "maxZoom": 18,
63 },
63 },
64 )
64 )
65 assert "<IPython.core.display.GeoJSON object>" == str(gj)
65 assert "<IPython.core.display.GeoJSON object>" == str(gj)
66
66
67
67
68 def test_retina_png():
68 def test_retina_png():
69 here = os.path.dirname(__file__)
69 here = os.path.dirname(__file__)
70 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
70 img = display.Image(os.path.join(here, "2x2.png"), retina=True)
71 assert img.height == 1
71 assert img.height == 1
72 assert img.width == 1
72 assert img.width == 1
73 data, md = img._repr_png_()
73 data, md = img._repr_png_()
74 assert md["width"] == 1
74 assert md["width"] == 1
75 assert md["height"] == 1
75 assert md["height"] == 1
76
76
77
77
78 def test_embed_svg_url():
78 def test_embed_svg_url():
79 import gzip
79 import gzip
80 from io import BytesIO
80 from io import BytesIO
81 svg_data = b'<svg><circle x="0" y="0" r="1"/></svg>'
81 svg_data = b'<svg><circle x="0" y="0" r="1"/></svg>'
82 url = 'http://test.com/circle.svg'
82 url = 'http://test.com/circle.svg'
83
83
84 gzip_svg = BytesIO()
84 gzip_svg = BytesIO()
85 with gzip.open(gzip_svg, 'wb') as fp:
85 with gzip.open(gzip_svg, 'wb') as fp:
86 fp.write(svg_data)
86 fp.write(svg_data)
87 gzip_svg = gzip_svg.getvalue()
87 gzip_svg = gzip_svg.getvalue()
88
88
89 def mocked_urlopen(*args, **kwargs):
89 def mocked_urlopen(*args, **kwargs):
90 class MockResponse:
90 class MockResponse:
91 def __init__(self, svg):
91 def __init__(self, svg):
92 self._svg_data = svg
92 self._svg_data = svg
93 self.headers = {'content-type': 'image/svg+xml'}
93 self.headers = {'content-type': 'image/svg+xml'}
94
94
95 def read(self):
95 def read(self):
96 return self._svg_data
96 return self._svg_data
97
97
98 if args[0] == url:
98 if args[0] == url:
99 return MockResponse(svg_data)
99 return MockResponse(svg_data)
100 elif args[0] == url + "z":
100 elif args[0] == url + "z":
101 ret = MockResponse(gzip_svg)
101 ret = MockResponse(gzip_svg)
102 ret.headers["content-encoding"] = "gzip"
102 ret.headers["content-encoding"] = "gzip"
103 return ret
103 return ret
104 return MockResponse(None)
104 return MockResponse(None)
105
105
106 with mock.patch('urllib.request.urlopen', side_effect=mocked_urlopen):
106 with mock.patch('urllib.request.urlopen', side_effect=mocked_urlopen):
107 svg = display.SVG(url=url)
107 svg = display.SVG(url=url)
108 assert svg._repr_svg_().startswith("<svg") is True
108 assert svg._repr_svg_().startswith("<svg") is True
109 svg = display.SVG(url=url + "z")
109 svg = display.SVG(url=url + "z")
110 assert svg._repr_svg_().startswith("<svg") is True
110 assert svg._repr_svg_().startswith("<svg") is True
111
111
112
112
113 def test_retina_jpeg():
113 def test_retina_jpeg():
114 here = os.path.dirname(__file__)
114 here = os.path.dirname(__file__)
115 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
115 img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
116 assert img.height == 1
116 assert img.height == 1
117 assert img.width == 1
117 assert img.width == 1
118 data, md = img._repr_jpeg_()
118 data, md = img._repr_jpeg_()
119 assert md["width"] == 1
119 assert md["width"] == 1
120 assert md["height"] == 1
120 assert md["height"] == 1
121
121
122
122
123 def test_base64image():
123 def test_base64image():
124 display.Image("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BCRQnOqNu0b4AAAAKSURBVAjXY2AAAAACAAHiIbwzAAAAAElFTkSuQmCC")
124 display.Image("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BCRQnOqNu0b4AAAAKSURBVAjXY2AAAAACAAHiIbwzAAAAAElFTkSuQmCC")
125
125
126 def test_image_filename_defaults():
126 def test_image_filename_defaults():
127 '''test format constraint, and validity of jpeg and png'''
127 '''test format constraint, and validity of jpeg and png'''
128 tpath = ipath.get_ipython_package_dir()
128 tpath = ipath.get_ipython_package_dir()
129 pytest.raises(
129 pytest.raises(
130 ValueError,
130 ValueError,
131 display.Image,
131 display.Image,
132 filename=os.path.join(tpath, "testing/tests/badformat.zip"),
132 filename=os.path.join(tpath, "testing/tests/badformat.zip"),
133 embed=True,
133 embed=True,
134 )
134 )
135 pytest.raises(ValueError, display.Image)
135 pytest.raises(ValueError, display.Image)
136 pytest.raises(
136 pytest.raises(
137 ValueError,
137 ValueError,
138 display.Image,
138 display.Image,
139 data="this is not an image",
139 data="this is not an image",
140 format="badformat",
140 format="badformat",
141 embed=True,
141 embed=True,
142 )
142 )
143 # check boths paths to allow packages to test at build and install time
143 # check boths paths to allow packages to test at build and install time
144 imgfile = os.path.join(tpath, 'core/tests/2x2.png')
144 imgfile = os.path.join(tpath, 'core/tests/2x2.png')
145 img = display.Image(filename=imgfile)
145 img = display.Image(filename=imgfile)
146 assert "png" == img.format
146 assert "png" == img.format
147 assert img._repr_png_() is not None
147 assert img._repr_png_() is not None
148 img = display.Image(
148 img = display.Image(
149 filename=os.path.join(tpath, "testing/tests/logo.jpg"), embed=False
149 filename=os.path.join(tpath, "testing/tests/logo.jpg"), embed=False
150 )
150 )
151 assert "jpeg" == img.format
151 assert "jpeg" == img.format
152 assert img._repr_jpeg_() is None
152 assert img._repr_jpeg_() is None
153
153
154 def _get_inline_config():
154 def _get_inline_config():
155 from matplotlib_inline.config import InlineBackend
155 from matplotlib_inline.config import InlineBackend
156 return InlineBackend.instance()
156 return InlineBackend.instance()
157
157
158
158
159 @dec.skip_without("ipykernel")
160 @dec.skip_without("matplotlib")
159 @dec.skip_without("matplotlib")
161 def test_set_matplotlib_close():
160 def test_set_matplotlib_close():
162 cfg = _get_inline_config()
161 cfg = _get_inline_config()
163 cfg.close_figures = False
162 cfg.close_figures = False
164 with pytest.deprecated_call():
163 with pytest.deprecated_call():
165 display.set_matplotlib_close()
164 display.set_matplotlib_close()
166 assert cfg.close_figures
165 assert cfg.close_figures
167 with pytest.deprecated_call():
166 with pytest.deprecated_call():
168 display.set_matplotlib_close(False)
167 display.set_matplotlib_close(False)
169 assert not cfg.close_figures
168 assert not cfg.close_figures
170
169
171 _fmt_mime_map = {
170 _fmt_mime_map = {
172 'png': 'image/png',
171 'png': 'image/png',
173 'jpeg': 'image/jpeg',
172 'jpeg': 'image/jpeg',
174 'pdf': 'application/pdf',
173 'pdf': 'application/pdf',
175 'retina': 'image/png',
174 'retina': 'image/png',
176 'svg': 'image/svg+xml',
175 'svg': 'image/svg+xml',
177 }
176 }
178
177
179 @dec.skip_without('matplotlib')
178 @dec.skip_without('matplotlib')
180 def test_set_matplotlib_formats():
179 def test_set_matplotlib_formats():
181 from matplotlib.figure import Figure
180 from matplotlib.figure import Figure
182 formatters = get_ipython().display_formatter.formatters
181 formatters = get_ipython().display_formatter.formatters
183 for formats in [
182 for formats in [
184 ('png',),
183 ('png',),
185 ('pdf', 'svg'),
184 ('pdf', 'svg'),
186 ('jpeg', 'retina', 'png'),
185 ('jpeg', 'retina', 'png'),
187 (),
186 (),
188 ]:
187 ]:
189 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
188 active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
190 with pytest.deprecated_call():
189 with pytest.deprecated_call():
191 display.set_matplotlib_formats(*formats)
190 display.set_matplotlib_formats(*formats)
192 for mime, f in formatters.items():
191 for mime, f in formatters.items():
193 if mime in active_mimes:
192 if mime in active_mimes:
194 assert Figure in f
193 assert Figure in f
195 else:
194 else:
196 assert Figure not in f
195 assert Figure not in f
197
196
198
197
199 @dec.skip_without("ipykernel")
200 @dec.skip_without("matplotlib")
198 @dec.skip_without("matplotlib")
201 def test_set_matplotlib_formats_kwargs():
199 def test_set_matplotlib_formats_kwargs():
202 from matplotlib.figure import Figure
200 from matplotlib.figure import Figure
203 ip = get_ipython()
201 ip = get_ipython()
204 cfg = _get_inline_config()
202 cfg = _get_inline_config()
205 cfg.print_figure_kwargs.update(dict(foo='bar'))
203 cfg.print_figure_kwargs.update(dict(foo='bar'))
206 kwargs = dict(dpi=150)
204 kwargs = dict(dpi=150)
207 with pytest.deprecated_call():
205 with pytest.deprecated_call():
208 display.set_matplotlib_formats("png", **kwargs)
206 display.set_matplotlib_formats("png", **kwargs)
209 formatter = ip.display_formatter.formatters["image/png"]
207 formatter = ip.display_formatter.formatters["image/png"]
210 f = formatter.lookup_by_type(Figure)
208 f = formatter.lookup_by_type(Figure)
211 formatter_kwargs = f.keywords
209 formatter_kwargs = f.keywords
212 expected = kwargs
210 expected = kwargs
213 expected["base64"] = True
211 expected["base64"] = True
214 expected["fmt"] = "png"
212 expected["fmt"] = "png"
215 expected.update(cfg.print_figure_kwargs)
213 expected.update(cfg.print_figure_kwargs)
216 assert formatter_kwargs == expected
214 assert formatter_kwargs == expected
217
215
218 def test_display_available():
216 def test_display_available():
219 """
217 """
220 Test that display is available without import
218 Test that display is available without import
221
219
222 We don't really care if it's in builtin or anything else, but it should
220 We don't really care if it's in builtin or anything else, but it should
223 always be available.
221 always be available.
224 """
222 """
225 ip = get_ipython()
223 ip = get_ipython()
226 with AssertNotPrints('NameError'):
224 with AssertNotPrints('NameError'):
227 ip.run_cell('display')
225 ip.run_cell('display')
228 try:
226 try:
229 ip.run_cell('del display')
227 ip.run_cell('del display')
230 except NameError:
228 except NameError:
231 pass # it's ok, it might be in builtins
229 pass # it's ok, it might be in builtins
232 # even if deleted it should be back
230 # even if deleted it should be back
233 with AssertNotPrints('NameError'):
231 with AssertNotPrints('NameError'):
234 ip.run_cell('display')
232 ip.run_cell('display')
235
233
236 def test_textdisplayobj_pretty_repr():
234 def test_textdisplayobj_pretty_repr():
237 p = display.Pretty("This is a simple test")
235 p = display.Pretty("This is a simple test")
238 assert repr(p) == "<IPython.core.display.Pretty object>"
236 assert repr(p) == "<IPython.core.display.Pretty object>"
239 assert p.data == "This is a simple test"
237 assert p.data == "This is a simple test"
240
238
241 p._show_mem_addr = True
239 p._show_mem_addr = True
242 assert repr(p) == object.__repr__(p)
240 assert repr(p) == object.__repr__(p)
243
241
244
242
245 def test_displayobject_repr():
243 def test_displayobject_repr():
246 h = display.HTML("<br />")
244 h = display.HTML("<br />")
247 assert repr(h) == "<IPython.core.display.HTML object>"
245 assert repr(h) == "<IPython.core.display.HTML object>"
248 h._show_mem_addr = True
246 h._show_mem_addr = True
249 assert repr(h) == object.__repr__(h)
247 assert repr(h) == object.__repr__(h)
250 h._show_mem_addr = False
248 h._show_mem_addr = False
251 assert repr(h) == "<IPython.core.display.HTML object>"
249 assert repr(h) == "<IPython.core.display.HTML object>"
252
250
253 j = display.Javascript("")
251 j = display.Javascript("")
254 assert repr(j) == "<IPython.core.display.Javascript object>"
252 assert repr(j) == "<IPython.core.display.Javascript object>"
255 j._show_mem_addr = True
253 j._show_mem_addr = True
256 assert repr(j) == object.__repr__(j)
254 assert repr(j) == object.__repr__(j)
257 j._show_mem_addr = False
255 j._show_mem_addr = False
258 assert repr(j) == "<IPython.core.display.Javascript object>"
256 assert repr(j) == "<IPython.core.display.Javascript object>"
259
257
260 @mock.patch('warnings.warn')
258 @mock.patch('warnings.warn')
261 def test_encourage_iframe_over_html(m_warn):
259 def test_encourage_iframe_over_html(m_warn):
262 display.HTML()
260 display.HTML()
263 m_warn.assert_not_called()
261 m_warn.assert_not_called()
264
262
265 display.HTML('<br />')
263 display.HTML('<br />')
266 m_warn.assert_not_called()
264 m_warn.assert_not_called()
267
265
268 display.HTML('<html><p>Lots of content here</p><iframe src="http://a.com"></iframe>')
266 display.HTML('<html><p>Lots of content here</p><iframe src="http://a.com"></iframe>')
269 m_warn.assert_not_called()
267 m_warn.assert_not_called()
270
268
271 display.HTML('<iframe src="http://a.com"></iframe>')
269 display.HTML('<iframe src="http://a.com"></iframe>')
272 m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
270 m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
273
271
274 m_warn.reset_mock()
272 m_warn.reset_mock()
275 display.HTML('<IFRAME SRC="http://a.com"></IFRAME>')
273 display.HTML('<IFRAME SRC="http://a.com"></IFRAME>')
276 m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
274 m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
277
275
278 def test_progress():
276 def test_progress():
279 p = display.ProgressBar(10)
277 p = display.ProgressBar(10)
280 assert "0/10" in repr(p)
278 assert "0/10" in repr(p)
281 p.html_width = "100%"
279 p.html_width = "100%"
282 p.progress = 5
280 p.progress = 5
283 assert (
281 assert (
284 p._repr_html_() == "<progress style='width:100%' max='10' value='5'></progress>"
282 p._repr_html_() == "<progress style='width:100%' max='10' value='5'></progress>"
285 )
283 )
286
284
287
285
288 def test_progress_iter():
286 def test_progress_iter():
289 with capture_output(display=False) as captured:
287 with capture_output(display=False) as captured:
290 for i in display.ProgressBar(5):
288 for i in display.ProgressBar(5):
291 out = captured.stdout
289 out = captured.stdout
292 assert "{0}/5".format(i) in out
290 assert "{0}/5".format(i) in out
293 out = captured.stdout
291 out = captured.stdout
294 assert "5/5" in out
292 assert "5/5" in out
295
293
296
294
297 def test_json():
295 def test_json():
298 d = {'a': 5}
296 d = {'a': 5}
299 lis = [d]
297 lis = [d]
300 metadata = [
298 metadata = [
301 {'expanded': False, 'root': 'root'},
299 {'expanded': False, 'root': 'root'},
302 {'expanded': True, 'root': 'root'},
300 {'expanded': True, 'root': 'root'},
303 {'expanded': False, 'root': 'custom'},
301 {'expanded': False, 'root': 'custom'},
304 {'expanded': True, 'root': 'custom'},
302 {'expanded': True, 'root': 'custom'},
305 ]
303 ]
306 json_objs = [
304 json_objs = [
307 display.JSON(d),
305 display.JSON(d),
308 display.JSON(d, expanded=True),
306 display.JSON(d, expanded=True),
309 display.JSON(d, root='custom'),
307 display.JSON(d, root='custom'),
310 display.JSON(d, expanded=True, root='custom'),
308 display.JSON(d, expanded=True, root='custom'),
311 ]
309 ]
312 for j, md in zip(json_objs, metadata):
310 for j, md in zip(json_objs, metadata):
313 assert j._repr_json_() == (d, md)
311 assert j._repr_json_() == (d, md)
314
312
315 with warnings.catch_warnings(record=True) as w:
313 with warnings.catch_warnings(record=True) as w:
316 warnings.simplefilter("always")
314 warnings.simplefilter("always")
317 j = display.JSON(json.dumps(d))
315 j = display.JSON(json.dumps(d))
318 assert len(w) == 1
316 assert len(w) == 1
319 assert j._repr_json_() == (d, metadata[0])
317 assert j._repr_json_() == (d, metadata[0])
320
318
321 json_objs = [
319 json_objs = [
322 display.JSON(lis),
320 display.JSON(lis),
323 display.JSON(lis, expanded=True),
321 display.JSON(lis, expanded=True),
324 display.JSON(lis, root='custom'),
322 display.JSON(lis, root='custom'),
325 display.JSON(lis, expanded=True, root='custom'),
323 display.JSON(lis, expanded=True, root='custom'),
326 ]
324 ]
327 for j, md in zip(json_objs, metadata):
325 for j, md in zip(json_objs, metadata):
328 assert j._repr_json_() == (lis, md)
326 assert j._repr_json_() == (lis, md)
329
327
330 with warnings.catch_warnings(record=True) as w:
328 with warnings.catch_warnings(record=True) as w:
331 warnings.simplefilter("always")
329 warnings.simplefilter("always")
332 j = display.JSON(json.dumps(lis))
330 j = display.JSON(json.dumps(lis))
333 assert len(w) == 1
331 assert len(w) == 1
334 assert j._repr_json_() == (lis, metadata[0])
332 assert j._repr_json_() == (lis, metadata[0])
335
333
336
334
337 def test_video_embedding():
335 def test_video_embedding():
338 """use a tempfile, with dummy-data, to ensure that video embedding doesn't crash"""
336 """use a tempfile, with dummy-data, to ensure that video embedding doesn't crash"""
339 v = display.Video("http://ignored")
337 v = display.Video("http://ignored")
340 assert not v.embed
338 assert not v.embed
341 html = v._repr_html_()
339 html = v._repr_html_()
342 assert 'src="data:' not in html
340 assert 'src="data:' not in html
343 assert 'src="http://ignored"' in html
341 assert 'src="http://ignored"' in html
344
342
345 with pytest.raises(ValueError):
343 with pytest.raises(ValueError):
346 v = display.Video(b'abc')
344 v = display.Video(b'abc')
347
345
348 with NamedFileInTemporaryDirectory('test.mp4') as f:
346 with NamedFileInTemporaryDirectory('test.mp4') as f:
349 f.write(b'abc')
347 f.write(b'abc')
350 f.close()
348 f.close()
351
349
352 v = display.Video(f.name)
350 v = display.Video(f.name)
353 assert not v.embed
351 assert not v.embed
354 html = v._repr_html_()
352 html = v._repr_html_()
355 assert 'src="data:' not in html
353 assert 'src="data:' not in html
356
354
357 v = display.Video(f.name, embed=True)
355 v = display.Video(f.name, embed=True)
358 html = v._repr_html_()
356 html = v._repr_html_()
359 assert 'src="data:video/mp4;base64,YWJj"' in html
357 assert 'src="data:video/mp4;base64,YWJj"' in html
360
358
361 v = display.Video(f.name, embed=True, mimetype='video/other')
359 v = display.Video(f.name, embed=True, mimetype='video/other')
362 html = v._repr_html_()
360 html = v._repr_html_()
363 assert 'src="data:video/other;base64,YWJj"' in html
361 assert 'src="data:video/other;base64,YWJj"' in html
364
362
365 v = display.Video(b'abc', embed=True, mimetype='video/mp4')
363 v = display.Video(b'abc', embed=True, mimetype='video/mp4')
366 html = v._repr_html_()
364 html = v._repr_html_()
367 assert 'src="data:video/mp4;base64,YWJj"' in html
365 assert 'src="data:video/mp4;base64,YWJj"' in html
368
366
369 v = display.Video(u'YWJj', embed=True, mimetype='video/xyz')
367 v = display.Video(u'YWJj', embed=True, mimetype='video/xyz')
370 html = v._repr_html_()
368 html = v._repr_html_()
371 assert 'src="data:video/xyz;base64,YWJj"' in html
369 assert 'src="data:video/xyz;base64,YWJj"' in html
372
370
373 def test_html_metadata():
371 def test_html_metadata():
374 s = "<h1>Test</h1>"
372 s = "<h1>Test</h1>"
375 h = display.HTML(s, metadata={"isolated": True})
373 h = display.HTML(s, metadata={"isolated": True})
376 assert h._repr_html_() == (s, {"isolated": True})
374 assert h._repr_html_() == (s, {"isolated": True})
377
375
378
376
379 def test_display_id():
377 def test_display_id():
380 ip = get_ipython()
378 ip = get_ipython()
381 with mock.patch.object(ip.display_pub, 'publish') as pub:
379 with mock.patch.object(ip.display_pub, 'publish') as pub:
382 handle = display.display('x')
380 handle = display.display('x')
383 assert handle is None
381 assert handle is None
384 handle = display.display('y', display_id='secret')
382 handle = display.display('y', display_id='secret')
385 assert isinstance(handle, display.DisplayHandle)
383 assert isinstance(handle, display.DisplayHandle)
386 handle2 = display.display('z', display_id=True)
384 handle2 = display.display('z', display_id=True)
387 assert isinstance(handle2, display.DisplayHandle)
385 assert isinstance(handle2, display.DisplayHandle)
388 assert handle.display_id != handle2.display_id
386 assert handle.display_id != handle2.display_id
389
387
390 assert pub.call_count == 3
388 assert pub.call_count == 3
391 args, kwargs = pub.call_args_list[0]
389 args, kwargs = pub.call_args_list[0]
392 assert args == ()
390 assert args == ()
393 assert kwargs == {
391 assert kwargs == {
394 'data': {
392 'data': {
395 'text/plain': repr('x')
393 'text/plain': repr('x')
396 },
394 },
397 'metadata': {},
395 'metadata': {},
398 }
396 }
399 args, kwargs = pub.call_args_list[1]
397 args, kwargs = pub.call_args_list[1]
400 assert args == ()
398 assert args == ()
401 assert kwargs == {
399 assert kwargs == {
402 'data': {
400 'data': {
403 'text/plain': repr('y')
401 'text/plain': repr('y')
404 },
402 },
405 'metadata': {},
403 'metadata': {},
406 'transient': {
404 'transient': {
407 'display_id': handle.display_id,
405 'display_id': handle.display_id,
408 },
406 },
409 }
407 }
410 args, kwargs = pub.call_args_list[2]
408 args, kwargs = pub.call_args_list[2]
411 assert args == ()
409 assert args == ()
412 assert kwargs == {
410 assert kwargs == {
413 'data': {
411 'data': {
414 'text/plain': repr('z')
412 'text/plain': repr('z')
415 },
413 },
416 'metadata': {},
414 'metadata': {},
417 'transient': {
415 'transient': {
418 'display_id': handle2.display_id,
416 'display_id': handle2.display_id,
419 },
417 },
420 }
418 }
421
419
422
420
423 def test_update_display():
421 def test_update_display():
424 ip = get_ipython()
422 ip = get_ipython()
425 with mock.patch.object(ip.display_pub, 'publish') as pub:
423 with mock.patch.object(ip.display_pub, 'publish') as pub:
426 with pytest.raises(TypeError):
424 with pytest.raises(TypeError):
427 display.update_display('x')
425 display.update_display('x')
428 display.update_display('x', display_id='1')
426 display.update_display('x', display_id='1')
429 display.update_display('y', display_id='2')
427 display.update_display('y', display_id='2')
430 args, kwargs = pub.call_args_list[0]
428 args, kwargs = pub.call_args_list[0]
431 assert args == ()
429 assert args == ()
432 assert kwargs == {
430 assert kwargs == {
433 'data': {
431 'data': {
434 'text/plain': repr('x')
432 'text/plain': repr('x')
435 },
433 },
436 'metadata': {},
434 'metadata': {},
437 'transient': {
435 'transient': {
438 'display_id': '1',
436 'display_id': '1',
439 },
437 },
440 'update': True,
438 'update': True,
441 }
439 }
442 args, kwargs = pub.call_args_list[1]
440 args, kwargs = pub.call_args_list[1]
443 assert args == ()
441 assert args == ()
444 assert kwargs == {
442 assert kwargs == {
445 'data': {
443 'data': {
446 'text/plain': repr('y')
444 'text/plain': repr('y')
447 },
445 },
448 'metadata': {},
446 'metadata': {},
449 'transient': {
447 'transient': {
450 'display_id': '2',
448 'display_id': '2',
451 },
449 },
452 'update': True,
450 'update': True,
453 }
451 }
454
452
455
453
456 def test_display_handle():
454 def test_display_handle():
457 ip = get_ipython()
455 ip = get_ipython()
458 handle = display.DisplayHandle()
456 handle = display.DisplayHandle()
459 assert isinstance(handle.display_id, str)
457 assert isinstance(handle.display_id, str)
460 handle = display.DisplayHandle("my-id")
458 handle = display.DisplayHandle("my-id")
461 assert handle.display_id == "my-id"
459 assert handle.display_id == "my-id"
462 with mock.patch.object(ip.display_pub, "publish") as pub:
460 with mock.patch.object(ip.display_pub, "publish") as pub:
463 handle.display("x")
461 handle.display("x")
464 handle.update("y")
462 handle.update("y")
465
463
466 args, kwargs = pub.call_args_list[0]
464 args, kwargs = pub.call_args_list[0]
467 assert args == ()
465 assert args == ()
468 assert kwargs == {
466 assert kwargs == {
469 'data': {
467 'data': {
470 'text/plain': repr('x')
468 'text/plain': repr('x')
471 },
469 },
472 'metadata': {},
470 'metadata': {},
473 'transient': {
471 'transient': {
474 'display_id': handle.display_id,
472 'display_id': handle.display_id,
475 }
473 }
476 }
474 }
477 args, kwargs = pub.call_args_list[1]
475 args, kwargs = pub.call_args_list[1]
478 assert args == ()
476 assert args == ()
479 assert kwargs == {
477 assert kwargs == {
480 'data': {
478 'data': {
481 'text/plain': repr('y')
479 'text/plain': repr('y')
482 },
480 },
483 'metadata': {},
481 'metadata': {},
484 'transient': {
482 'transient': {
485 'display_id': handle.display_id,
483 'display_id': handle.display_id,
486 },
484 },
487 'update': True,
485 'update': True,
488 }
486 }
489
487
490
488
491 def test_image_alt_tag():
489 def test_image_alt_tag():
492 """Simple test for display.Image(args, alt=x,)"""
490 """Simple test for display.Image(args, alt=x,)"""
493 thisurl = "http://example.com/image.png"
491 thisurl = "http://example.com/image.png"
494 img = display.Image(url=thisurl, alt="an image")
492 img = display.Image(url=thisurl, alt="an image")
495 assert '<img src="%s" alt="an image"/>' % (thisurl) == img._repr_html_()
493 assert '<img src="%s" alt="an image"/>' % (thisurl) == img._repr_html_()
496 img = display.Image(url=thisurl, unconfined=True, alt="an image")
494 img = display.Image(url=thisurl, unconfined=True, alt="an image")
497 assert (
495 assert (
498 '<img src="%s" class="unconfined" alt="an image"/>' % (thisurl)
496 '<img src="%s" class="unconfined" alt="an image"/>' % (thisurl)
499 == img._repr_html_()
497 == img._repr_html_()
500 )
498 )
501 img = display.Image(url=thisurl, alt='>"& <')
499 img = display.Image(url=thisurl, alt='>"& <')
502 assert '<img src="%s" alt="&gt;&quot;&amp; &lt;"/>' % (thisurl) == img._repr_html_()
500 assert '<img src="%s" alt="&gt;&quot;&amp; &lt;"/>' % (thisurl) == img._repr_html_()
503
501
504 img = display.Image(url=thisurl, metadata={"alt": "an image"})
502 img = display.Image(url=thisurl, metadata={"alt": "an image"})
505 assert img.alt == "an image"
503 assert img.alt == "an image"
506 here = os.path.dirname(__file__)
504 here = os.path.dirname(__file__)
507 img = display.Image(os.path.join(here, "2x2.png"), alt="an image")
505 img = display.Image(os.path.join(here, "2x2.png"), alt="an image")
508 assert img.alt == "an image"
506 assert img.alt == "an image"
509 _, md = img._repr_png_()
507 _, md = img._repr_png_()
510 assert md["alt"] == "an image"
508 assert md["alt"] == "an image"
511
509
512
510
513 def test_image_bad_filename_raises_proper_exception():
511 def test_image_bad_filename_raises_proper_exception():
514 with pytest.raises(FileNotFoundError):
512 with pytest.raises(FileNotFoundError):
515 display.Image("/this/file/does/not/exist/")._repr_png_()
513 display.Image("/this/file/does/not/exist/")._repr_png_()
@@ -1,280 +1,279
1 #!/usr/bin/env python3
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 """Setup script for IPython.
3 """Setup script for IPython.
4
4
5 Under Posix environments it works like a typical setup.py script.
5 Under Posix environments it works like a typical setup.py script.
6 Under Windows, the command sdist is not supported, since IPython
6 Under Windows, the command sdist is not supported, since IPython
7 requires utilities which are not available under Windows."""
7 requires utilities which are not available under Windows."""
8
8
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10 # Copyright (c) 2008-2011, IPython Development Team.
10 # Copyright (c) 2008-2011, IPython Development Team.
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.rst, distributed with this software.
17 # The full license is in the file COPYING.rst, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 import os
20 import os
21 import sys
21 import sys
22 from pathlib import Path
22 from pathlib import Path
23
23
24 # **Python version check**
24 # **Python version check**
25 #
25 #
26 # This check is also made in IPython/__init__, don't forget to update both when
26 # This check is also made in IPython/__init__, don't forget to update both when
27 # changing Python version requirements.
27 # changing Python version requirements.
28 if sys.version_info < (3, 7):
28 if sys.version_info < (3, 7):
29 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
29 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
30 try:
30 try:
31 import pip
31 import pip
32 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
32 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
33 if pip_version < (9, 0, 1) :
33 if pip_version < (9, 0, 1) :
34 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
34 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
35 'pip {} detected.'.format(pip.__version__)
35 'pip {} detected.'.format(pip.__version__)
36 else:
36 else:
37 # pip is new enough - it must be something else
37 # pip is new enough - it must be something else
38 pip_message = ''
38 pip_message = ''
39 except Exception:
39 except Exception:
40 pass
40 pass
41
41
42
42
43 error = """
43 error = """
44 IPython 7.17+ supports Python 3.7 and above, following NEP 29.
44 IPython 7.17+ supports Python 3.7 and above, following NEP 29.
45 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
45 When using Python 2.7, please install IPython 5.x LTS Long Term Support version.
46 Python 3.3 and 3.4 were supported up to IPython 6.x.
46 Python 3.3 and 3.4 were supported up to IPython 6.x.
47 Python 3.5 was supported with IPython 7.0 to 7.9.
47 Python 3.5 was supported with IPython 7.0 to 7.9.
48 Python 3.6 was supported with IPython up to 7.16.
48 Python 3.6 was supported with IPython up to 7.16.
49
49
50 See IPython `README.rst` file for more information:
50 See IPython `README.rst` file for more information:
51
51
52 https://github.com/ipython/ipython/blob/master/README.rst
52 https://github.com/ipython/ipython/blob/master/README.rst
53
53
54 Python {py} detected.
54 Python {py} detected.
55 {pip}
55 {pip}
56 """.format(py=sys.version_info, pip=pip_message )
56 """.format(py=sys.version_info, pip=pip_message )
57
57
58 print(error, file=sys.stderr)
58 print(error, file=sys.stderr)
59 sys.exit(1)
59 sys.exit(1)
60
60
61 # At least we're on the python version we need, move on.
61 # At least we're on the python version we need, move on.
62
62
63 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
63 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
64 # update it when the contents of directories change.
64 # update it when the contents of directories change.
65 if Path("MANIFEST").exists():
65 if Path("MANIFEST").exists():
66 Path("MANIFEST").unlink()
66 Path("MANIFEST").unlink()
67
67
68 from distutils.core import setup
68 from distutils.core import setup
69
69
70 # Our own imports
70 # Our own imports
71 from setupbase import target_update
71 from setupbase import target_update
72
72
73 from setupbase import (
73 from setupbase import (
74 setup_args,
74 setup_args,
75 find_packages,
75 find_packages,
76 find_package_data,
76 find_package_data,
77 check_package_data_first,
77 check_package_data_first,
78 find_entry_points,
78 find_entry_points,
79 build_scripts_entrypt,
79 build_scripts_entrypt,
80 find_data_files,
80 find_data_files,
81 git_prebuild,
81 git_prebuild,
82 install_symlinked,
82 install_symlinked,
83 install_lib_symlink,
83 install_lib_symlink,
84 install_scripts_for_symlink,
84 install_scripts_for_symlink,
85 unsymlink,
85 unsymlink,
86 )
86 )
87
87
88 #-------------------------------------------------------------------------------
88 #-------------------------------------------------------------------------------
89 # Handle OS specific things
89 # Handle OS specific things
90 #-------------------------------------------------------------------------------
90 #-------------------------------------------------------------------------------
91
91
92 if os.name in ('nt','dos'):
92 if os.name in ('nt','dos'):
93 os_name = 'windows'
93 os_name = 'windows'
94 else:
94 else:
95 os_name = os.name
95 os_name = os.name
96
96
97 # Under Windows, 'sdist' has not been supported. Now that the docs build with
97 # Under Windows, 'sdist' has not been supported. Now that the docs build with
98 # Sphinx it might work, but let's not turn it on until someone confirms that it
98 # Sphinx it might work, but let's not turn it on until someone confirms that it
99 # actually works.
99 # actually works.
100 if os_name == 'windows' and 'sdist' in sys.argv:
100 if os_name == 'windows' and 'sdist' in sys.argv:
101 print('The sdist command is not available under Windows. Exiting.')
101 print('The sdist command is not available under Windows. Exiting.')
102 sys.exit(1)
102 sys.exit(1)
103
103
104
104
105 #-------------------------------------------------------------------------------
105 #-------------------------------------------------------------------------------
106 # Things related to the IPython documentation
106 # Things related to the IPython documentation
107 #-------------------------------------------------------------------------------
107 #-------------------------------------------------------------------------------
108
108
109 # update the manuals when building a source dist
109 # update the manuals when building a source dist
110 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
110 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
111
111
112 # List of things to be updated. Each entry is a triplet of args for
112 # List of things to be updated. Each entry is a triplet of args for
113 # target_update()
113 # target_update()
114 to_update = [
114 to_update = [
115 ('docs/man/ipython.1.gz',
115 ('docs/man/ipython.1.gz',
116 ['docs/man/ipython.1'],
116 ['docs/man/ipython.1'],
117 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
117 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
118 ]
118 ]
119
119
120
120
121 [ target_update(*t) for t in to_update ]
121 [ target_update(*t) for t in to_update ]
122
122
123 #---------------------------------------------------------------------------
123 #---------------------------------------------------------------------------
124 # Find all the packages, package data, and data_files
124 # Find all the packages, package data, and data_files
125 #---------------------------------------------------------------------------
125 #---------------------------------------------------------------------------
126
126
127 packages = find_packages()
127 packages = find_packages()
128 package_data = find_package_data()
128 package_data = find_package_data()
129
129
130 data_files = find_data_files()
130 data_files = find_data_files()
131
131
132 setup_args['packages'] = packages
132 setup_args['packages'] = packages
133 setup_args['package_data'] = package_data
133 setup_args['package_data'] = package_data
134 setup_args['data_files'] = data_files
134 setup_args['data_files'] = data_files
135
135
136 #---------------------------------------------------------------------------
136 #---------------------------------------------------------------------------
137 # custom distutils commands
137 # custom distutils commands
138 #---------------------------------------------------------------------------
138 #---------------------------------------------------------------------------
139 # imports here, so they are after setuptools import if there was one
139 # imports here, so they are after setuptools import if there was one
140 from distutils.command.sdist import sdist
140 from distutils.command.sdist import sdist
141
141
142 setup_args['cmdclass'] = {
142 setup_args['cmdclass'] = {
143 'build_py': \
143 'build_py': \
144 check_package_data_first(git_prebuild('IPython')),
144 check_package_data_first(git_prebuild('IPython')),
145 'sdist' : git_prebuild('IPython', sdist),
145 'sdist' : git_prebuild('IPython', sdist),
146 'symlink': install_symlinked,
146 'symlink': install_symlinked,
147 'install_lib_symlink': install_lib_symlink,
147 'install_lib_symlink': install_lib_symlink,
148 'install_scripts_sym': install_scripts_for_symlink,
148 'install_scripts_sym': install_scripts_for_symlink,
149 'unsymlink': unsymlink,
149 'unsymlink': unsymlink,
150 }
150 }
151
151
152
152
153 #---------------------------------------------------------------------------
153 #---------------------------------------------------------------------------
154 # Handle scripts, dependencies, and setuptools specific things
154 # Handle scripts, dependencies, and setuptools specific things
155 #---------------------------------------------------------------------------
155 #---------------------------------------------------------------------------
156
156
157 # For some commands, use setuptools. Note that we do NOT list install here!
157 # For some commands, use setuptools. Note that we do NOT list install here!
158 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
158 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
159 needs_setuptools = {'develop', 'release', 'bdist_egg', 'bdist_rpm',
159 needs_setuptools = {'develop', 'release', 'bdist_egg', 'bdist_rpm',
160 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
160 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
161 'egg_info', 'easy_install', 'upload', 'install_egg_info',
161 'egg_info', 'easy_install', 'upload', 'install_egg_info',
162 }
162 }
163
163
164 if len(needs_setuptools.intersection(sys.argv)) > 0:
164 if len(needs_setuptools.intersection(sys.argv)) > 0:
165 import setuptools
165 import setuptools
166
166
167 # This dict is used for passing extra arguments that are setuptools
167 # This dict is used for passing extra arguments that are setuptools
168 # specific to setup
168 # specific to setup
169 setuptools_extra_args = {}
169 setuptools_extra_args = {}
170
170
171 # setuptools requirements
171 # setuptools requirements
172
172
173 extras_require = dict(
173 extras_require = dict(
174 parallel=["ipyparallel"],
174 parallel=["ipyparallel"],
175 qtconsole=["qtconsole"],
175 qtconsole=["qtconsole"],
176 doc=["Sphinx>=1.3"],
176 doc=["Sphinx>=1.3"],
177 test=[
177 test=[
178 "pytest",
178 "pytest",
179 "testpath",
179 "testpath",
180 "pygments",
180 "pygments",
181 ],
181 ],
182 test_extra=[
182 test_extra=[
183 "pytest",
183 "pytest",
184 "testpath",
184 "testpath",
185 "curio",
185 "curio",
186 "matplotlib!=3.2.0",
186 "matplotlib!=3.2.0",
187 "nbformat",
187 "nbformat",
188 "ipykernel",
189 "numpy>=1.17",
188 "numpy>=1.17",
190 "pandas",
189 "pandas",
191 "pygments",
190 "pygments",
192 "trio",
191 "trio",
193 ],
192 ],
194 terminal=[],
193 terminal=[],
195 kernel=["ipykernel"],
194 kernel=["ipykernel"],
196 nbformat=["nbformat"],
195 nbformat=["nbformat"],
197 notebook=["notebook", "ipywidgets"],
196 notebook=["notebook", "ipywidgets"],
198 nbconvert=["nbconvert"],
197 nbconvert=["nbconvert"],
199 )
198 )
200
199
201 install_requires = [
200 install_requires = [
202 "setuptools>=18.5",
201 "setuptools>=18.5",
203 "jedi>=0.16",
202 "jedi>=0.16",
204 "decorator",
203 "decorator",
205 "pickleshare",
204 "pickleshare",
206 "traitlets>=4.2",
205 "traitlets>=4.2",
207 "prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1",
206 "prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1",
208 "pygments",
207 "pygments",
209 "backcall",
208 "backcall",
210 "stack_data",
209 "stack_data",
211 "matplotlib-inline",
210 "matplotlib-inline",
212 ]
211 ]
213
212
214 # Platform-specific dependencies:
213 # Platform-specific dependencies:
215 # This is the correct way to specify these,
214 # This is the correct way to specify these,
216 # but requires pip >= 6. pip < 6 ignores these.
215 # but requires pip >= 6. pip < 6 ignores these.
217
216
218 extras_require.update(
217 extras_require.update(
219 {
218 {
220 ':sys_platform != "win32"': ["pexpect>4.3"],
219 ':sys_platform != "win32"': ["pexpect>4.3"],
221 ':sys_platform == "darwin"': ["appnope"],
220 ':sys_platform == "darwin"': ["appnope"],
222 ':sys_platform == "win32"': ["colorama"],
221 ':sys_platform == "win32"': ["colorama"],
223 }
222 }
224 )
223 )
225 # FIXME: re-specify above platform dependencies for pip < 6
224 # FIXME: re-specify above platform dependencies for pip < 6
226 # These would result in non-portable bdists.
225 # These would result in non-portable bdists.
227 if not any(arg.startswith('bdist') for arg in sys.argv):
226 if not any(arg.startswith('bdist') for arg in sys.argv):
228 if sys.platform == 'darwin':
227 if sys.platform == 'darwin':
229 install_requires.extend(['appnope'])
228 install_requires.extend(['appnope'])
230
229
231 if not sys.platform.startswith("win"):
230 if not sys.platform.startswith("win"):
232 install_requires.append("pexpect>4.3")
231 install_requires.append("pexpect>4.3")
233
232
234 # workaround pypa/setuptools#147, where setuptools misspells
233 # workaround pypa/setuptools#147, where setuptools misspells
235 # platform_python_implementation as python_implementation
234 # platform_python_implementation as python_implementation
236 if 'setuptools' in sys.modules:
235 if 'setuptools' in sys.modules:
237 for key in list(extras_require):
236 for key in list(extras_require):
238 if 'platform_python_implementation' in key:
237 if 'platform_python_implementation' in key:
239 new_key = key.replace('platform_python_implementation', 'python_implementation')
238 new_key = key.replace('platform_python_implementation', 'python_implementation')
240 extras_require[new_key] = extras_require.pop(key)
239 extras_require[new_key] = extras_require.pop(key)
241
240
242 everything = set()
241 everything = set()
243 for key, deps in extras_require.items():
242 for key, deps in extras_require.items():
244 if ':' not in key:
243 if ':' not in key:
245 everything.update(deps)
244 everything.update(deps)
246 extras_require['all'] = list(sorted(everything))
245 extras_require['all'] = list(sorted(everything))
247
246
248 if 'setuptools' in sys.modules:
247 if 'setuptools' in sys.modules:
249 setuptools_extra_args['python_requires'] = '>=3.7'
248 setuptools_extra_args['python_requires'] = '>=3.7'
250 setuptools_extra_args['zip_safe'] = False
249 setuptools_extra_args['zip_safe'] = False
251 setuptools_extra_args['entry_points'] = {
250 setuptools_extra_args['entry_points'] = {
252 'console_scripts': find_entry_points(),
251 'console_scripts': find_entry_points(),
253 'pygments.lexers': [
252 'pygments.lexers': [
254 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
253 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
255 'ipython = IPython.lib.lexers:IPythonLexer',
254 'ipython = IPython.lib.lexers:IPythonLexer',
256 'ipython3 = IPython.lib.lexers:IPython3Lexer',
255 'ipython3 = IPython.lib.lexers:IPython3Lexer',
257 ],
256 ],
258 }
257 }
259 setup_args['extras_require'] = extras_require
258 setup_args['extras_require'] = extras_require
260 setup_args['install_requires'] = install_requires
259 setup_args['install_requires'] = install_requires
261
260
262 else:
261 else:
263 # scripts has to be a non-empty list, or install_scripts isn't called
262 # scripts has to be a non-empty list, or install_scripts isn't called
264 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
263 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
265
264
266 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
265 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
267
266
268 #---------------------------------------------------------------------------
267 #---------------------------------------------------------------------------
269 # Do the actual setup now
268 # Do the actual setup now
270 #---------------------------------------------------------------------------
269 #---------------------------------------------------------------------------
271
270
272 setup_args.update(setuptools_extra_args)
271 setup_args.update(setuptools_extra_args)
273
272
274
273
275
274
276 def main():
275 def main():
277 setup(**setup_args)
276 setup(**setup_args)
278
277
279 if __name__ == '__main__':
278 if __name__ == '__main__':
280 main()
279 main()
General Comments 0
You need to be logged in to leave comments. Login now