##// END OF EJS Templates
Merge pull request #9200 from Carreau/rc2...
Matthias Bussonnier -
r22044:2b851fe3 merge
parent child Browse files
Show More
@@ -1,39 +1,23 b''
1 =====================
1 =====================
2 Development version
2 Development version
3 =====================
3 =====================
4
4
5 This document describes in-flight development work.
5 This document describes in-flight development work.
6
6
7 .. warning::
7 .. warning::
8
8
9 Please do not edit this file by hand (doing so will likely cause merge
9 Please do not edit this file by hand (doing so will likely cause merge
10 conflicts for other Pull Requests). Instead, create a new file in the
10 conflicts for other Pull Requests). Instead, create a new file in the
11 `docs/source/whatsnew/pr` folder
11 `docs/source/whatsnew/pr` folder
12
12
13
13
14 IPython debugger (IPdb) now supports the number of context lines for the
15 ``where`` (and ``w``) commands. The `context` keyword is also available in various APIs.
16 See PR :ghpull:`9097`
17
14
18 YouTube video will now show thumbnail when exported to a media that do not support video. (:ghpull:`9086`)
19
20 Add warning when running `ipython <subcommand>` when subcommand is deprecated. `jupyter` should now be used.
21
22 Code in `%pinfo` (also known as `??`) are now highlighter (:ghpull:`8947`)
23
24 `%aimport` now support module completion. (:ghpull:`8884`)
25
26 `ipdb` output is now colored ! (:ghpull:`8842`)
27
28 Add ability to transpose columns for completion: (:ghpull:`8748`)
29
30 Many many docs improvements and bug fixes, you can see the list of changes [add link to GitHub diff]
31
15
32 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
16 .. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT.
33
17
34
18
35 Backwards incompatible changes
19 Backwards incompatible changes
36 ------------------------------
20 ------------------------------
37
21
38
22
39 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT. No newline at end of file
23 .. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT.
@@ -1,46 +1,69 b''
1 ============
1 ============
2 4.x Series
2 4.x Series
3 ============
3 ============
4
4
5
6 IPython 4.1
7 ===========
8
9 Release February, 2016. IPython 4.1 contain mostly bug fixes. It though contain
10 a few improvement.
11
12
13 - IPython debugger (IPdb) now supports the number of context lines for the
14 ``where`` (and ``w``) commands. The `context` keyword is also available in
15 various APIs. See PR :ghpull:`9097`
16 - YouTube video will now show thumbnail when exported to a media that do not
17 support video. (:ghpull:`9086`)
18 - Add warning when running `ipython <subcommand>` when subcommand is
19 deprecated. `jupyter` should now be used.
20 - Code in `%pinfo` (also known as `??`) are now highlighter (:ghpull:`8947`)
21 - `%aimport` now support module completion. (:ghpull:`8884`)
22 - `ipdb` output is now colored ! (:ghpull:`8842`)
23 - Add ability to transpose columns for completion: (:ghpull:`8748`)
24
25 Many many docs improvements and bug fixes, you can see the
26 `list of changes <https://github.com/ipython/ipython/compare/4.0.0...4.1.0>`_
27
5 IPython 4.0
28 IPython 4.0
6 ===========
29 ===========
7
30
8 Released August, 2015
31 Released August, 2015
9
32
10 IPython 4.0 is the first major release after the Big Split.
33 IPython 4.0 is the first major release after the Big Split.
11 IPython no longer contains the notebook, qtconsole, etc. which have moved to
34 IPython no longer contains the notebook, qtconsole, etc. which have moved to
12 `jupyter <https://jupyter.readthedocs.org>`_.
35 `jupyter <https://jupyter.readthedocs.org>`_.
13 IPython subprojects, such as `IPython.parallel <https://ipyparallel.readthedocs.org>`_ and `widgets <https://ipywidgets.readthedocs.org>`_ have moved to their own repos as well.
36 IPython subprojects, such as `IPython.parallel <https://ipyparallel.readthedocs.org>`_ and `widgets <https://ipywidgets.readthedocs.org>`_ have moved to their own repos as well.
14
37
15 The following subpackages are deprecated:
38 The following subpackages are deprecated:
16
39
17 - IPython.kernel (now jupyter_client and ipykernel)
40 - IPython.kernel (now jupyter_client and ipykernel)
18 - IPython.consoleapp (now jupyter_client.consoleapp)
41 - IPython.consoleapp (now jupyter_client.consoleapp)
19 - IPython.nbformat (now nbformat)
42 - IPython.nbformat (now nbformat)
20 - IPython.nbconvert (now nbconvert)
43 - IPython.nbconvert (now nbconvert)
21 - IPython.html (now notebook)
44 - IPython.html (now notebook)
22 - IPython.parallel (now ipyparallel)
45 - IPython.parallel (now ipyparallel)
23 - IPython.utils.traitlets (now traitlets)
46 - IPython.utils.traitlets (now traitlets)
24 - IPython.config (now traitlets.config)
47 - IPython.config (now traitlets.config)
25 - IPython.qt (now qtconsole)
48 - IPython.qt (now qtconsole)
26 - IPython.terminal.console (now jupyter_console)
49 - IPython.terminal.console (now jupyter_console)
27
50
28 and a few other utilities.
51 and a few other utilities.
29
52
30 Shims for the deprecated subpackages have been added,
53 Shims for the deprecated subpackages have been added,
31 so existing code should continue to work with a warning about the new home.
54 so existing code should continue to work with a warning about the new home.
32
55
33 There are few changes to the code beyond the reorganization and some bugfixes.
56 There are few changes to the code beyond the reorganization and some bugfixes.
34
57
35 IPython highlights:
58 IPython highlights:
36
59
37 - Public APIs for discovering IPython paths is moved from :mod:`IPython.utils.path` to :mod:`IPython.paths`.
60 - Public APIs for discovering IPython paths is moved from :mod:`IPython.utils.path` to :mod:`IPython.paths`.
38 The old function locations continue to work with deprecation warnings.
61 The old function locations continue to work with deprecation warnings.
39 - Code raising ``DeprecationWarning``
62 - Code raising ``DeprecationWarning``
40 entered by the user in an interactive session will now display the warning by
63 entered by the user in an interactive session will now display the warning by
41 default. See :ghpull:`8480` an :ghissue:`8478`.
64 default. See :ghpull:`8480` an :ghissue:`8478`.
42 - The `--deep-reload` flag and the corresponding options to inject `dreload` or
65 - The `--deep-reload` flag and the corresponding options to inject `dreload` or
43 `reload` into the interactive namespace have been deprecated, and will be
66 `reload` into the interactive namespace have been deprecated, and will be
44 removed in future versions. You should now explicitly import `reload` from
67 removed in future versions. You should now explicitly import `reload` from
45 `IPython.lib.deepreload` to use it.
68 `IPython.lib.deepreload` to use it.
46
69
@@ -1,28 +1,32 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """IPython release build script.
2 """IPython release build script.
3 """
3 """
4
5 import os
4 import os
6 from shutil import rmtree
5 from shutil import rmtree
7
6
8 from toollib import sh, pjoin, get_ipdir, cd, compile_tree, execfile, sdists, wheels
7 from toollib import sh, pjoin, get_ipdir, cd, compile_tree, execfile, sdists, buildwheels
8
9 def build_release():
10
11 # Get main ipython dir, this will raise if it doesn't pass some checks
12 ipdir = get_ipdir()
13 cd(ipdir)
9
14
10 # Get main ipython dir, this will raise if it doesn't pass some checks
15 # Load release info
11 ipdir = get_ipdir()
16 execfile(pjoin('IPython', 'core', 'release.py'), globals())
12 cd(ipdir)
13
17
14 # Load release info
18 # Check that everything compiles
15 execfile(pjoin('IPython', 'core', 'release.py'), globals())
19 compile_tree('*')
16
20
17 # Check that everything compiles
21 # Cleanup
18 compile_tree('*')
22 for d in ['build', 'dist', pjoin('docs', 'build'), pjoin('docs', 'dist'),
23 pjoin('docs', 'source', 'api', 'generated')]:
24 if os.path.isdir(d):
25 rmtree(d)
19
26
20 # Cleanup
27 # Build source and binary distros
21 for d in ['build', 'dist', pjoin('docs', 'build'), pjoin('docs', 'dist'),
28 sh(sdists)
22 pjoin('docs', 'source', 'api', 'generated')]:
29 buildwheels()
23 if os.path.isdir(d):
24 rmtree(d)
25
30
26 # Build source and binary distros
31 if __name__ == '__main__':
27 sh(sdists)
32 build_release()
28 sh(wheels)
@@ -1,88 +1,88 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """IPython release script.
2 """IPython release script.
3
3
4 This should ONLY be run at real release time.
4 This should ONLY be run at real release time.
5 """
5 """
6 from __future__ import print_function
6 from __future__ import print_function
7
7
8 import os
8 import os
9 import sys
9 import sys
10
10
11 from toollib import (get_ipdir, pjoin, cd, execfile, sh, archive,
11 from toollib import (get_ipdir, pjoin, cd, execfile, sh, archive,
12 sdists, archive_user, archive_dir)
12 sdists, archive_user, archive_dir, buildwheels)
13 from gh_api import post_download
13 from gh_api import post_download
14
14
15 # Get main ipython dir, this will raise if it doesn't pass some checks
15 # Get main ipython dir, this will raise if it doesn't pass some checks
16 ipdir = get_ipdir()
16 ipdir = get_ipdir()
17 tooldir = pjoin(ipdir, 'tools')
17 tooldir = pjoin(ipdir, 'tools')
18 distdir = pjoin(ipdir, 'dist')
18 distdir = pjoin(ipdir, 'dist')
19
19
20 # Where I keep static backups of each release
20 # Where I keep static backups of each release
21 ipbackupdir = os.path.expanduser('~/ipython/backup')
21 ipbackupdir = os.path.expanduser('~/ipython/backup')
22 if not os.path.exists(ipbackupdir):
22 if not os.path.exists(ipbackupdir):
23 os.makedirs(ipbackupdir)
23 os.makedirs(ipbackupdir)
24
24
25 # Start in main IPython dir
25 # Start in main IPython dir
26 cd(ipdir)
26 cd(ipdir)
27
27
28 # Load release info
28 # Load release info
29 version = None
29 version = None
30 execfile(pjoin('IPython','core','release.py'), globals())
30 execfile(pjoin('IPython','core','release.py'), globals())
31
31
32 # Build site addresses for file uploads
32 # Build site addresses for file uploads
33 release_site = '%s/release/%s' % (archive, version)
33 release_site = '%s/release/%s' % (archive, version)
34 backup_site = '%s/backup/' % archive
34 backup_site = '%s/backup/' % archive
35
35
36 # Start actual release process
36 # Start actual release process
37 print()
37 print()
38 print('Releasing IPython')
38 print('Releasing IPython')
39 print('=================')
39 print('=================')
40 print()
40 print()
41 print('Version:', version)
41 print('Version:', version)
42 print()
42 print()
43 print('Source IPython directory:', ipdir)
43 print('Source IPython directory:', ipdir)
44 print()
44 print()
45
45
46 # Perform local backup, go to tools dir to run it.
46 # Perform local backup, go to tools dir to run it.
47 cd(tooldir)
47 cd(tooldir)
48 sh('./make_tarball.py')
48 sh('./make_tarball.py')
49 sh('mv ipython-*.tgz %s' % ipbackupdir)
49 sh('mv ipython-*.tgz %s' % ipbackupdir)
50
50
51 # Build release files
51 # Build release files
52 sh('./build_release %s' % ipdir)
52 sh('./build_release %s' % ipdir)
53
53
54 # Not Registering with PyPI, registering with setup.py is insecure as communication is not encrypted
54 # Not Registering with PyPI, registering with setup.py is insecure as communication is not encrypted
55 cd(ipdir)
55 cd(ipdir)
56
56
57 # Upload all files
57 # Upload all files
58 sh(sdists)
58 sh(sdists)
59 for py in ('2', '3'):
59
60 sh('python%s setupegg.py bdist_wheel' % py)
60 buildwheels()
61
61
62 if 'upload' not in sys.argv:
62 if 'upload' not in sys.argv:
63 print("`./release upload` to register and release")
63 print("`./release upload` to register and release")
64 sys.exit(0)
64 sys.exit(0)
65
65
66
66
67 print('Will not upload with setuptools as upload connection is insecure. Please use `twine upload dist/*` to upload the files to PyPI')
67 print('Will not upload with setuptools as upload connection is insecure. Please use `twine upload dist/*` to upload the files to PyPI')
68
68
69 cd(distdir)
69 cd(distdir)
70 print( 'Uploading distribution files to GitHub...')
70 print( 'Uploading distribution files to GitHub...')
71
71
72 for fname in os.listdir('.'):
72 for fname in os.listdir('.'):
73 # TODO: update to GitHub releases API
73 # TODO: update to GitHub releases API
74 continue
74 continue
75 print('uploading %s to GitHub' % fname)
75 print('uploading %s to GitHub' % fname)
76 desc = "IPython %s source distribution" % version
76 desc = "IPython %s source distribution" % version
77 post_download("ipython/ipython", fname, description=desc)
77 post_download("ipython/ipython", fname, description=desc)
78
78
79 # Make target dir if it doesn't exist
79 # Make target dir if it doesn't exist
80 print('Uploading IPython to backup site.')
80 print('Uploading IPython to backup site.')
81 sh('ssh %s "mkdir -p %s/release/%s" ' % (archive_user, archive_dir, version))
81 sh('ssh %s "mkdir -p %s/release/%s" ' % (archive_user, archive_dir, version))
82 sh('scp * %s' % release_site)
82 sh('scp * %s' % release_site)
83
83
84 print( 'Uploading backup files...')
84 print( 'Uploading backup files...')
85 cd(ipbackupdir)
85 cd(ipbackupdir)
86 sh('scp `ls -1tr *tgz | tail -1` %s' % backup_site)
86 sh('scp `ls -1tr *tgz | tail -1` %s' % backup_site)
87
87
88 print('Done!')
88 print('Done!')
@@ -1,64 +1,66 b''
1 """Various utilities common to IPython release and maintenance tools.
1 """Various utilities common to IPython release and maintenance tools.
2 """
2 """
3 from __future__ import print_function
3 from __future__ import print_function
4
4
5 # Library imports
5 # Library imports
6 import os
6 import os
7
7
8 # Useful shorthands
8 # Useful shorthands
9 pjoin = os.path.join
9 pjoin = os.path.join
10 cd = os.chdir
10 cd = os.chdir
11
11
12 # Constants
12 # Constants
13
13
14 # SSH root address of the archive site
14 # SSH root address of the archive site
15 archive_user = 'ipython@archive.ipython.org'
15 archive_user = 'ipython@archive.ipython.org'
16 archive_dir = 'archive.ipython.org'
16 archive_dir = 'archive.ipython.org'
17 archive = '%s:%s' % (archive_user, archive_dir)
17 archive = '%s:%s' % (archive_user, archive_dir)
18
18
19 # Build commands
19 # Build commands
20 # Source dists
20 # Source dists
21 sdists = './setup.py sdist --formats=gztar,zip'
21 sdists = './setup.py sdist --formats=gztar,zip'
22 # Binary dists
22 # Binary dists
23 wheels = './setupegg.py bdist_wheel'
23 def buildwheels():
24 for py in ('2', '3'):
25 sh('python%s setupegg.py bdist_wheel' % py)
24
26
25 # Utility functions
27 # Utility functions
26 def sh(cmd):
28 def sh(cmd):
27 """Run system command in shell, raise SystemExit if it returns an error."""
29 """Run system command in shell, raise SystemExit if it returns an error."""
28 print("$", cmd)
30 print("$", cmd)
29 stat = os.system(cmd)
31 stat = os.system(cmd)
30 #stat = 0 # Uncomment this and comment previous to run in debug mode
32 #stat = 0 # Uncomment this and comment previous to run in debug mode
31 if stat:
33 if stat:
32 raise SystemExit("Command %s failed with code: %s" % (cmd, stat))
34 raise SystemExit("Command %s failed with code: %s" % (cmd, stat))
33
35
34 # Backwards compatibility
36 # Backwards compatibility
35 c = sh
37 c = sh
36
38
37 def get_ipdir():
39 def get_ipdir():
38 """Get IPython directory from command line, or assume it's the one above."""
40 """Get IPython directory from command line, or assume it's the one above."""
39
41
40 # Initialize arguments and check location
42 # Initialize arguments and check location
41 ipdir = pjoin(os.path.dirname(__file__), os.pardir)
43 ipdir = pjoin(os.path.dirname(__file__), os.pardir)
42
44
43 ipdir = os.path.abspath(ipdir)
45 ipdir = os.path.abspath(ipdir)
44
46
45 cd(ipdir)
47 cd(ipdir)
46 if not os.path.isdir('IPython') and os.path.isfile('setup.py'):
48 if not os.path.isdir('IPython') and os.path.isfile('setup.py'):
47 raise SystemExit('Invalid ipython directory: %s' % ipdir)
49 raise SystemExit('Invalid ipython directory: %s' % ipdir)
48 return ipdir
50 return ipdir
49
51
50
52
51 def compile_tree(folder='.'):
53 def compile_tree(folder='.'):
52 """Compile all Python files below current directory."""
54 """Compile all Python files below current directory."""
53 stat = os.system('python -m compileall {}'.format(folder))
55 stat = os.system('python -m compileall {}'.format(folder))
54 if stat:
56 if stat:
55 msg = '*** ERROR: Some Python files in tree do NOT compile! ***\n'
57 msg = '*** ERROR: Some Python files in tree do NOT compile! ***\n'
56 msg += 'See messages above for the actual file that produced it.\n'
58 msg += 'See messages above for the actual file that produced it.\n'
57 raise SystemExit(msg)
59 raise SystemExit(msg)
58
60
59 try:
61 try:
60 execfile
62 execfile
61 except NameError:
63 except NameError:
62 def execfile(fname, globs, locs=None):
64 def execfile(fname, globs, locs=None):
63 locs = locs or globs
65 locs = locs or globs
64 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
66 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
@@ -1,78 +1,82 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """Update the What's New doc (development version)
2 """Update the What's New doc (development version)
3
3
4 This collects the snippets from whatsnew/pr/, moves their content into
4 This collects the snippets from whatsnew/pr/, moves their content into
5 whatsnew/development.rst (chronologically ordered), and deletes the snippets.
5 whatsnew/development.rst (chronologically ordered), and deletes the snippets.
6 """
6 """
7
7
8 import io
8 import io
9 import os
9 import sys
10 from glob import glob
10 from glob import glob
11 from os.path import dirname, basename, abspath, join as pjoin
11 from os.path import dirname, basename, abspath, join as pjoin
12 from subprocess import check_call, check_output
12 from subprocess import check_call, check_output
13
13
14 repo_root = dirname(dirname(abspath(__file__)))
14 repo_root = dirname(dirname(abspath(__file__)))
15 whatsnew_dir = pjoin(repo_root, 'docs', 'source', 'whatsnew')
15 whatsnew_dir = pjoin(repo_root, 'docs', 'source', 'whatsnew')
16 pr_dir = pjoin(whatsnew_dir, 'pr')
16 pr_dir = pjoin(whatsnew_dir, 'pr')
17 target = pjoin(whatsnew_dir, 'development.rst')
17 target = pjoin(whatsnew_dir, 'development.rst')
18
18
19 FEATURE_MARK = ".. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT."
19 FEATURE_MARK = ".. DO NOT EDIT THIS LINE BEFORE RELEASE. FEATURE INSERTION POINT."
20 INCOMPAT_MARK = ".. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT."
20 INCOMPAT_MARK = ".. DO NOT EDIT THIS LINE BEFORE RELEASE. INCOMPAT INSERTION POINT."
21
21
22 # 1. Collect the whatsnew snippet files ---------------------------------------
22 # 1. Collect the whatsnew snippet files ---------------------------------------
23
23
24 files = set(glob(pjoin(pr_dir, '*.rst')))
24 files = set(glob(pjoin(pr_dir, '*.rst')))
25 # Ignore explanatory and example files
25 # Ignore explanatory and example files
26 files.difference_update({pjoin(pr_dir, f) for f in {
26 files.difference_update({pjoin(pr_dir, f) for f in {
27 'incompat-switching-to-perl.rst',
27 'incompat-switching-to-perl.rst',
28 'antigravity-feature.rst'}
28 'antigravity-feature.rst'}
29 })
29 })
30
30
31 if not files:
32 print("No automatic update available for what's new")
33 sys.exit(0)
34
31
35
32 def getmtime(f):
36 def getmtime(f):
33 return check_output(['git', 'log', '-1', '--format="%ai"', '--', f])
37 return check_output(['git', 'log', '-1', '--format="%ai"', '--', f])
34
38
35 files = sorted(files, key=getmtime)
39 files = sorted(files, key=getmtime)
36
40
37 features, incompats = [], []
41 features, incompats = [], []
38 for path in files:
42 for path in files:
39 with io.open(path, encoding='utf-8') as f:
43 with io.open(path, encoding='utf-8') as f:
40 try:
44 try:
41 content = f.read().rstrip()
45 content = f.read().rstrip()
42 except Exception as e:
46 except Exception as e:
43 raise Exception('Error reading "{}"'.format(f)) from e
47 raise Exception('Error reading "{}"'.format(f)) from e
44
48
45 if basename(path).startswith('incompat-'):
49 if basename(path).startswith('incompat-'):
46 incompats.append(content)
50 incompats.append(content)
47 else:
51 else:
48 features.append(content)
52 features.append(content)
49
53
50 # Put the insertion markers back on the end, so they're ready for next time.
54 # Put the insertion markers back on the end, so they're ready for next time.
51 feature_block = '\n\n'.join(features + [FEATURE_MARK])
55 feature_block = '\n\n'.join(features + [FEATURE_MARK])
52 incompat_block = '\n\n'.join(incompats + [INCOMPAT_MARK])
56 incompat_block = '\n\n'.join(incompats + [INCOMPAT_MARK])
53
57
54 # 2. Update the target file ---------------------------------------------------
58 # 2. Update the target file ---------------------------------------------------
55
59
56 with io.open(target, encoding='utf-8') as f:
60 with io.open(target, encoding='utf-8') as f:
57 content = f.read()
61 content = f.read()
58
62
59 assert content.count(FEATURE_MARK) == 1
63 assert content.count(FEATURE_MARK) == 1
60 assert content.count(INCOMPAT_MARK) == 1
64 assert content.count(INCOMPAT_MARK) == 1
61
65
62 content = content.replace(FEATURE_MARK, feature_block)
66 content = content.replace(FEATURE_MARK, feature_block)
63 content = content.replace(INCOMPAT_MARK, incompat_block)
67 content = content.replace(INCOMPAT_MARK, incompat_block)
64
68
65 # Clean trailing whitespace
69 # Clean trailing whitespace
66 content = '\n'.join(l.rstrip() for l in content.splitlines())
70 content = '\n'.join(l.rstrip() for l in content.splitlines())
67
71
68 with io.open(target, 'w', encoding='utf-8') as f:
72 with io.open(target, 'w', encoding='utf-8') as f:
69 f.write(content)
73 f.write(content)
70
74
71 # 3. Stage the changes in git -------------------------------------------------
75 # 3. Stage the changes in git -------------------------------------------------
72
76
73 for file in files:
77 for file in files:
74 check_call(['git', 'rm', file])
78 check_call(['git', 'rm', file])
75
79
76 check_call(['git', 'add', target])
80 check_call(['git', 'add', target])
77
81
78 print("Merged what's new changes. Check the diff and commit the change.")
82 print("Merged what's new changes. Check the diff and commit the change.")
General Comments 0
You need to be logged in to leave comments. Login now