##// END OF EJS Templates
Move more metadata from IPython.core.release.py to setup.cfg
James Morris -
Show More
@@ -1,119 +1,54 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project."""
2 """Release data for the IPython project."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2008, IPython Development Team.
5 # Copyright (c) 2008, IPython Development Team.
6 # Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
6 # Copyright (c) 2001, Fernando Perez <fernando.perez@colorado.edu>
7 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
7 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
8 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
8 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
9 #
9 #
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11 #
11 #
12 # The full license is in the file COPYING.txt, distributed with this software.
12 # The full license is in the file COPYING.txt, distributed with this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Name of the package for release purposes. This is the name which labels
16 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
17 name = 'ipython'
18
19 # IPython version information. An empty _version_extra corresponds to a full
15 # IPython version information. An empty _version_extra corresponds to a full
20 # release. 'dev' as a _version_extra string means this is a development
16 # release. 'dev' as a _version_extra string means this is a development
21 # version
17 # version
22 _version_major = 8
18 _version_major = 8
23 _version_minor = 0
19 _version_minor = 0
24 _version_patch = 0
20 _version_patch = 0
25 _version_extra = '.dev'
21 _version_extra = '.dev'
26 # _version_extra = 'b1'
22 # _version_extra = 'b1'
27 # _version_extra = '' # Uncomment this for full releases
23 # _version_extra = '' # Uncomment this for full releases
28
24
29 # Construct full version string from these.
25 # Construct full version string from these.
30 _ver = [_version_major, _version_minor, _version_patch]
26 _ver = [_version_major, _version_minor, _version_patch]
31
27
32 __version__ = '.'.join(map(str, _ver))
28 __version__ = '.'.join(map(str, _ver))
33 if _version_extra:
29 if _version_extra:
34 __version__ = __version__ + _version_extra
30 __version__ = __version__ + _version_extra
35
31
36 version = __version__ # backwards compatibility name
32 version = __version__ # backwards compatibility name
37 version_info = (_version_major, _version_minor, _version_patch, _version_extra)
33 version_info = (_version_major, _version_minor, _version_patch, _version_extra)
38
34
39 # Change this when incrementing the kernel protocol version
35 # Change this when incrementing the kernel protocol version
40 kernel_protocol_version_info = (5, 0)
36 kernel_protocol_version_info = (5, 0)
41 kernel_protocol_version = "%i.%i" % kernel_protocol_version_info
37 kernel_protocol_version = "%i.%i" % kernel_protocol_version_info
42
38
43 description = "IPython: Productive Interactive Computing"
44
45 long_description = \
46 """
47 IPython provides a rich toolkit to help you make the most out of using Python
48 interactively. Its main components are:
49
50 * A powerful interactive Python shell
51 * A `Jupyter <https://jupyter.org/>`_ kernel to work with Python code in Jupyter
52 notebooks and other interactive frontends.
53
54 The enhanced interactive Python shells have the following main features:
55
56 * Comprehensive object introspection.
57
58 * Input history, persistent across sessions.
59
60 * Caching of output results during a session with automatically generated
61 references.
62
63 * Extensible tab completion, with support by default for completion of python
64 variables and keywords, filenames and function keywords.
65
66 * Extensible system of 'magic' commands for controlling the environment and
67 performing many tasks related either to IPython or the operating system.
68
69 * A rich configuration system with easy switching between different setups
70 (simpler than changing $PYTHONSTARTUP environment variables every time).
71
72 * Session logging and reloading.
73
74 * Extensible syntax processing for special purpose situations.
75
76 * Access to the system shell with user-extensible alias system.
77
78 * Easily embeddable in other Python programs and GUIs.
79
80 * Integrated access to the pdb debugger and the Python profiler.
81
82 The latest development version is always available from IPython's `GitHub
83 site <http://github.com/ipython>`_.
84 """
85
86 license = 'BSD'
39 license = 'BSD'
87
40
88 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
41 authors = {'Fernando' : ('Fernando Perez','fperez.net@gmail.com'),
89 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
42 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
90 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
43 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
91 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
44 'Ville' : ('Ville Vainio','vivainio@gmail.com'),
92 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
45 'Brian' : ('Brian E Granger', 'ellisonbg@gmail.com'),
93 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
46 'Min' : ('Min Ragan-Kelley', 'benjaminrk@gmail.com'),
94 'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
47 'Thomas' : ('Thomas A. Kluyver', 'takowl@gmail.com'),
95 'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
48 'Jorgen' : ('Jorgen Stenarson', 'jorgen.stenarson@bostream.nu'),
96 'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
49 'Matthias' : ('Matthias Bussonnier', 'bussonniermatthias@gmail.com'),
97 }
50 }
98
51
99 author = 'The IPython Development Team'
52 author = 'The IPython Development Team'
100
53
101 author_email = 'ipython-dev@python.org'
54 author_email = 'ipython-dev@python.org'
102
103 url = 'https://ipython.org'
104
105
106 platforms = ['Linux','Mac OSX','Windows']
107
108 keywords = ['Interactive','Interpreter','Shell', 'Embedding']
109
110 classifiers = [
111 'Framework :: IPython',
112 'Intended Audience :: Developers',
113 'Intended Audience :: Science/Research',
114 'License :: OSI Approved :: BSD License',
115 'Programming Language :: Python',
116 'Programming Language :: Python :: 3',
117 'Programming Language :: Python :: 3 :: Only',
118 'Topic :: System :: Shells'
119 ]
@@ -1,53 +1,107 b''
1 [metadata]
1 [metadata]
2 name = ipython
2 version = attr: IPython.core.release.__version__
3 version = attr: IPython.core.release.__version__
4 url = https://ipython.org
5 description = IPython: Productive Interactive Computing
6 long_description_content_type = text/x-rst
7 long_description = IPython provides a rich toolkit to help you make the most out of using Python
8 interactively. Its main components are:
9
10 * A powerful interactive Python shell
11 * A `Jupyter <https://jupyter.org/>`_ kernel to work with Python code in Jupyter
12 notebooks and other interactive frontends.
13
14 The enhanced interactive Python shells have the following main features:
15
16 * Comprehensive object introspection.
17
18 * Input history, persistent across sessions.
19
20 * Caching of output results during a session with automatically generated
21 references.
22
23 * Extensible tab completion, with support by default for completion of python
24 variables and keywords, filenames and function keywords.
25
26 * Extensible system of 'magic' commands for controlling the environment and
27 performing many tasks related either to IPython or the operating system.
28
29 * A rich configuration system with easy switching between different setups
30 (simpler than changing $PYTHONSTARTUP environment variables every time).
31
32 * Session logging and reloading.
33
34 * Extensible syntax processing for special purpose situations.
35
36 * Access to the system shell with user-extensible alias system.
37
38 * Easily embeddable in other Python programs and GUIs.
39
40 * Integrated access to the pdb debugger and the Python profiler.
41
42 The latest development version is always available from IPython's `GitHub
43 site <http://github.com/ipython>`_.
44
3 license_file = LICENSE
45 license_file = LICENSE
4 project_urls =
46 project_urls =
5 Documentation = https://ipython.readthedocs.io/
47 Documentation = https://ipython.readthedocs.io/
6 Funding = https://numfocus.org/
48 Funding = https://numfocus.org/
7 Source = https://github.com/ipython/ipython
49 Source = https://github.com/ipython/ipython
8 Tracker = https://github.com/ipython/ipython/issues
50 Tracker = https://github.com/ipython/ipython/issues
51 keywords = Interactive, Interpreter, Shell, Embedding
52 platforms = Linux, Mac OSX, Windows
53 classifiers =
54 Framework :: IPython
55 Intended Audience :: Developers
56 Intended Audience :: Science/Research
57 License :: OSI Approved :: BSD License
58 Programming Language :: Python
59 Programming Language :: Python :: 3
60 Programming Language :: Python :: 3 :: Only
61 Topic :: System :: Shell
62
9
63
10 [options]
64 [options]
11 packages = find:
65 packages = find:
12 python_requires = >=3.8
66 python_requires = >=3.8
13 zip_safe = False
67 zip_safe = False
14 install_requires =
68 install_requires =
15 setuptools>=18.5
69 setuptools>=18.5
16 jedi>=0.16
70 jedi>=0.16
17 decorator
71 decorator
18 pickleshare
72 pickleshare
19 traitlets>=4.2
73 traitlets>=4.2
20 prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1
74 prompt_toolkit>=2.0.0,<3.1.0,!=3.0.0,!=3.0.1
21 pygments
75 pygments
22 backcall
76 backcall
23 stack_data
77 stack_data
24 matplotlib-inline
78 matplotlib-inline
25 pexpect>4.3; sys_platform != "win32"
79 pexpect>4.3; sys_platform != "win32"
26 appnope; sys_platform == "darwin"
80 appnope; sys_platform == "darwin"
27 colorama; sys_platform == "win32"
81 colorama; sys_platform == "win32"
28
82
29 [options.packages.find]
83 [options.packages.find]
30 exclude =
84 exclude =
31 deathrow
85 deathrow
32 quarantine
86 quarantine
33 setupext
87 setupext
34
88
35 [options.package_data]
89 [options.package_data]
36 IPython.core = profile/README*
90 IPython.core = profile/README*
37 IPython.core.tests = *.png, *.jpg, daft_extension/*.py
91 IPython.core.tests = *.png, *.jpg, daft_extension/*.py
38 IPython.lib.tests = *.wav
92 IPython.lib.tests = *.wav
39 IPython.testing.plugin = *.txt
93 IPython.testing.plugin = *.txt
40
94
41 [options.entry_points]
95 [options.entry_points]
42 console_scripts =
96 console_scripts =
43 ipython = IPython:start_ipython
97 ipython = IPython:start_ipython
44 ipython3 = IPython:start_ipython
98 ipython3 = IPython:start_ipython
45 pygments.lexers =
99 pygments.lexers =
46 ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer
100 ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer
47 ipython = IPython.lib.lexers:IPythonLexer
101 ipython = IPython.lib.lexers:IPythonLexer
48 ipython3 = IPython.lib.lexers:IPython3Lexer
102 ipython3 = IPython.lib.lexers:IPython3Lexer
49
103
50 [velin]
104 [velin]
51 ignore_patterns =
105 ignore_patterns =
52 IPython/core/tests,
106 IPython/core/tests,
53 IPython/testing
107 IPython/testing
@@ -1,354 +1,347 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 This module defines the things that are used in setup.py for building IPython
3 This module defines the things that are used in setup.py for building IPython
4
4
5 This includes:
5 This includes:
6
6
7 * The basic arguments to setup
7 * The basic arguments to setup
8 * Functions for finding things like packages, package data, etc.
8 * Functions for finding things like packages, package data, etc.
9 * A function for checking dependencies.
9 * A function for checking dependencies.
10 """
10 """
11
11
12 # Copyright (c) IPython Development Team.
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14
14
15 import os
15 import os
16 import re
16 import re
17 import sys
17 import sys
18 from glob import glob
18 from glob import glob
19 from logging import log
19 from logging import log
20
20
21 from setuptools import Command
21 from setuptools import Command
22 from setuptools.command.build_py import build_py
22 from setuptools.command.build_py import build_py
23
23
24 from setuptools.command.install import install
24 from setuptools.command.install import install
25 from setuptools.command.install_scripts import install_scripts
25 from setuptools.command.install_scripts import install_scripts
26
26
27 from setupext import install_data_ext
27 from setupext import install_data_ext
28
28
29 #-------------------------------------------------------------------------------
29 #-------------------------------------------------------------------------------
30 # Useful globals and utility functions
30 # Useful globals and utility functions
31 #-------------------------------------------------------------------------------
31 #-------------------------------------------------------------------------------
32
32
33 # A few handy globals
33 # A few handy globals
34 isfile = os.path.isfile
34 isfile = os.path.isfile
35 pjoin = os.path.join
35 pjoin = os.path.join
36 repo_root = os.path.dirname(os.path.abspath(__file__))
36 repo_root = os.path.dirname(os.path.abspath(__file__))
37
37
38 def execfile(fname, globs, locs=None):
38 def execfile(fname, globs, locs=None):
39 locs = locs or globs
39 locs = locs or globs
40 with open(fname) as f:
40 with open(fname) as f:
41 exec(compile(f.read(), fname, "exec"), globs, locs)
41 exec(compile(f.read(), fname, "exec"), globs, locs)
42
42
43 # A little utility we'll need below, since glob() does NOT allow you to do
43 # A little utility we'll need below, since glob() does NOT allow you to do
44 # exclusion on multiple endings!
44 # exclusion on multiple endings!
45 def file_doesnt_endwith(test,endings):
45 def file_doesnt_endwith(test,endings):
46 """Return true if test is a file and its name does NOT end with any
46 """Return true if test is a file and its name does NOT end with any
47 of the strings listed in endings."""
47 of the strings listed in endings."""
48 if not isfile(test):
48 if not isfile(test):
49 return False
49 return False
50 for e in endings:
50 for e in endings:
51 if test.endswith(e):
51 if test.endswith(e):
52 return False
52 return False
53 return True
53 return True
54
54
55 #---------------------------------------------------------------------------
55 #---------------------------------------------------------------------------
56 # Basic project information
56 # Basic project information
57 #---------------------------------------------------------------------------
57 #---------------------------------------------------------------------------
58
58
59 # release.py contains version, authors, license, url, keywords, etc.
59 # release.py contains version, authors, license, url, keywords, etc.
60 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
60 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
61
61
62 # Create a dict with the basic information
62 # Create a dict with the basic information
63 # This dict is eventually passed to setup after additional keys are added.
63 # This dict is eventually passed to setup after additional keys are added.
64 setup_args = dict(
64 setup_args = dict(
65 name = name,
66 description = description,
67 long_description = long_description,
68 author = author,
65 author = author,
69 author_email = author_email,
66 author_email = author_email,
70 url = url,
71 license = license,
67 license = license,
72 platforms = platforms,
73 keywords = keywords,
74 classifiers = classifiers,
75 cmdclass = {'install_data': install_data_ext},
68 cmdclass = {'install_data': install_data_ext},
76 )
69 )
77
70
78
71
79 #---------------------------------------------------------------------------
72 #---------------------------------------------------------------------------
80 # Find packages
73 # Find packages
81 #---------------------------------------------------------------------------
74 #---------------------------------------------------------------------------
82
75
83 def find_packages():
76 def find_packages():
84 """
77 """
85 Find all of IPython's packages.
78 Find all of IPython's packages.
86 """
79 """
87 excludes = ['deathrow', 'quarantine']
80 excludes = ['deathrow', 'quarantine']
88 packages = []
81 packages = []
89 for directory, subdirs, files in os.walk("IPython"):
82 for directory, subdirs, files in os.walk("IPython"):
90 package = directory.replace(os.path.sep, ".")
83 package = directory.replace(os.path.sep, ".")
91 if any(package.startswith("IPython." + exc) for exc in excludes):
84 if any(package.startswith("IPython." + exc) for exc in excludes):
92 # package is to be excluded (e.g. deathrow)
85 # package is to be excluded (e.g. deathrow)
93 continue
86 continue
94 if '__init__.py' not in files:
87 if '__init__.py' not in files:
95 # not a package
88 # not a package
96 continue
89 continue
97 packages.append(package)
90 packages.append(package)
98 return packages
91 return packages
99
92
100 #---------------------------------------------------------------------------
93 #---------------------------------------------------------------------------
101 # Find package data
94 # Find package data
102 #---------------------------------------------------------------------------
95 #---------------------------------------------------------------------------
103
96
104 def find_package_data():
97 def find_package_data():
105 """
98 """
106 Find IPython's package_data.
99 Find IPython's package_data.
107 """
100 """
108 # This is not enough for these things to appear in an sdist.
101 # This is not enough for these things to appear in an sdist.
109 # We need to muck with the MANIFEST to get this to work
102 # We need to muck with the MANIFEST to get this to work
110
103
111 package_data = {
104 package_data = {
112 'IPython.core' : ['profile/README*'],
105 'IPython.core' : ['profile/README*'],
113 'IPython.core.tests' : ['*.png', '*.jpg', 'daft_extension/*.py'],
106 'IPython.core.tests' : ['*.png', '*.jpg', 'daft_extension/*.py'],
114 'IPython.lib.tests' : ['*.wav'],
107 'IPython.lib.tests' : ['*.wav'],
115 'IPython.testing.plugin' : ['*.txt'],
108 'IPython.testing.plugin' : ['*.txt'],
116 }
109 }
117
110
118 return package_data
111 return package_data
119
112
120
113
121 def check_package_data(package_data):
114 def check_package_data(package_data):
122 """verify that package_data globs make sense"""
115 """verify that package_data globs make sense"""
123 print("checking package data")
116 print("checking package data")
124 for pkg, data in package_data.items():
117 for pkg, data in package_data.items():
125 pkg_root = pjoin(*pkg.split('.'))
118 pkg_root = pjoin(*pkg.split('.'))
126 for d in data:
119 for d in data:
127 path = pjoin(pkg_root, d)
120 path = pjoin(pkg_root, d)
128 if '*' in path:
121 if '*' in path:
129 assert len(glob(path)) > 0, "No files match pattern %s" % path
122 assert len(glob(path)) > 0, "No files match pattern %s" % path
130 else:
123 else:
131 assert os.path.exists(path), "Missing package data: %s" % path
124 assert os.path.exists(path), "Missing package data: %s" % path
132
125
133
126
134 def check_package_data_first(command):
127 def check_package_data_first(command):
135 """decorator for checking package_data before running a given command
128 """decorator for checking package_data before running a given command
136
129
137 Probably only needs to wrap build_py
130 Probably only needs to wrap build_py
138 """
131 """
139 class DecoratedCommand(command):
132 class DecoratedCommand(command):
140 def run(self):
133 def run(self):
141 check_package_data(self.package_data)
134 check_package_data(self.package_data)
142 command.run(self)
135 command.run(self)
143 return DecoratedCommand
136 return DecoratedCommand
144
137
145
138
146 #---------------------------------------------------------------------------
139 #---------------------------------------------------------------------------
147 # Find data files
140 # Find data files
148 #---------------------------------------------------------------------------
141 #---------------------------------------------------------------------------
149
142
150 def find_data_files():
143 def find_data_files():
151 """
144 """
152 Find IPython's data_files.
145 Find IPython's data_files.
153
146
154 Just man pages at this point.
147 Just man pages at this point.
155 """
148 """
156
149
157 if "freebsd" in sys.platform:
150 if "freebsd" in sys.platform:
158 manpagebase = pjoin('man', 'man1')
151 manpagebase = pjoin('man', 'man1')
159 else:
152 else:
160 manpagebase = pjoin('share', 'man', 'man1')
153 manpagebase = pjoin('share', 'man', 'man1')
161
154
162 # Simple file lists can be made by hand
155 # Simple file lists can be made by hand
163 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
156 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
164 if not manpages:
157 if not manpages:
165 # When running from a source tree, the manpages aren't gzipped
158 # When running from a source tree, the manpages aren't gzipped
166 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
159 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
167
160
168 # And assemble the entire output list
161 # And assemble the entire output list
169 data_files = [ (manpagebase, manpages) ]
162 data_files = [ (manpagebase, manpages) ]
170
163
171 return data_files
164 return data_files
172
165
173
166
174 # The two functions below are copied from IPython.utils.path, so we don't need
167 # The two functions below are copied from IPython.utils.path, so we don't need
175 # to import IPython during setup, which fails on Python 3.
168 # to import IPython during setup, which fails on Python 3.
176
169
177 def target_outdated(target,deps):
170 def target_outdated(target,deps):
178 """Determine whether a target is out of date.
171 """Determine whether a target is out of date.
179
172
180 target_outdated(target,deps) -> 1/0
173 target_outdated(target,deps) -> 1/0
181
174
182 deps: list of filenames which MUST exist.
175 deps: list of filenames which MUST exist.
183 target: single filename which may or may not exist.
176 target: single filename which may or may not exist.
184
177
185 If target doesn't exist or is older than any file listed in deps, return
178 If target doesn't exist or is older than any file listed in deps, return
186 true, otherwise return false.
179 true, otherwise return false.
187 """
180 """
188 try:
181 try:
189 target_time = os.path.getmtime(target)
182 target_time = os.path.getmtime(target)
190 except os.error:
183 except os.error:
191 return 1
184 return 1
192 for dep in deps:
185 for dep in deps:
193 dep_time = os.path.getmtime(dep)
186 dep_time = os.path.getmtime(dep)
194 if dep_time > target_time:
187 if dep_time > target_time:
195 #print "For target",target,"Dep failed:",dep # dbg
188 #print "For target",target,"Dep failed:",dep # dbg
196 #print "times (dep,tar):",dep_time,target_time # dbg
189 #print "times (dep,tar):",dep_time,target_time # dbg
197 return 1
190 return 1
198 return 0
191 return 0
199
192
200
193
201 def target_update(target,deps,cmd):
194 def target_update(target,deps,cmd):
202 """Update a target with a given command given a list of dependencies.
195 """Update a target with a given command given a list of dependencies.
203
196
204 target_update(target,deps,cmd) -> runs cmd if target is outdated.
197 target_update(target,deps,cmd) -> runs cmd if target is outdated.
205
198
206 This is just a wrapper around target_outdated() which calls the given
199 This is just a wrapper around target_outdated() which calls the given
207 command if target is outdated."""
200 command if target is outdated."""
208
201
209 if target_outdated(target,deps):
202 if target_outdated(target,deps):
210 os.system(cmd)
203 os.system(cmd)
211
204
212 #---------------------------------------------------------------------------
205 #---------------------------------------------------------------------------
213 # Find scripts
206 # Find scripts
214 #---------------------------------------------------------------------------
207 #---------------------------------------------------------------------------
215
208
216 def find_entry_points():
209 def find_entry_points():
217 """Defines the command line entry points for IPython
210 """Defines the command line entry points for IPython
218
211
219 This always uses setuptools-style entry points. When setuptools is not in
212 This always uses setuptools-style entry points. When setuptools is not in
220 use, our own build_scripts_entrypt class below parses these and builds
213 use, our own build_scripts_entrypt class below parses these and builds
221 command line scripts.
214 command line scripts.
222
215
223 Each of our entry points gets both a plain name, e.g. ipython, and one
216 Each of our entry points gets both a plain name, e.g. ipython, and one
224 suffixed with the Python major version number, e.g. ipython3.
217 suffixed with the Python major version number, e.g. ipython3.
225 """
218 """
226 ep = [
219 ep = [
227 'ipython%s = IPython:start_ipython',
220 'ipython%s = IPython:start_ipython',
228 ]
221 ]
229 suffix = str(sys.version_info[0])
222 suffix = str(sys.version_info[0])
230 return [e % '' for e in ep] + [e % suffix for e in ep]
223 return [e % '' for e in ep] + [e % suffix for e in ep]
231
224
232 class install_lib_symlink(Command):
225 class install_lib_symlink(Command):
233 user_options = [
226 user_options = [
234 ('install-dir=', 'd', "directory to install to"),
227 ('install-dir=', 'd', "directory to install to"),
235 ]
228 ]
236
229
237 def initialize_options(self):
230 def initialize_options(self):
238 self.install_dir = None
231 self.install_dir = None
239
232
240 def finalize_options(self):
233 def finalize_options(self):
241 self.set_undefined_options('symlink',
234 self.set_undefined_options('symlink',
242 ('install_lib', 'install_dir'),
235 ('install_lib', 'install_dir'),
243 )
236 )
244
237
245 def run(self):
238 def run(self):
246 if sys.platform == 'win32':
239 if sys.platform == 'win32':
247 raise Exception("This doesn't work on Windows.")
240 raise Exception("This doesn't work on Windows.")
248 pkg = os.path.join(os.getcwd(), 'IPython')
241 pkg = os.path.join(os.getcwd(), 'IPython')
249 dest = os.path.join(self.install_dir, 'IPython')
242 dest = os.path.join(self.install_dir, 'IPython')
250 if os.path.islink(dest):
243 if os.path.islink(dest):
251 print('removing existing symlink at %s' % dest)
244 print('removing existing symlink at %s' % dest)
252 os.unlink(dest)
245 os.unlink(dest)
253 print('symlinking %s -> %s' % (pkg, dest))
246 print('symlinking %s -> %s' % (pkg, dest))
254 os.symlink(pkg, dest)
247 os.symlink(pkg, dest)
255
248
256 class unsymlink(install):
249 class unsymlink(install):
257 def run(self):
250 def run(self):
258 dest = os.path.join(self.install_lib, 'IPython')
251 dest = os.path.join(self.install_lib, 'IPython')
259 if os.path.islink(dest):
252 if os.path.islink(dest):
260 print('removing symlink at %s' % dest)
253 print('removing symlink at %s' % dest)
261 os.unlink(dest)
254 os.unlink(dest)
262 else:
255 else:
263 print('No symlink exists at %s' % dest)
256 print('No symlink exists at %s' % dest)
264
257
265 class install_symlinked(install):
258 class install_symlinked(install):
266 def run(self):
259 def run(self):
267 if sys.platform == 'win32':
260 if sys.platform == 'win32':
268 raise Exception("This doesn't work on Windows.")
261 raise Exception("This doesn't work on Windows.")
269
262
270 # Run all sub-commands (at least those that need to be run)
263 # Run all sub-commands (at least those that need to be run)
271 for cmd_name in self.get_sub_commands():
264 for cmd_name in self.get_sub_commands():
272 self.run_command(cmd_name)
265 self.run_command(cmd_name)
273
266
274 # 'sub_commands': a list of commands this command might have to run to
267 # 'sub_commands': a list of commands this command might have to run to
275 # get its work done. See cmd.py for more info.
268 # get its work done. See cmd.py for more info.
276 sub_commands = [('install_lib_symlink', lambda self:True),
269 sub_commands = [('install_lib_symlink', lambda self:True),
277 ('install_scripts_sym', lambda self:True),
270 ('install_scripts_sym', lambda self:True),
278 ]
271 ]
279
272
280 class install_scripts_for_symlink(install_scripts):
273 class install_scripts_for_symlink(install_scripts):
281 """Redefined to get options from 'symlink' instead of 'install'.
274 """Redefined to get options from 'symlink' instead of 'install'.
282
275
283 I love distutils almost as much as I love setuptools.
276 I love distutils almost as much as I love setuptools.
284 """
277 """
285 def finalize_options(self):
278 def finalize_options(self):
286 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
279 self.set_undefined_options('build', ('build_scripts', 'build_dir'))
287 self.set_undefined_options('symlink',
280 self.set_undefined_options('symlink',
288 ('install_scripts', 'install_dir'),
281 ('install_scripts', 'install_dir'),
289 ('force', 'force'),
282 ('force', 'force'),
290 ('skip_build', 'skip_build'),
283 ('skip_build', 'skip_build'),
291 )
284 )
292
285
293
286
294 #---------------------------------------------------------------------------
287 #---------------------------------------------------------------------------
295 # VCS related
288 # VCS related
296 #---------------------------------------------------------------------------
289 #---------------------------------------------------------------------------
297
290
298
291
299 def git_prebuild(pkg_dir, build_cmd=build_py):
292 def git_prebuild(pkg_dir, build_cmd=build_py):
300 """Return extended build or sdist command class for recording commit
293 """Return extended build or sdist command class for recording commit
301
294
302 records git commit in IPython.utils._sysinfo.commit
295 records git commit in IPython.utils._sysinfo.commit
303
296
304 for use in IPython.utils.sysinfo.sys_info() calls after installation.
297 for use in IPython.utils.sysinfo.sys_info() calls after installation.
305 """
298 """
306
299
307 class MyBuildPy(build_cmd):
300 class MyBuildPy(build_cmd):
308 ''' Subclass to write commit data into installation tree '''
301 ''' Subclass to write commit data into installation tree '''
309 def run(self):
302 def run(self):
310 # loose as `.dev` is suppose to be invalid
303 # loose as `.dev` is suppose to be invalid
311 print("check version number")
304 print("check version number")
312 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
305 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
313 if not loose_pep440re.match(version):
306 if not loose_pep440re.match(version):
314 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
307 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
315
308
316
309
317 build_cmd.run(self)
310 build_cmd.run(self)
318 # this one will only fire for build commands
311 # this one will only fire for build commands
319 if hasattr(self, 'build_lib'):
312 if hasattr(self, 'build_lib'):
320 self._record_commit(self.build_lib)
313 self._record_commit(self.build_lib)
321
314
322 def make_release_tree(self, base_dir, files):
315 def make_release_tree(self, base_dir, files):
323 # this one will fire for sdist
316 # this one will fire for sdist
324 build_cmd.make_release_tree(self, base_dir, files)
317 build_cmd.make_release_tree(self, base_dir, files)
325 self._record_commit(base_dir)
318 self._record_commit(base_dir)
326
319
327 def _record_commit(self, base_dir):
320 def _record_commit(self, base_dir):
328 import subprocess
321 import subprocess
329 proc = subprocess.Popen('git rev-parse --short HEAD',
322 proc = subprocess.Popen('git rev-parse --short HEAD',
330 stdout=subprocess.PIPE,
323 stdout=subprocess.PIPE,
331 stderr=subprocess.PIPE,
324 stderr=subprocess.PIPE,
332 shell=True)
325 shell=True)
333 repo_commit, _ = proc.communicate()
326 repo_commit, _ = proc.communicate()
334 repo_commit = repo_commit.strip().decode("ascii")
327 repo_commit = repo_commit.strip().decode("ascii")
335
328
336 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
329 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
337 if os.path.isfile(out_pth) and not repo_commit:
330 if os.path.isfile(out_pth) and not repo_commit:
338 # nothing to write, don't clobber
331 # nothing to write, don't clobber
339 return
332 return
340
333
341 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
334 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
342
335
343 # remove to avoid overwriting original via hard link
336 # remove to avoid overwriting original via hard link
344 try:
337 try:
345 os.remove(out_pth)
338 os.remove(out_pth)
346 except (IOError, OSError):
339 except (IOError, OSError):
347 pass
340 pass
348 with open(out_pth, 'w') as out_file:
341 with open(out_pth, 'w') as out_file:
349 out_file.writelines([
342 out_file.writelines([
350 '# GENERATED BY setup.py\n',
343 '# GENERATED BY setup.py\n',
351 'commit = u"%s"\n' % repo_commit,
344 'commit = u"%s"\n' % repo_commit,
352 ])
345 ])
353 return MyBuildPy
346 return MyBuildPy
354
347
General Comments 0
You need to be logged in to leave comments. Login now