##// END OF EJS Templates
pyproject.toml (project.entrypoints, project.scripts): Move here from setup.py, setupbase.py
Matthias Koeppe -
Show More
@@ -1,196 +1,205 b''
1 [build-system]
1 [build-system]
2 requires = ["setuptools>=61.2"]
2 requires = ["setuptools>=61.2"]
3 # We need access to the 'setupbase' module at build time.
3 # We need access to the 'setupbase' module at build time.
4 # Hence we declare a custom build backend.
4 # Hence we declare a custom build backend.
5 build-backend = "_build_meta" # just re-exports setuptools.build_meta definitions
5 build-backend = "_build_meta" # just re-exports setuptools.build_meta definitions
6 backend-path = ["."]
6 backend-path = ["."]
7
7
8 [project]
8 [project]
9 name = "ipython"
9 name = "ipython"
10 description = "IPython: Productive Interactive Computing"
10 description = "IPython: Productive Interactive Computing"
11 keywords = ["Interactive", "Interpreter", "Shell", "Embedding"]
11 keywords = ["Interactive", "Interpreter", "Shell", "Embedding"]
12 classifiers = [
12 classifiers = [
13 "Framework :: IPython",
13 "Framework :: IPython",
14 "Framework :: Jupyter",
14 "Framework :: Jupyter",
15 "Intended Audience :: Developers",
15 "Intended Audience :: Developers",
16 "Intended Audience :: Science/Research",
16 "Intended Audience :: Science/Research",
17 "License :: OSI Approved :: BSD License",
17 "License :: OSI Approved :: BSD License",
18 "Programming Language :: Python",
18 "Programming Language :: Python",
19 "Programming Language :: Python :: 3",
19 "Programming Language :: Python :: 3",
20 "Programming Language :: Python :: 3 :: Only",
20 "Programming Language :: Python :: 3 :: Only",
21 "Topic :: System :: Shells",
21 "Topic :: System :: Shells",
22 ]
22 ]
23 requires-python = ">=3.10"
23 requires-python = ">=3.10"
24 dependencies = [
24 dependencies = [
25 'colorama; sys_platform == "win32"',
25 'colorama; sys_platform == "win32"',
26 "decorator",
26 "decorator",
27 "exceptiongroup; python_version<'3.11'",
27 "exceptiongroup; python_version<'3.11'",
28 "jedi>=0.16",
28 "jedi>=0.16",
29 "matplotlib-inline",
29 "matplotlib-inline",
30 'pexpect>4.3; sys_platform != "win32" and sys_platform != "emscripten"',
30 'pexpect>4.3; sys_platform != "win32" and sys_platform != "emscripten"',
31 "prompt_toolkit>=3.0.41,<3.1.0",
31 "prompt_toolkit>=3.0.41,<3.1.0",
32 "pygments>=2.4.0",
32 "pygments>=2.4.0",
33 "stack_data",
33 "stack_data",
34 "traitlets>=5",
34 "traitlets>=5",
35 "typing_extensions; python_version<'3.10'",
35 "typing_extensions; python_version<'3.10'",
36 ]
36 ]
37 dynamic = ["authors", "entry-points", "license", "scripts", "version"]
37 dynamic = ["authors", "license", "version"]
38
39 [project.entry-points."pygments.lexers"]
40 ipythonconsole = "IPython.lib.lexers:IPythonConsoleLexer"
41 ipython = "IPython.lib.lexers:IPythonLexer"
42 ipython3 = "IPython.lib.lexers:IPython3Lexer"
43
44 [project.scripts]
45 ipython = "IPython:start_ipython"
46 ipython3 = "IPython:start_ipython"
38
47
39 [project.readme]
48 [project.readme]
40 file = "long_description.rst"
49 file = "long_description.rst"
41 content-type = "text/x-rst"
50 content-type = "text/x-rst"
42
51
43 [project.urls]
52 [project.urls]
44 Homepage = "https://ipython.org"
53 Homepage = "https://ipython.org"
45 Documentation = "https://ipython.readthedocs.io/"
54 Documentation = "https://ipython.readthedocs.io/"
46 Funding = "https://numfocus.org/"
55 Funding = "https://numfocus.org/"
47 Source = "https://github.com/ipython/ipython"
56 Source = "https://github.com/ipython/ipython"
48 Tracker = "https://github.com/ipython/ipython/issues"
57 Tracker = "https://github.com/ipython/ipython/issues"
49
58
50 [project.optional-dependencies]
59 [project.optional-dependencies]
51 black = [
60 black = [
52 "black",
61 "black",
53 ]
62 ]
54 doc = [
63 doc = [
55 "ipykernel",
64 "ipykernel",
56 "setuptools>=18.5",
65 "setuptools>=18.5",
57 "sphinx>=1.3",
66 "sphinx>=1.3",
58 "sphinx-rtd-theme",
67 "sphinx-rtd-theme",
59 "docrepr",
68 "docrepr",
60 "matplotlib",
69 "matplotlib",
61 "stack_data",
70 "stack_data",
62 "typing_extensions",
71 "typing_extensions",
63 "exceptiongroup",
72 "exceptiongroup",
64 "ipython[test]",
73 "ipython[test]",
65 ]
74 ]
66 kernel = [
75 kernel = [
67 "ipykernel",
76 "ipykernel",
68 ]
77 ]
69 nbconvert = [
78 nbconvert = [
70 "nbconvert",
79 "nbconvert",
71 ]
80 ]
72 nbformat = [
81 nbformat = [
73 "nbformat",
82 "nbformat",
74 ]
83 ]
75 notebook = [
84 notebook = [
76 "ipywidgets",
85 "ipywidgets",
77 "notebook",
86 "notebook",
78 ]
87 ]
79 parallel = [
88 parallel = [
80 "ipyparallel",
89 "ipyparallel",
81 ]
90 ]
82 qtconsole = [
91 qtconsole = [
83 "qtconsole",
92 "qtconsole",
84 ]
93 ]
85 terminal = []
94 terminal = []
86 test = [
95 test = [
87 "pytest<8",
96 "pytest<8",
88 "pytest-asyncio<0.22",
97 "pytest-asyncio<0.22",
89 "testpath",
98 "testpath",
90 "pickleshare",
99 "pickleshare",
91 ]
100 ]
92 test_extra = [
101 test_extra = [
93 "ipython[test]",
102 "ipython[test]",
94 "curio",
103 "curio",
95 "matplotlib!=3.2.0",
104 "matplotlib!=3.2.0",
96 "nbformat",
105 "nbformat",
97 "numpy>=1.23",
106 "numpy>=1.23",
98 "pandas",
107 "pandas",
99 "trio",
108 "trio",
100 ]
109 ]
101 all = [
110 all = [
102 "ipython[black,doc,kernel,nbconvert,nbformat,notebook,parallel,qtconsole,terminal]",
111 "ipython[black,doc,kernel,nbconvert,nbformat,notebook,parallel,qtconsole,terminal]",
103 "ipython[test,test_extra]",
112 "ipython[test,test_extra]",
104 ]
113 ]
105
114
106 [tool.mypy]
115 [tool.mypy]
107 python_version = "3.10"
116 python_version = "3.10"
108 ignore_missing_imports = true
117 ignore_missing_imports = true
109 follow_imports = 'silent'
118 follow_imports = 'silent'
110 exclude = [
119 exclude = [
111 'test_\.+\.py',
120 'test_\.+\.py',
112 'IPython.utils.tests.test_wildcard',
121 'IPython.utils.tests.test_wildcard',
113 'testing',
122 'testing',
114 'tests',
123 'tests',
115 'PyColorize.py',
124 'PyColorize.py',
116 '_process_win32_controller.py',
125 '_process_win32_controller.py',
117 'IPython/core/application.py',
126 'IPython/core/application.py',
118 'IPython/core/profileapp.py',
127 'IPython/core/profileapp.py',
119 'IPython/lib/deepreload.py',
128 'IPython/lib/deepreload.py',
120 'IPython/sphinxext/ipython_directive.py',
129 'IPython/sphinxext/ipython_directive.py',
121 'IPython/terminal/ipapp.py',
130 'IPython/terminal/ipapp.py',
122 'IPython/utils/_process_win32.py',
131 'IPython/utils/_process_win32.py',
123 'IPython/utils/path.py',
132 'IPython/utils/path.py',
124 ]
133 ]
125
134
126 [tool.pytest.ini_options]
135 [tool.pytest.ini_options]
127 addopts = [
136 addopts = [
128 "--durations=10",
137 "--durations=10",
129 "-pIPython.testing.plugin.pytest_ipdoctest",
138 "-pIPython.testing.plugin.pytest_ipdoctest",
130 "--ipdoctest-modules",
139 "--ipdoctest-modules",
131 "--ignore=docs",
140 "--ignore=docs",
132 "--ignore=examples",
141 "--ignore=examples",
133 "--ignore=htmlcov",
142 "--ignore=htmlcov",
134 "--ignore=ipython_kernel",
143 "--ignore=ipython_kernel",
135 "--ignore=ipython_parallel",
144 "--ignore=ipython_parallel",
136 "--ignore=results",
145 "--ignore=results",
137 "--ignore=tmp",
146 "--ignore=tmp",
138 "--ignore=tools",
147 "--ignore=tools",
139 "--ignore=traitlets",
148 "--ignore=traitlets",
140 "--ignore=IPython/core/tests/daft_extension",
149 "--ignore=IPython/core/tests/daft_extension",
141 "--ignore=IPython/sphinxext",
150 "--ignore=IPython/sphinxext",
142 "--ignore=IPython/terminal/pt_inputhooks",
151 "--ignore=IPython/terminal/pt_inputhooks",
143 "--ignore=IPython/__main__.py",
152 "--ignore=IPython/__main__.py",
144 "--ignore=IPython/external/qt_for_kernel.py",
153 "--ignore=IPython/external/qt_for_kernel.py",
145 "--ignore=IPython/html/widgets/widget_link.py",
154 "--ignore=IPython/html/widgets/widget_link.py",
146 "--ignore=IPython/html/widgets/widget_output.py",
155 "--ignore=IPython/html/widgets/widget_output.py",
147 "--ignore=IPython/terminal/console.py",
156 "--ignore=IPython/terminal/console.py",
148 "--ignore=IPython/utils/_process_cli.py",
157 "--ignore=IPython/utils/_process_cli.py",
149 "--ignore=IPython/utils/_process_posix.py",
158 "--ignore=IPython/utils/_process_posix.py",
150 "--ignore=IPython/utils/_process_win32.py",
159 "--ignore=IPython/utils/_process_win32.py",
151 "--ignore=IPython/utils/_process_win32_controller.py",
160 "--ignore=IPython/utils/_process_win32_controller.py",
152 "--ignore=IPython/utils/daemonize.py",
161 "--ignore=IPython/utils/daemonize.py",
153 "--ignore=IPython/utils/eventful.py",
162 "--ignore=IPython/utils/eventful.py",
154 "--ignore=IPython/kernel",
163 "--ignore=IPython/kernel",
155 "--ignore=IPython/consoleapp.py",
164 "--ignore=IPython/consoleapp.py",
156 "--ignore=IPython/core/inputsplitter.py",
165 "--ignore=IPython/core/inputsplitter.py",
157 "--ignore=IPython/lib/kernel.py",
166 "--ignore=IPython/lib/kernel.py",
158 "--ignore=IPython/utils/jsonutil.py",
167 "--ignore=IPython/utils/jsonutil.py",
159 "--ignore=IPython/utils/localinterfaces.py",
168 "--ignore=IPython/utils/localinterfaces.py",
160 "--ignore=IPython/utils/log.py",
169 "--ignore=IPython/utils/log.py",
161 "--ignore=IPython/utils/signatures.py",
170 "--ignore=IPython/utils/signatures.py",
162 "--ignore=IPython/utils/traitlets.py",
171 "--ignore=IPython/utils/traitlets.py",
163 "--ignore=IPython/utils/version.py"
172 "--ignore=IPython/utils/version.py"
164 ]
173 ]
165 doctest_optionflags = [
174 doctest_optionflags = [
166 "NORMALIZE_WHITESPACE",
175 "NORMALIZE_WHITESPACE",
167 "ELLIPSIS"
176 "ELLIPSIS"
168 ]
177 ]
169 ipdoctest_optionflags = [
178 ipdoctest_optionflags = [
170 "NORMALIZE_WHITESPACE",
179 "NORMALIZE_WHITESPACE",
171 "ELLIPSIS"
180 "ELLIPSIS"
172 ]
181 ]
173 asyncio_mode = "strict"
182 asyncio_mode = "strict"
174
183
175 [tool.pyright]
184 [tool.pyright]
176 pythonPlatform="All"
185 pythonPlatform="All"
177
186
178 [tool.setuptools]
187 [tool.setuptools]
179 zip-safe = false
188 zip-safe = false
180 platforms = ["Linux", "Mac OSX", "Windows"]
189 platforms = ["Linux", "Mac OSX", "Windows"]
181 license-files = ["LICENSE"]
190 license-files = ["LICENSE"]
182 include-package-data = false
191 include-package-data = false
183
192
184 [tool.setuptools.packages.find]
193 [tool.setuptools.packages.find]
185 exclude = ["setupext"]
194 exclude = ["setupext"]
186 namespaces = false
195 namespaces = false
187
196
188 [tool.setuptools.package-data]
197 [tool.setuptools.package-data]
189 "IPython" = ["py.typed"]
198 "IPython" = ["py.typed"]
190 "IPython.core" = ["profile/README*"]
199 "IPython.core" = ["profile/README*"]
191 "IPython.core.tests" = ["*.png", "*.jpg", "daft_extension/*.py"]
200 "IPython.core.tests" = ["*.png", "*.jpg", "daft_extension/*.py"]
192 "IPython.lib.tests" = ["*.wav"]
201 "IPython.lib.tests" = ["*.wav"]
193 "IPython.testing.plugin" = ["*.txt"]
202 "IPython.testing.plugin" = ["*.txt"]
194
203
195 [tool.setuptools.dynamic]
204 [tool.setuptools.dynamic]
196 version = {attr = "IPython.core.release.__version__"}
205 version = {attr = "IPython.core.release.__version__"}
@@ -1,150 +1,141 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Setup script for IPython.
2 """Setup script for IPython.
3
3
4 Under Posix environments it works like a typical setup.py script.
4 Under Posix environments it works like a typical setup.py script.
5 Under Windows, the command sdist is not supported, since IPython
5 Under Windows, the command sdist is not supported, since IPython
6 requires utilities which are not available under Windows."""
6 requires utilities which are not available under Windows."""
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (c) 2008-2011, IPython Development Team.
9 # Copyright (c) 2008-2011, IPython Development Team.
10 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
10 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
11 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
11 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
12 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
12 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
13 #
13 #
14 # Distributed under the terms of the Modified BSD License.
14 # Distributed under the terms of the Modified BSD License.
15 #
15 #
16 # The full license is in the file COPYING.rst, distributed with this software.
16 # The full license is in the file COPYING.rst, distributed with this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 import os
19 import os
20 import sys
20 import sys
21
21
22 # **Python version check**
22 # **Python version check**
23 #
23 #
24 # This check is also made in IPython/__init__, don't forget to update both when
24 # This check is also made in IPython/__init__, don't forget to update both when
25 # changing Python version requirements.
25 # changing Python version requirements.
26 if sys.version_info < (3, 10):
26 if sys.version_info < (3, 10):
27 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
27 pip_message = 'This may be due to an out of date pip. Make sure you have pip >= 9.0.1.'
28 try:
28 try:
29 import pip
29 import pip
30 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
30 pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
31 if pip_version < (9, 0, 1) :
31 if pip_version < (9, 0, 1) :
32 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
32 pip_message = 'Your pip version is out of date, please install pip >= 9.0.1. '\
33 'pip {} detected.'.format(pip.__version__)
33 'pip {} detected.'.format(pip.__version__)
34 else:
34 else:
35 # pip is new enough - it must be something else
35 # pip is new enough - it must be something else
36 pip_message = ''
36 pip_message = ''
37 except Exception:
37 except Exception:
38 pass
38 pass
39
39
40
40
41 error = """
41 error = """
42 IPython 8.19+ supports Python 3.10 and above, following SPEC0
42 IPython 8.19+ supports Python 3.10 and above, following SPEC0
43 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
43 IPython 8.13+ supports Python 3.9 and above, following NEP 29.
44 IPython 8.0-8.12 supports Python 3.8 and above, following NEP 29.
44 IPython 8.0-8.12 supports Python 3.8 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 Python 3.7 was still supported with the 7.x branch.
49 Python 3.7 was still supported with the 7.x branch.
50
50
51 See IPython `README.rst` file for more information:
51 See IPython `README.rst` file for more information:
52
52
53 https://github.com/ipython/ipython/blob/main/README.rst
53 https://github.com/ipython/ipython/blob/main/README.rst
54
54
55 Python {py} detected.
55 Python {py} detected.
56 {pip}
56 {pip}
57 """.format(
57 """.format(
58 py=sys.version_info, pip=pip_message
58 py=sys.version_info, pip=pip_message
59 )
59 )
60
60
61 print(error, file=sys.stderr)
61 print(error, file=sys.stderr)
62 sys.exit(1)
62 sys.exit(1)
63
63
64 # At least we're on the python version we need, move on.
64 # At least we're on the python version we need, move on.
65
65
66 from setuptools import setup
66 from setuptools import setup
67
67
68 # Our own imports
68 # Our own imports
69
69
70 from setupbase import target_update, find_entry_points
70 from setupbase import target_update
71
71
72 from setupbase import (
72 from setupbase import (
73 setup_args,
73 setup_args,
74 check_package_data_first,
74 check_package_data_first,
75 find_data_files,
75 find_data_files,
76 git_prebuild,
76 git_prebuild,
77 )
77 )
78
78
79 #-------------------------------------------------------------------------------
79 #-------------------------------------------------------------------------------
80 # Handle OS specific things
80 # Handle OS specific things
81 #-------------------------------------------------------------------------------
81 #-------------------------------------------------------------------------------
82
82
83 if os.name in ('nt','dos'):
83 if os.name in ('nt','dos'):
84 os_name = 'windows'
84 os_name = 'windows'
85 else:
85 else:
86 os_name = os.name
86 os_name = os.name
87
87
88 # Under Windows, 'sdist' has not been supported. Now that the docs build with
88 # Under Windows, 'sdist' has not been supported. Now that the docs build with
89 # Sphinx it might work, but let's not turn it on until someone confirms that it
89 # Sphinx it might work, but let's not turn it on until someone confirms that it
90 # actually works.
90 # actually works.
91 if os_name == 'windows' and 'sdist' in sys.argv:
91 if os_name == 'windows' and 'sdist' in sys.argv:
92 print('The sdist command is not available under Windows. Exiting.')
92 print('The sdist command is not available under Windows. Exiting.')
93 sys.exit(1)
93 sys.exit(1)
94
94
95
95
96 #-------------------------------------------------------------------------------
96 #-------------------------------------------------------------------------------
97 # Things related to the IPython documentation
97 # Things related to the IPython documentation
98 #-------------------------------------------------------------------------------
98 #-------------------------------------------------------------------------------
99
99
100 # update the manuals when building a source dist
100 # update the manuals when building a source dist
101 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
101 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
102
102
103 # List of things to be updated. Each entry is a triplet of args for
103 # List of things to be updated. Each entry is a triplet of args for
104 # target_update()
104 # target_update()
105 to_update = [
105 to_update = [
106 (
106 (
107 "docs/man/ipython.1.gz",
107 "docs/man/ipython.1.gz",
108 ["docs/man/ipython.1"],
108 ["docs/man/ipython.1"],
109 "cd docs/man && python -m gzip --best ipython.1",
109 "cd docs/man && python -m gzip --best ipython.1",
110 ),
110 ),
111 ]
111 ]
112
112
113
113
114 [ target_update(*t) for t in to_update ]
114 [ target_update(*t) for t in to_update ]
115
115
116 #---------------------------------------------------------------------------
116 #---------------------------------------------------------------------------
117 # Find all the packages, package data, and data_files
117 # Find all the packages, package data, and data_files
118 #---------------------------------------------------------------------------
118 #---------------------------------------------------------------------------
119
119
120 data_files = find_data_files()
120 data_files = find_data_files()
121
121
122 setup_args['data_files'] = data_files
122 setup_args['data_files'] = data_files
123
123
124 #---------------------------------------------------------------------------
124 #---------------------------------------------------------------------------
125 # custom distutils commands
125 # custom distutils commands
126 #---------------------------------------------------------------------------
126 #---------------------------------------------------------------------------
127 # imports here, so they are after setuptools import if there was one
127 # imports here, so they are after setuptools import if there was one
128 from setuptools.command.sdist import sdist
128 from setuptools.command.sdist import sdist
129
129
130 setup_args['cmdclass'] = {
130 setup_args['cmdclass'] = {
131 'build_py': \
131 'build_py': \
132 check_package_data_first(git_prebuild('IPython')),
132 check_package_data_first(git_prebuild('IPython')),
133 'sdist' : git_prebuild('IPython', sdist),
133 'sdist' : git_prebuild('IPython', sdist),
134 }
134 }
135
135
136 setup_args["entry_points"] = {
137 "console_scripts": find_entry_points(),
138 "pygments.lexers": [
139 "ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer",
140 "ipython = IPython.lib.lexers:IPythonLexer",
141 "ipython3 = IPython.lib.lexers:IPython3Lexer",
142 ],
143 }
144
145 #---------------------------------------------------------------------------
136 #---------------------------------------------------------------------------
146 # Do the actual setup now
137 # Do the actual setup now
147 #---------------------------------------------------------------------------
138 #---------------------------------------------------------------------------
148
139
149 if __name__ == "__main__":
140 if __name__ == "__main__":
150 setup(**setup_args)
141 setup(**setup_args)
@@ -1,246 +1,226 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
27
28 #-------------------------------------------------------------------------------
28 #-------------------------------------------------------------------------------
29 # Useful globals and utility functions
29 # Useful globals and utility functions
30 #-------------------------------------------------------------------------------
30 #-------------------------------------------------------------------------------
31
31
32 # A few handy globals
32 # A few handy globals
33 isfile = os.path.isfile
33 isfile = os.path.isfile
34 pjoin = os.path.join
34 pjoin = os.path.join
35 repo_root = os.path.dirname(os.path.abspath(__file__))
35 repo_root = os.path.dirname(os.path.abspath(__file__))
36
36
37 def execfile(fname, globs, locs=None):
37 def execfile(fname, globs, locs=None):
38 locs = locs or globs
38 locs = locs or globs
39 with open(fname, encoding="utf-8") as f:
39 with open(fname, encoding="utf-8") as f:
40 exec(compile(f.read(), fname, "exec"), globs, locs)
40 exec(compile(f.read(), fname, "exec"), globs, locs)
41
41
42 # A little utility we'll need below, since glob() does NOT allow you to do
42 # A little utility we'll need below, since glob() does NOT allow you to do
43 # exclusion on multiple endings!
43 # exclusion on multiple endings!
44 def file_doesnt_endwith(test,endings):
44 def file_doesnt_endwith(test,endings):
45 """Return true if test is a file and its name does NOT end with any
45 """Return true if test is a file and its name does NOT end with any
46 of the strings listed in endings."""
46 of the strings listed in endings."""
47 if not isfile(test):
47 if not isfile(test):
48 return False
48 return False
49 for e in endings:
49 for e in endings:
50 if test.endswith(e):
50 if test.endswith(e):
51 return False
51 return False
52 return True
52 return True
53
53
54 #---------------------------------------------------------------------------
54 #---------------------------------------------------------------------------
55 # Basic project information
55 # Basic project information
56 #---------------------------------------------------------------------------
56 #---------------------------------------------------------------------------
57
57
58 # release.py contains version, authors, license, url, keywords, etc.
58 # release.py contains version, authors, license, url, keywords, etc.
59 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
59 execfile(pjoin(repo_root, 'IPython','core','release.py'), globals())
60
60
61 # Create a dict with the basic information
61 # Create a dict with the basic information
62 # This dict is eventually passed to setup after additional keys are added.
62 # This dict is eventually passed to setup after additional keys are added.
63 setup_args = dict(
63 setup_args = dict(
64 author = author,
64 author = author,
65 author_email = author_email,
65 author_email = author_email,
66 license = license,
66 license = license,
67 )
67 )
68
68
69 #---------------------------------------------------------------------------
69 #---------------------------------------------------------------------------
70 # Check package data
70 # Check package data
71 #---------------------------------------------------------------------------
71 #---------------------------------------------------------------------------
72
72
73 def check_package_data(package_data):
73 def check_package_data(package_data):
74 """verify that package_data globs make sense"""
74 """verify that package_data globs make sense"""
75 print("checking package data")
75 print("checking package data")
76 for pkg, data in package_data.items():
76 for pkg, data in package_data.items():
77 pkg_root = pjoin(*pkg.split('.'))
77 pkg_root = pjoin(*pkg.split('.'))
78 for d in data:
78 for d in data:
79 path = pjoin(pkg_root, d)
79 path = pjoin(pkg_root, d)
80 if '*' in path:
80 if '*' in path:
81 assert len(glob(path)) > 0, "No files match pattern %s" % path
81 assert len(glob(path)) > 0, "No files match pattern %s" % path
82 else:
82 else:
83 assert os.path.exists(path), "Missing package data: %s" % path
83 assert os.path.exists(path), "Missing package data: %s" % path
84
84
85
85
86 def check_package_data_first(command):
86 def check_package_data_first(command):
87 """decorator for checking package_data before running a given command
87 """decorator for checking package_data before running a given command
88
88
89 Probably only needs to wrap build_py
89 Probably only needs to wrap build_py
90 """
90 """
91 class DecoratedCommand(command):
91 class DecoratedCommand(command):
92 def run(self):
92 def run(self):
93 check_package_data(self.package_data)
93 check_package_data(self.package_data)
94 command.run(self)
94 command.run(self)
95 return DecoratedCommand
95 return DecoratedCommand
96
96
97
97
98 #---------------------------------------------------------------------------
98 #---------------------------------------------------------------------------
99 # Find data files
99 # Find data files
100 #---------------------------------------------------------------------------
100 #---------------------------------------------------------------------------
101
101
102 def find_data_files():
102 def find_data_files():
103 """
103 """
104 Find IPython's data_files.
104 Find IPython's data_files.
105
105
106 Just man pages at this point.
106 Just man pages at this point.
107 """
107 """
108
108
109 if "freebsd" in sys.platform:
109 if "freebsd" in sys.platform:
110 manpagebase = pjoin('man', 'man1')
110 manpagebase = pjoin('man', 'man1')
111 else:
111 else:
112 manpagebase = pjoin('share', 'man', 'man1')
112 manpagebase = pjoin('share', 'man', 'man1')
113
113
114 # Simple file lists can be made by hand
114 # Simple file lists can be made by hand
115 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
115 manpages = [f for f in glob(pjoin('docs','man','*.1.gz')) if isfile(f)]
116 if not manpages:
116 if not manpages:
117 # When running from a source tree, the manpages aren't gzipped
117 # When running from a source tree, the manpages aren't gzipped
118 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
118 manpages = [f for f in glob(pjoin('docs','man','*.1')) if isfile(f)]
119
119
120 # And assemble the entire output list
120 # And assemble the entire output list
121 data_files = [ (manpagebase, manpages) ]
121 data_files = [ (manpagebase, manpages) ]
122
122
123 return data_files
123 return data_files
124
124
125
125
126 # The two functions below are copied from IPython.utils.path, so we don't need
126 # The two functions below are copied from IPython.utils.path, so we don't need
127 # to import IPython during setup, which fails on Python 3.
127 # to import IPython during setup, which fails on Python 3.
128
128
129 def target_outdated(target,deps):
129 def target_outdated(target,deps):
130 """Determine whether a target is out of date.
130 """Determine whether a target is out of date.
131
131
132 target_outdated(target,deps) -> 1/0
132 target_outdated(target,deps) -> 1/0
133
133
134 deps: list of filenames which MUST exist.
134 deps: list of filenames which MUST exist.
135 target: single filename which may or may not exist.
135 target: single filename which may or may not exist.
136
136
137 If target doesn't exist or is older than any file listed in deps, return
137 If target doesn't exist or is older than any file listed in deps, return
138 true, otherwise return false.
138 true, otherwise return false.
139 """
139 """
140 try:
140 try:
141 target_time = os.path.getmtime(target)
141 target_time = os.path.getmtime(target)
142 except os.error:
142 except os.error:
143 return 1
143 return 1
144 for dep in deps:
144 for dep in deps:
145 dep_time = os.path.getmtime(dep)
145 dep_time = os.path.getmtime(dep)
146 if dep_time > target_time:
146 if dep_time > target_time:
147 #print "For target",target,"Dep failed:",dep # dbg
147 #print "For target",target,"Dep failed:",dep # dbg
148 #print "times (dep,tar):",dep_time,target_time # dbg
148 #print "times (dep,tar):",dep_time,target_time # dbg
149 return 1
149 return 1
150 return 0
150 return 0
151
151
152
152
153 def target_update(target,deps,cmd):
153 def target_update(target,deps,cmd):
154 """Update a target with a given command given a list of dependencies.
154 """Update a target with a given command given a list of dependencies.
155
155
156 target_update(target,deps,cmd) -> runs cmd if target is outdated.
156 target_update(target,deps,cmd) -> runs cmd if target is outdated.
157
157
158 This is just a wrapper around target_outdated() which calls the given
158 This is just a wrapper around target_outdated() which calls the given
159 command if target is outdated."""
159 command if target is outdated."""
160
160
161 if target_outdated(target,deps):
161 if target_outdated(target,deps):
162 os.system(cmd)
162 os.system(cmd)
163
163
164 #---------------------------------------------------------------------------
164 #---------------------------------------------------------------------------
165 # Find scripts
166 #---------------------------------------------------------------------------
167
168 def find_entry_points():
169 """Defines the command line entry points for IPython
170
171 This always uses setuptools-style entry points. When setuptools is not in
172 use, our own build_scripts_entrypt class below parses these and builds
173 command line scripts.
174
175 Each of our entry points gets a plain name, e.g. ipython, and a name
176 suffixed with the Python major version number, e.g. ipython3.
177 """
178 ep = [
179 'ipython%s = IPython:start_ipython',
180 ]
181 major_suffix = str(sys.version_info[0])
182 return [e % "" for e in ep] + [e % major_suffix for e in ep]
183
184 #---------------------------------------------------------------------------
185 # VCS related
165 # VCS related
186 #---------------------------------------------------------------------------
166 #---------------------------------------------------------------------------
187
167
188 def git_prebuild(pkg_dir, build_cmd=build_py):
168 def git_prebuild(pkg_dir, build_cmd=build_py):
189 """Return extended build or sdist command class for recording commit
169 """Return extended build or sdist command class for recording commit
190
170
191 records git commit in IPython.utils._sysinfo.commit
171 records git commit in IPython.utils._sysinfo.commit
192
172
193 for use in IPython.utils.sysinfo.sys_info() calls after installation.
173 for use in IPython.utils.sysinfo.sys_info() calls after installation.
194 """
174 """
195
175
196 class MyBuildPy(build_cmd):
176 class MyBuildPy(build_cmd):
197 ''' Subclass to write commit data into installation tree '''
177 ''' Subclass to write commit data into installation tree '''
198 def run(self):
178 def run(self):
199 # loose as `.dev` is suppose to be invalid
179 # loose as `.dev` is suppose to be invalid
200 print("check version number")
180 print("check version number")
201 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
181 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
202 if not loose_pep440re.match(version):
182 if not loose_pep440re.match(version):
203 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
183 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
204
184
205
185
206 build_cmd.run(self)
186 build_cmd.run(self)
207 # this one will only fire for build commands
187 # this one will only fire for build commands
208 if hasattr(self, 'build_lib'):
188 if hasattr(self, 'build_lib'):
209 self._record_commit(self.build_lib)
189 self._record_commit(self.build_lib)
210
190
211 def make_release_tree(self, base_dir, files):
191 def make_release_tree(self, base_dir, files):
212 # this one will fire for sdist
192 # this one will fire for sdist
213 build_cmd.make_release_tree(self, base_dir, files)
193 build_cmd.make_release_tree(self, base_dir, files)
214 self._record_commit(base_dir)
194 self._record_commit(base_dir)
215
195
216 def _record_commit(self, base_dir):
196 def _record_commit(self, base_dir):
217 import subprocess
197 import subprocess
218 proc = subprocess.Popen('git rev-parse --short HEAD',
198 proc = subprocess.Popen('git rev-parse --short HEAD',
219 stdout=subprocess.PIPE,
199 stdout=subprocess.PIPE,
220 stderr=subprocess.PIPE,
200 stderr=subprocess.PIPE,
221 shell=True)
201 shell=True)
222 repo_commit, _ = proc.communicate()
202 repo_commit, _ = proc.communicate()
223 repo_commit = repo_commit.strip().decode("ascii")
203 repo_commit = repo_commit.strip().decode("ascii")
224
204
225 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
205 out_pth = pjoin(base_dir, pkg_dir, 'utils', '_sysinfo.py')
226 if os.path.isfile(out_pth) and not repo_commit:
206 if os.path.isfile(out_pth) and not repo_commit:
227 # nothing to write, don't clobber
207 # nothing to write, don't clobber
228 return
208 return
229
209
230 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
210 print("writing git commit '%s' to %s" % (repo_commit, out_pth))
231
211
232 # remove to avoid overwriting original via hard link
212 # remove to avoid overwriting original via hard link
233 try:
213 try:
234 os.remove(out_pth)
214 os.remove(out_pth)
235 except (IOError, OSError):
215 except (IOError, OSError):
236 pass
216 pass
237 with open(out_pth, "w", encoding="utf-8") as out_file:
217 with open(out_pth, "w", encoding="utf-8") as out_file:
238 out_file.writelines(
218 out_file.writelines(
239 [
219 [
240 "# GENERATED BY setup.py\n",
220 "# GENERATED BY setup.py\n",
241 'commit = "%s"\n' % repo_commit,
221 'commit = "%s"\n' % repo_commit,
242 ]
222 ]
243 )
223 )
244
224
245 return MyBuildPy
225 return MyBuildPy
246
226
General Comments 0
You need to be logged in to leave comments. Login now