Update upstream source from tag 'upstream/4.5.0'
Update to upstream version '4.5.0'
with Debian dir 5d10305e942d868c053bc8aa18db5ccb849b0c5f
Gordon Ball
4 years ago
2 | 2 | sudo: false |
3 | 3 | python: |
4 | 4 | - nightly |
5 | - 3.6 | |
6 | - 3.5 | |
7 | - 3.4 | |
8 | - 3.3 | |
9 | - 2.7 | |
5 | - "3.6" | |
6 | - "3.5" | |
7 | - "3.4" | |
8 | - "2.7" | |
10 | 9 | before_install: |
11 | - pip install --upgrade setuptools pip | |
10 | - pip install --upgrade pip | |
11 | - pip install --upgrade setuptools | |
12 | 12 | install: |
13 | 13 | - pip install -r dev-requirements.txt . |
14 | 14 | script: |
5 | 5 | # Documentation |
6 | 6 | graft docs |
7 | 7 | graft examples |
8 | ||
9 | # Test files | |
10 | graft jupyter_core/tests/dotipython | |
11 | graft jupyter_core/tests/dotipython_empty | |
8 | 12 | |
9 | 13 | # docs subdirs we want to skip |
10 | 14 | prune docs/_build |
0 | 0 | Changes in jupyter-core |
1 | 1 | ======================= |
2 | ||
3 | 4.5 | |
4 | --- | |
5 | ||
6 | 4.5.0 | |
7 | ~~~~~ | |
8 | ||
9 | `on | |
10 | GitHub <https://github.com/jupyter/jupyter_core/releases/tag/4.5.0>`__ | |
11 | ||
12 | - ``jupyter --version`` now tries to show the version number of various other | |
13 | installed Jupyter packages, not just ``jupyter_core`` (:ghpull:`136`). | |
14 | This will hopefully make it clearer that there are various packages with | |
15 | their own version numbers. | |
16 | - Allow a :envvar:`JUPYTER_CONFIG_PATH` environment variable to specify a | |
17 | search path of additional locations for config (:ghpull:`139`). | |
18 | - ``jupyter subcommand`` no longer modifies the :envvar:`PATH` environment | |
19 | variable when it runs ``jupyter-subcommand`` (:ghpull:`148`). | |
20 | - Jupyter's 'runtime' directory no longer uses ``XDG_RUNTIME_DIR`` | |
21 | (:ghpull:`143`). While it has some attractive properties, it has led to | |
22 | various problems; see the pull request for details. | |
23 | - Fix ``JupyterApp`` to respect the ``raise_config_file_errors`` traitlet | |
24 | (:ghpull:`149`). | |
25 | - Various improvements to the bash completion scripts in this repository | |
26 | (:ghpull:`125`, :ghpull:`126`). | |
27 | - The ``setup.py`` script now always uses setuptools, like most other Jupyter | |
28 | projects (:ghpull:`147`). | |
29 | - The LICENSE file is included in wheels (:ghpull:`133`). | |
2 | 30 | |
3 | 31 | 4.4 |
4 | 32 | --- |
3 | 3 | autoload -Uz bashcompinit && bashcompinit |
4 | 4 | fi |
5 | 5 | |
6 | _jupyter() | |
6 | _jupyter_get_flags() | |
7 | 7 | { |
8 | 8 | local url=$1 |
9 | 9 | local var=$2 |
10 | 10 | local dash=$3 |
11 | if [[ "$url $var" == $__jupyter ]]; then | |
12 | opts=$__jupyter | |
11 | if [[ "$url $var" == $__jupyter_complete_last ]]; then | |
12 | opts=$__jupyter_complete_last_res | |
13 | 13 | return |
14 | 14 | fi |
15 | ||
16 | if [ -z $1 ]; then | |
17 | opts=$(jupyter --help | sed -n 's/^ -/-/p' |sed -e 's/, /\n/' |sed -e 's/\(-[[:alnum:]_-]*\).*/\1/') | |
18 | else | |
15 | 19 | # matplotlib and profile don't need the = and the |
16 | 20 | # version without simplifies the special cased completion |
17 | opts=$(jupyter ${url} --help-all | grep -E "^-{1,2}[^-]" | sed -e "s/<.*//" -e "s/[^=]$/& /" -e "$ s/^/\n-h\n--help\n--help-all\n/") | |
18 | __jupyter="$url $var" | |
19 | __jupyter="$opts" | |
21 | opts=$(jupyter ${url} --help-all | grep -E "^-{1,2}[^-]" | sed -e "s/<.*//" -e "s/[^=]$/& /" -e "$ s/^/\n-h\n--help\n--help-all\n/") | |
22 | fi | |
23 | __jupyter_complete_last="$url $var" | |
24 | __jupyter_complete_last_res="$opts" | |
20 | 25 | } |
21 | 26 | |
22 | 27 | _jupyter() |
25 | 30 | local prev=${COMP_WORDS[COMP_CWORD - 1]} |
26 | 31 | local subcommands="notebook qtconsole console nbconvert kernelspec trust " |
27 | 32 | local opts="help" |
28 | if [ -z "$__jupyter" ]; then | |
29 | _jupyter baseopts | |
30 | __jupyter="${opts}" | |
31 | fi | |
32 | local baseopts="$__jupyter" | |
33 | 33 | local mode="" |
34 | 34 | for i in "${COMP_WORDS[@]}"; do |
35 | 35 | [ "$cur" = "$i" ] && break |
46 | 46 | if [[ ${cur} == -* ]]; then |
47 | 47 | case $mode in |
48 | 48 | "notebook" | "qtconsole" | "console" | "nbconvert") |
49 | _jupyter $mode | |
50 | opts=$"${opts} ${baseopts}" | |
49 | _jupyter_get_flags $mode | |
50 | opts=$"${opts}" | |
51 | 51 | ;; |
52 | 52 | "kernelspec") |
53 | 53 | if [[ $COMP_CWORD -ge 3 ]]; then |
54 | 54 | # 'history trim' and 'history clear' covered by next line |
55 | _jupyter $mode\ "${COMP_WORDS[2]}" | |
55 | _jupyter_get_flags $mode\ "${COMP_WORDS[2]}" | |
56 | 56 | else |
57 | _jupyter $mode | |
57 | _jupyter_get_flags $mode | |
58 | 58 | |
59 | 59 | fi |
60 | 60 | opts=$"${opts}" |
61 | 61 | ;; |
62 | 62 | *) |
63 | opts=$baseopts | |
63 | _jupyter_get_flags | |
64 | 64 | esac |
65 | 65 | # don't drop the trailing space |
66 | 66 | local IFS=$'\t\n' |
81 | 81 | local sub=$(echo $subcommands | sed -e "s/ / \t/g") |
82 | 82 | COMPREPLY=( $(compgen -W "${sub}" -- ${cur}) ) |
83 | 83 | else |
84 | local IFS=$'\n' | |
85 | compopt -o filenames | |
84 | 86 | COMPREPLY=( $(compgen -f -- ${cur}) ) |
85 | 87 | fi |
86 | 88 | fi |
64 | 64 | |
65 | 65 | aliases = base_aliases |
66 | 66 | flags = base_flags |
67 | ||
67 | ||
68 | 68 | def _log_level_default(self): |
69 | 69 | return logging.INFO |
70 | 70 | |
202 | 202 | except ConfigFileNotFound: |
203 | 203 | self.log.debug("Config file not found, skipping: %s", config_file_name) |
204 | 204 | except Exception: |
205 | # For testing purposes. | |
206 | if not suppress_errors: | |
205 | # Reraise errors for testing purposes, or if set in | |
206 | # self.raise_config_file_errors | |
207 | if (not suppress_errors) or self.raise_config_file_errors: | |
207 | 208 | raise |
208 | self.log.warn("Error loading config file: %s" % | |
209 | self.log.warning("Error loading config file: %s" % | |
209 | 210 | config_file_name, exc_info=True) |
210 | 211 | |
211 | 212 | # subcommand-related |
14 | 14 | import sys |
15 | 15 | from subprocess import Popen |
16 | 16 | |
17 | try: | |
18 | # py3 | |
19 | from shutil import which | |
20 | except ImportError: | |
21 | from .utils.shutil_which import which | |
22 | ||
17 | 23 | from . import paths |
18 | 24 | from .version import __version__ |
19 | 25 | |
20 | 26 | class JupyterParser(argparse.ArgumentParser): |
21 | ||
27 | ||
22 | 28 | @property |
23 | 29 | def epilog(self): |
24 | 30 | """Add subcommands to epilog on request |
25 | ||
31 | ||
26 | 32 | Avoids searching PATH for subcommands unless help output is requested. |
27 | 33 | """ |
28 | 34 | return 'Available subcommands: %s' % ' '.join(list_subcommands()) |
29 | ||
35 | ||
30 | 36 | @epilog.setter |
31 | 37 | def epilog(self, x): |
32 | 38 | """Ignore epilog set in Parser.__init__""" |
41 | 47 | group.add_argument('--version', action='store_true', |
42 | 48 | help="show the jupyter command's version and exit") |
43 | 49 | group.add_argument('subcommand', type=str, nargs='?', help='the subcommand to launch') |
44 | ||
50 | ||
45 | 51 | group.add_argument('--config-dir', action='store_true', |
46 | 52 | help="show Jupyter config dir") |
47 | 53 | group.add_argument('--data-dir', action='store_true', |
52 | 58 | help="show all Jupyter paths. Add --json for machine-readable format.") |
53 | 59 | parser.add_argument('--json', action='store_true', |
54 | 60 | help="output paths as machine-readable json") |
55 | ||
61 | ||
56 | 62 | return parser |
57 | 63 | |
58 | 64 | |
59 | 65 | def list_subcommands(): |
60 | 66 | """List all jupyter subcommands |
61 | ||
67 | ||
62 | 68 | searches PATH for `jupyter-name` |
63 | ||
69 | ||
64 | 70 | Returns a list of jupyter's subcommand names, without the `jupyter-` prefix. |
65 | 71 | Nested children (e.g. jupyter-sub-subsub) are not included. |
66 | 72 | """ |
88 | 94 | |
89 | 95 | def _execvp(cmd, argv): |
90 | 96 | """execvp, except on Windows where it uses Popen |
91 | ||
97 | ||
92 | 98 | Python provides execvp on Windows, but its behavior is problematic (Python bug#9148). |
93 | 99 | """ |
94 | 100 | if sys.platform.startswith('win'): |
112 | 118 | os.execvp(cmd, argv) |
113 | 119 | |
114 | 120 | |
121 | def _jupyter_abspath(subcommand): | |
122 | """This method get the abspath of a specified jupyter-subcommand with no | |
123 | changes on ENV. | |
124 | """ | |
125 | # get env PATH with self | |
126 | search_path = os.pathsep.join(_path_with_self()) | |
127 | # get the abs path for the jupyter-<subcommand> | |
128 | jupyter_subcommand = 'jupyter-{}'.format(subcommand) | |
129 | abs_path = which(jupyter_subcommand, path=search_path) | |
130 | if abs_path is None: | |
131 | raise Exception( | |
132 | 'Jupyter command `{}` not found.'.format(jupyter_subcommand) | |
133 | ) | |
134 | ||
135 | if not os.access(abs_path, os.X_OK): | |
136 | raise Exception( | |
137 | 'Jupyter command `{}` is not executable.'.format(jupyter_subcommand) | |
138 | ) | |
139 | ||
140 | return abs_path | |
141 | ||
142 | ||
115 | 143 | def _path_with_self(): |
116 | 144 | """Put `jupyter`'s dir at the front of PATH |
117 | ||
145 | ||
118 | 146 | Ensures that /path/to/jupyter subcommand |
119 | 147 | will do /path/to/jupyter-subcommand |
120 | 148 | even if /other/jupyter-subcommand is ahead of it on PATH |
127 | 155 | path_list = (os.environ.get('PATH') or os.defpath).split(os.pathsep) |
128 | 156 | for script in scripts: |
129 | 157 | bindir = os.path.dirname(script) |
130 | if (os.path.isdir(bindir) | |
131 | and os.access(script, os.X_OK) # only if it's a script | |
158 | if ( | |
159 | os.path.isdir(bindir) | |
160 | and os.access(script, os.X_OK) # only if it's a script | |
132 | 161 | ): |
133 | 162 | # ensure executable's dir is on PATH |
134 | 163 | # avoids missing subcommands when jupyter is run via absolute path |
135 | 164 | path_list.insert(0, bindir) |
136 | os.environ['PATH'] = os.pathsep.join(path_list) | |
137 | 165 | return path_list |
138 | 166 | |
139 | 167 | |
140 | 168 | def main(): |
141 | _path_with_self() # ensure executable is on PATH | |
142 | 169 | if len(sys.argv) > 1 and not sys.argv[1].startswith('-'): |
143 | 170 | # Don't parse if a subcommand is given |
144 | 171 | # Avoids argparse gobbling up args passed to subcommand, such as `-h`. |
148 | 175 | args, opts = parser.parse_known_args() |
149 | 176 | subcommand = args.subcommand |
150 | 177 | if args.version: |
151 | print(__version__) | |
178 | print('{:<17}:'.format('jupyter core'), __version__) | |
179 | for package, name in [ | |
180 | ('notebook', 'jupyter-notebook'), | |
181 | ('qtconsole', 'qtconsole'), | |
182 | ('IPython', 'ipython'), | |
183 | ('ipykernel', 'ipykernel'), | |
184 | ('jupyter_client', 'jupyter client'), | |
185 | ('jupyterlab', 'jupyter lab'), | |
186 | ('nbconvert', 'nbconvert'), | |
187 | ('ipywidgets', 'ipywidgets'), | |
188 | ('nbformat', 'nbformat'), | |
189 | ('traitlets', 'traitlets'), | |
190 | ]: | |
191 | version = None | |
192 | try: | |
193 | mod = __import__(package) | |
194 | version = mod.__version__ | |
195 | except ImportError: | |
196 | version = 'not installed' | |
197 | print('{:<17}:'.format(name), version) | |
152 | 198 | return |
153 | 199 | if args.json and not args.paths: |
154 | 200 | sys.exit("--json is only used with --paths") |
175 | 221 | for p in path: |
176 | 222 | print(' ' + p) |
177 | 223 | return |
178 | ||
224 | ||
179 | 225 | if not subcommand: |
180 | 226 | parser.print_usage(file=sys.stderr) |
181 | 227 | sys.exit("subcommand is required") |
182 | ||
183 | command = 'jupyter-' + subcommand | |
228 | ||
229 | command = _jupyter_abspath(subcommand) | |
230 | ||
184 | 231 | try: |
185 | 232 | _execvp(command, sys.argv[1:]) |
186 | 233 | except OSError as e: |
89 | 89 | |
90 | 90 | Returns JUPYTER_RUNTIME_DIR if defined. |
91 | 91 | |
92 | Respects XDG_RUNTIME_DIR on non-OS X, non-Windows, | |
93 | falls back on data_dir/runtime otherwise. | |
92 | The default is now (data_dir)/runtime on all platforms; | |
93 | we no longer use XDG_RUNTIME_DIR after various problems. | |
94 | 94 | """ |
95 | 95 | env = os.environ |
96 | 96 | |
97 | 97 | if env.get('JUPYTER_RUNTIME_DIR'): |
98 | 98 | return env['JUPYTER_RUNTIME_DIR'] |
99 | ||
100 | if sys.platform == 'darwin': | |
101 | return pjoin(jupyter_data_dir(), 'runtime') | |
102 | elif os.name == 'nt': | |
103 | return pjoin(jupyter_data_dir(), 'runtime') | |
104 | else: | |
105 | # Linux, non-OS X Unix, AIX, etc. | |
106 | xdg = env.get("XDG_RUNTIME_DIR", None) | |
107 | if xdg: | |
108 | return pjoin(xdg, 'jupyter') | |
109 | return pjoin(jupyter_data_dir(), 'runtime') | |
99 | ||
100 | return pjoin(jupyter_data_dir(), 'runtime') | |
110 | 101 | |
111 | 102 | |
112 | 103 | if os.name == 'nt': |
129 | 120 | |
130 | 121 | JUPYTER_PATH environment variable has highest priority. |
131 | 122 | |
132 | If *subdirs are given, that subdirectory will be added to each element. | |
123 | If ``*subdirs`` are given, that subdirectory will be added to each element. | |
133 | 124 | |
134 | 125 | Examples: |
135 | 126 | |
182 | 173 | if os.environ.get('JUPYTER_NO_CONFIG'): |
183 | 174 | return paths |
184 | 175 | |
176 | # highest priority is env | |
177 | if os.environ.get('JUPYTER_CONFIG_PATH'): | |
178 | paths.extend( | |
179 | p.rstrip(os.sep) | |
180 | for p in os.environ['JUPYTER_CONFIG_PATH'].split(os.pathsep) | |
181 | ) | |
182 | ||
183 | # then sys.prefix | |
185 | 184 | for p in ENV_CONFIG_PATH: |
186 | 185 | if p not in SYSTEM_CONFIG_PATH: |
187 | 186 | paths.append(p) |
93 | 93 | shutil.rmtree(config_dir) |
94 | 94 | shutil.rmtree(wd) |
95 | 95 | |
96 | def test_load_bad_config(): | |
97 | config_dir = mkdtemp() | |
98 | wd = mkdtemp() | |
99 | with open(pjoin(config_dir, 'dummy_app_config.py'), 'w') as f: | |
100 | f.write('c.DummyApp.m = "a\n') # Syntax error | |
101 | with patch.object(py3compat, 'getcwd', lambda : wd): | |
102 | with pytest.raises(SyntaxError): | |
103 | app = DummyApp(config_dir=config_dir) | |
104 | app.raise_config_file_errors=True | |
105 | app.initialize([]) | |
106 | ||
107 | shutil.rmtree(config_dir) | |
108 | shutil.rmtree(wd) | |
109 |
155 | 155 | |
156 | 156 | with linux, xdg: |
157 | 157 | runtime = jupyter_runtime_dir() |
158 | assert runtime == pjoin(xdg_env['XDG_RUNTIME_DIR'], 'jupyter') | |
158 | assert runtime == pjoin(xdg_env['XDG_DATA_HOME'], 'jupyter', 'runtime') | |
159 | 159 | |
160 | 160 | |
161 | 161 | def test_jupyter_path(): |
0 | 0 | # Copyright (c) Jupyter Development Team. |
1 | 1 | # Distributed under the terms of the Modified BSD License. |
2 | 2 | |
3 | version_info = (4, 4, 0) | |
3 | version_info = (4, 5, 0) | |
4 | 4 | |
5 | 5 | __version__ = '.'.join(map(str, version_info)) |
0 | [metadata] | |
1 | name = jupyter_core | |
2 | version = attr: jupyter_core.version.__version__ | |
3 | description = Jupyter core package. A base package on which Jupyter projects rely. | |
4 | long_description = There is no reason to install this package on its own. | |
5 | author = Jupyter Development Team | |
6 | author_email = jupyter@googlegroups.org | |
7 | url = https://jupyter.org | |
8 | license = BSD | |
9 | license_file = COPYING.md | |
10 | classifiers = | |
11 | Intended Audience :: Developers | |
12 | Intended Audience :: System Administrators | |
13 | Intended Audience :: Science/Research | |
14 | License :: OSI Approved :: BSD License | |
15 | Programming Language :: Python | |
16 | Programming Language :: Python :: 2 | |
17 | Programming Language :: Python :: 2.7 | |
18 | Programming Language :: Python :: 3 | |
19 | Programming Language :: Python :: 3.3 | |
20 | Programming Language :: Python :: 3.4 | |
21 | ||
22 | [options] | |
23 | py_modules = jupyter | |
24 | packages = jupyter_core, jupyter_core.utils, jupyter_core.tests | |
25 | include_package_data = True | |
26 | python_requires = >=2.7, !=3.0, !=3.1, !=3.2 | |
27 | install_requires = | |
28 | traitlets | |
29 | ||
30 | [options.entry_points] | |
31 | console_scripts = | |
32 | jupyter = jupyter_core.command:main | |
33 | jupyter-migrate = jupyter_core.migrate:main | |
34 | jupyter-troubleshoot = jupyter_core.troubleshoot:main | |
35 | ||
0 | 36 | [bdist_wheel] |
1 | 37 | universal=1 |
2 | 2 | |
3 | 3 | # Copyright (c) Juptyer Development Team. |
4 | 4 | # Distributed under the terms of the Modified BSD License. |
5 | ||
6 | #----------------------------------------------------------------------------- | |
7 | # Minimal Python version sanity check (from IPython) | |
8 | #----------------------------------------------------------------------------- | |
9 | from __future__ import print_function | |
10 | ||
11 | import os | |
12 | 5 | import sys |
13 | from glob import glob | |
14 | ||
15 | v = sys.version_info | |
16 | if v[:2] < (2,7) or (v[:2] > (3,) and v[:2] < (3,3)): | |
17 | error = "ERROR: Jupyter requires Python version 2.7 or 3.3 or above." | |
18 | print(error, file=sys.stderr) | |
19 | sys.exit(1) | |
20 | ||
21 | # At least we're on the python version we need, move on. | |
22 | ||
23 | from distutils.core import setup | |
24 | ||
25 | pjoin = os.path.join | |
26 | here = os.path.abspath(os.path.dirname(__file__)) | |
27 | ||
28 | # Get the current package version. | |
29 | version_ns = {} | |
30 | with open(pjoin(here, 'jupyter_core', 'version.py')) as f: | |
31 | exec(f.read(), {}, version_ns) | |
32 | ||
33 | def find_package_data(): | |
34 | """Find package data (testing support files)""" | |
35 | package_data = {} | |
36 | package_data['jupyter_core.tests'] = test_files = [] | |
37 | test_dir = pjoin('jupyter_core', 'tests') | |
38 | prefix_len = len(test_dir) + len(os.sep) | |
39 | for parent, dirs, files in os.walk(test_dir): | |
40 | if files: | |
41 | test_files.append(pjoin(parent[prefix_len:], '*.*')) | |
42 | ||
43 | return package_data | |
44 | ||
45 | package_data = find_package_data() | |
46 | ||
47 | setup_args = dict( | |
48 | name = 'jupyter_core', | |
49 | version = version_ns['__version__'], | |
50 | packages = ['jupyter_core', | |
51 | 'jupyter_core.utils', | |
52 | 'jupyter_core.tests'], | |
53 | py_modules = ['jupyter'], | |
54 | package_data = package_data, | |
55 | scripts = glob(pjoin('scripts', '*')), | |
56 | description = "Jupyter core package. A base package on which Jupyter projects rely.", | |
57 | long_description = """There is no reason to install this package on its own.""", | |
58 | author = "Jupyter Development Team", | |
59 | author_email = "jupyter@googlegroups.org", | |
60 | url = "https://jupyter.org", | |
61 | license = "BSD", | |
62 | classifiers = [ | |
63 | 'Intended Audience :: Developers', | |
64 | 'Intended Audience :: System Administrators', | |
65 | 'Intended Audience :: Science/Research', | |
66 | 'License :: OSI Approved :: BSD License', | |
67 | 'Programming Language :: Python', | |
68 | 'Programming Language :: Python :: 2', | |
69 | 'Programming Language :: Python :: 2.7', | |
70 | 'Programming Language :: Python :: 3', | |
71 | 'Programming Language :: Python :: 3.3', | |
72 | 'Programming Language :: Python :: 3.4', | |
73 | ], | |
74 | ) | |
75 | ||
76 | if any(arg.startswith('bdist') for arg in sys.argv): | |
77 | import setuptools | |
78 | ||
79 | setuptools_args = {} | |
80 | ||
81 | setuptools_args['install_requires'] = [ | |
82 | 'traitlets', | |
83 | ] | |
84 | ||
85 | setuptools_args['entry_points'] = { | |
86 | 'console_scripts': [ | |
87 | 'jupyter = jupyter_core.command:main', | |
88 | 'jupyter-migrate = jupyter_core.migrate:main', | |
89 | 'jupyter-troubleshoot = jupyter_core.troubleshoot:main', | |
90 | ] | |
91 | } | |
92 | ||
93 | # setuptools requirements | |
94 | if 'setuptools' in sys.modules: | |
95 | setup_args.update(setuptools_args) | |
96 | setup_args.pop('scripts', None) | |
6 | from setuptools import setup | |
7 | from setuptools.command.bdist_egg import bdist_egg | |
97 | 8 | |
98 | 9 | |
99 | if __name__ == '__main__': | |
100 | setup(**setup_args) | |
10 | class bdist_egg_disabled(bdist_egg): | |
11 | """Disabled version of bdist_egg | |
12 | ||
13 | Prevents setup.py install from performing setuptools' default easy_install, | |
14 | which it should never ever do. | |
15 | """ | |
16 | def run(self): | |
17 | sys.exit("Aborting implicit building of eggs. Use `pip install .` to install from source.") | |
18 | ||
19 | ||
20 | # Loads metadata and options from setup.cfg: | |
21 | setup( | |
22 | cmdclass={ | |
23 | 'bdist_egg': bdist_egg if 'bdist_egg' in sys.argv else bdist_egg_disabled, | |
24 | }, | |
25 | ) |