##// END OF EJS Templates
retar correctly xz
Matthias Bussonnier -
Show More
@@ -1,108 +1,108 b''
1 1 [metadata]
2 2 name = ipython
3 3 version = attr: IPython.core.release.__version__
4 4 url = https://ipython.org
5 5 description = IPython: Productive Interactive Computing
6 6 long_description_content_type = text/x-rst
7 7 long_description = IPython provides a rich toolkit to help you make the most out of using Python
8 8 interactively. Its main components are:
9 9
10 10 * A powerful interactive Python shell
11 11 * A `Jupyter <https://jupyter.org/>`_ kernel to work with Python code in Jupyter
12 12 notebooks and other interactive frontends.
13 13
14 14 The enhanced interactive Python shells have the following main features:
15 15
16 16 * Comprehensive object introspection.
17 17
18 18 * Input history, persistent across sessions.
19 19
20 20 * Caching of output results during a session with automatically generated
21 21 references.
22 22
23 23 * Extensible tab completion, with support by default for completion of python
24 24 variables and keywords, filenames and function keywords.
25 25
26 26 * Extensible system of 'magic' commands for controlling the environment and
27 27 performing many tasks related either to IPython or the operating system.
28 28
29 29 * A rich configuration system with easy switching between different setups
30 30 (simpler than changing $PYTHONSTARTUP environment variables every time).
31 31
32 32 * Session logging and reloading.
33 33
34 34 * Extensible syntax processing for special purpose situations.
35 35
36 36 * Access to the system shell with user-extensible alias system.
37 37
38 38 * Easily embeddable in other Python programs and GUIs.
39 39
40 40 * Integrated access to the pdb debugger and the Python profiler.
41 41
42 42 The latest development version is always available from IPython's `GitHub
43 43 site <http://github.com/ipython>`_.
44 44
45 45 license_file = LICENSE
46 46 project_urls =
47 47 Documentation = https://ipython.readthedocs.io/
48 48 Funding = https://numfocus.org/
49 49 Source = https://github.com/ipython/ipython
50 50 Tracker = https://github.com/ipython/ipython/issues
51 51 keywords = Interactive, Interpreter, Shell, Embedding
52 52 platforms = Linux, Mac OSX, Windows
53 53 classifiers =
54 54 Framework :: IPython
55 55 Intended Audience :: Developers
56 56 Intended Audience :: Science/Research
57 57 License :: OSI Approved :: BSD License
58 58 Programming Language :: Python
59 59 Programming Language :: Python :: 3
60 60 Programming Language :: Python :: 3 :: Only
61 Topic :: System :: Shell
61 Topic :: System :: Shells
62 62
63 63
64 64 [options]
65 65 packages = find:
66 66 python_requires = >=3.8
67 67 zip_safe = False
68 68 install_requires =
69 69 setuptools>=18.5
70 70 jedi>=0.16
71 71 decorator
72 72 pickleshare
73 73 traitlets>=5
74 74 prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1
75 75 pygments
76 76 backcall
77 77 stack_data
78 78 matplotlib-inline
79 79 pexpect>4.3; sys_platform != "win32"
80 80 appnope; sys_platform == "darwin"
81 81 colorama; sys_platform == "win32"
82 82
83 83 [options.packages.find]
84 84 exclude =
85 85 setupext
86 86
87 87 [options.package_data]
88 88 IPython.core = profile/README*
89 89 IPython.core.tests = *.png, *.jpg, daft_extension/*.py
90 90 IPython.lib.tests = *.wav
91 91 IPython.testing.plugin = *.txt
92 92
93 93 [options.entry_points]
94 94 console_scripts =
95 95 ipython = IPython:start_ipython
96 96 ipython3 = IPython:start_ipython
97 97 pygments.lexers =
98 98 ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer
99 99 ipython = IPython.lib.lexers:IPythonLexer
100 100 ipython3 = IPython.lib.lexers:IPython3Lexer
101 101
102 102 [velin]
103 103 ignore_patterns =
104 104 IPython/core/tests
105 105 IPython/testing
106 106
107 107 [tool.black]
108 108 exclude = 'timing\.py'
@@ -1,22 +1,23 b''
1 1 #!/usr/bin/env python3
2 2 """IPython release build script.
3 3 """
4 4 import os
5 5 import sys
6 6 from shutil import rmtree
7 7
8 8 from toollib import sh, pjoin, get_ipdir, cd, sdists, buildwheels
9 9
10 10 def build_release():
11 11
12 12 # Get main ipython dir, this will raise if it doesn't pass some checks
13 13 ipdir = get_ipdir()
14 14 cd(ipdir)
15 15
16 16 # Build source and binary distros
17 17 sh(sdists)
18 18 buildwheels()
19 19 sh(' '.join([sys.executable, 'tools/retar.py', 'dist/*.gz']))
20 sh(' '.join([sys.executable, 'tools/retar.py', 'dist/*.xz']))
20 21
21 22 if __name__ == '__main__':
22 23 build_release()
@@ -1,93 +1,93 b''
1 1 #!/usr/bin/env python3
2 2 """IPython release script.
3 3
4 4 This should ONLY be run at real release time.
5 5 """
6 6 from __future__ import print_function
7 7
8 8 import os
9 9 from glob import glob
10 10 from subprocess import call
11 11 import sys
12 12
13 13 from toollib import (get_ipdir, pjoin, cd, execfile, sh, archive,
14 14 sdists, archive_user, archive_dir, buildwheels)
15 15 from gh_api import post_download
16 16
17 17 # Get main ipython dir, this will raise if it doesn't pass some checks
18 18 ipdir = get_ipdir()
19 19 tooldir = pjoin(ipdir, 'tools')
20 20 distdir = pjoin(ipdir, 'dist')
21 21
22 22 # Where I keep static backups of each release
23 23 ipbackupdir = os.path.expanduser('~/ipython/backup')
24 24 if not os.path.exists(ipbackupdir):
25 25 os.makedirs(ipbackupdir)
26 26
27 27 # Start in main IPython dir
28 28 cd(ipdir)
29 29
30 30 # Load release info
31 31 version = None
32 32 execfile(pjoin('IPython','core','release.py'), globals())
33 33
34 34 # Build site addresses for file uploads
35 35 release_site = '%s/release/%s' % (archive, version)
36 36 backup_site = '%s/backup/' % archive
37 37
38 38 # Start actual release process
39 39 print()
40 40 print('Releasing IPython')
41 41 print('=================')
42 42 print()
43 43 print('Version:', version)
44 44 print()
45 45 print('Source IPython directory:', ipdir)
46 46 print()
47 47
48 48 # Perform local backup, go to tools dir to run it.
49 49 cd(tooldir)
50 50
51 51 if 'upload' in sys.argv:
52 52 cd(distdir)
53 53
54 54 # do not upload OS specific files like .DS_Store
55 55 to_upload = glob('*.whl')+glob('*.tar.gz')
56 56 for fname in to_upload:
57 57 # TODO: update to GitHub releases API
58 58 continue
59 59 print('uploading %s to GitHub' % fname)
60 60 desc = "IPython %s source distribution" % version
61 61 post_download("ipython/ipython", fname, description=desc)
62 62
63 63 # Make target dir if it doesn't exist
64 64 print('1. Uploading IPython to archive.ipython.org')
65 65 sh('ssh %s "mkdir -p %s/release/%s" ' % (archive_user, archive_dir, version))
66 sh('scp *.tar.gz *.whl %s' % release_site)
66 sh('scp *.tar.gz *.tar.xz *.whl %s' % release_site)
67 67
68 68 print('2. Uploading backup files...')
69 69 cd(ipbackupdir)
70 70 sh('scp `ls -1tr *tgz | tail -1` %s' % backup_site)
71 71
72 72 print('3. Uploading to PyPI using twine')
73 73 cd(distdir)
74 74 call(['twine', 'upload'] + to_upload)
75 75
76 76 else:
77 77 # Build, but don't upload
78 78
79 79 # Make backup tarball
80 80 sh('./make_tarball.py')
81 81 sh('mv ipython-*.tgz %s' % ipbackupdir)
82 82
83 83 # Build release files
84 84 sh('./build_release')
85 85
86 86 cd(ipdir)
87 87
88 88 buildwheels()
89 89 print("`./release upload` to upload source distribution on PyPI and ipython archive")
90 90 sys.exit(0)
91 91
92 92
93 93
@@ -1,68 +1,83 b''
1 1 """
2 2 Un-targz and retargz a targz file to ensure reproducible build.
3 3
4 4 usage:
5 5
6 6 $ export SOURCE_DATE_EPOCH=$(date +%s)
7 7 ...
8 8 $ python retar.py <tarfile.gz>
9 9
10 10 The process of creating an sdist can be non-reproducible:
11 11 - directory created during the process get a mtime of the creation date;
12 12 - gziping files embed the timestamp of zip creation.
13 13
14 14 This will untar-retar; ensuring that all mtime > SOURCE_DATE_EPOCH will be set
15 15 equal to SOURCE_DATE_EPOCH.
16 16
17 17 """
18 18
19 19 import tarfile
20 20 import sys
21 21 import os
22 22 import gzip
23 23 import io
24 24
25 25 from pathlib import Path
26 26
27 27 if len(sys.argv) > 2:
28 28 raise ValueError("Too many arguments")
29 29
30 30
31 31 timestamp = int(os.environ["SOURCE_DATE_EPOCH"])
32 32
33 33 path = Path(sys.argv[1])
34 34 old_buf = io.BytesIO()
35 35 with open(path, "rb") as f:
36 36 old_buf.write(f.read())
37 37 old_buf.seek(0)
38 old = tarfile.open(fileobj=old_buf, mode="r:gz")
38 if path.name.endswith("gz"):
39 r_mode = "r:gz"
40 if path.name.endswith(("xz", "xz2")):
41 r_mode = "r:xz"
42 old = tarfile.open(fileobj=old_buf, mode=r_mode)
39 43
40 44 buf = io.BytesIO()
41 45 new = tarfile.open(fileobj=buf, mode="w", format=tarfile.GNU_FORMAT)
42 46 for i, m in enumerate(old):
43 47 data = None
44 48 # mutation does not work, copy
45 49 if m.name.endswith('.DS_Store'):
46 50 continue
47 51 m2 = tarfile.TarInfo(m.name)
48 52 m2.mtime = min(timestamp, m.mtime)
53 m2.pax_headers["mtime"] = m2.mtime
49 54 m2.size = m.size
50 55 m2.type = m.type
51 56 m2.linkname = m.linkname
52 57 m2.mode = m.mode
53 58 if m.isdir():
54 59 new.addfile(m2)
55 60 else:
56 61 data = old.extractfile(m)
57 62 new.addfile(m2, data)
58 63 new.close()
59 64 old.close()
60 65
61 66 buf.seek(0)
62 with open(path, "wb") as f:
63 with gzip.GzipFile('', "wb", fileobj=f, mtime=timestamp) as gzf:
64 gzf.write(buf.read())
67
68 if r_mode == "r:gz":
69 with open(path, "wb") as f:
70 with gzip.GzipFile("", "wb", fileobj=f, mtime=timestamp) as gzf:
71 gzf.write(buf.read())
72 elif r_mode == "r:xz":
73 import lzma
74
75 with lzma.open(path, "wb") as f:
76 f.write(buf.read())
77
78 else:
79 assert False
65 80
66 81 # checks the archive is valid.
67 82 archive = tarfile.open(path)
68 83 names = archive.getnames()
@@ -1,51 +1,51 b''
1 1 """Various utilities common to IPython release and maintenance tools.
2 2 """
3 3
4 4 # Library imports
5 5 import os
6 6 import sys
7 7
8 8 # Useful shorthands
9 9 pjoin = os.path.join
10 10 cd = os.chdir
11 11
12 12 # Constants
13 13
14 14 # SSH root address of the archive site
15 15 archive_user = 'ipython@archive.ipython.org'
16 16 archive_dir = 'archive.ipython.org'
17 17 archive = '%s:%s' % (archive_user, archive_dir)
18 18
19 19 # Build commands
20 20 # Source dists
21 sdists = "{python} setup.py sdist --formats=xztar".format(python=sys.executable)
21 sdists = "{python} setup.py sdist --formats=xztar,gztar".format(python=sys.executable)
22 22 # Binary dists
23 23 def buildwheels():
24 24 sh("{python} setup.py bdist_wheel".format(python=sys.executable))
25 25
26 26
27 27 # Utility functions
28 28 def sh(cmd):
29 29 """Run system command in shell, raise SystemExit if it returns an error."""
30 30 print("$", cmd)
31 31 stat = os.system(cmd)
32 32 #stat = 0 # Uncomment this and comment previous to run in debug mode
33 33 if stat:
34 34 raise SystemExit("Command %s failed with code: %s" % (cmd, stat))
35 35
36 36 def get_ipdir():
37 37 """Get IPython directory from command line, or assume it's the one above."""
38 38
39 39 # Initialize arguments and check location
40 40 ipdir = pjoin(os.path.dirname(__file__), os.pardir)
41 41
42 42 ipdir = os.path.abspath(ipdir)
43 43
44 44 cd(ipdir)
45 45 if not os.path.isdir('IPython') and os.path.isfile('setup.py'):
46 46 raise SystemExit('Invalid ipython directory: %s' % ipdir)
47 47 return ipdir
48 48
49 49 def execfile(fname, globs, locs=None):
50 50 locs = locs or globs
51 51 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
General Comments 0
You need to be logged in to leave comments. Login now