2019-11-25 10:02:23 +03:00
|
|
|
# Copyright (c) Microsoft Corporation.
|
|
|
|
# Licensed under the MIT license.
|
2018-09-07 13:21:46 +03:00
|
|
|
|
2020-10-26 18:21:59 +03:00
|
|
|
"""
|
|
|
|
Script for installation and distribution.
|
|
|
|
|
|
|
|
You can use environment variable `NNI_RELEASE` to set release version.
|
|
|
|
|
|
|
|
If release version is not set, default to a development build whose version string will be `999.dev0`.
|
|
|
|
|
|
|
|
|
2021-08-03 17:22:16 +03:00
|
|
|
## Prepare Environment ##
|
|
|
|
|
|
|
|
Install development dependencies:
|
|
|
|
|
|
|
|
$ pip install -U -r dependencies/setup.txt
|
|
|
|
$ pip install -r dependencies/develop.txt
|
|
|
|
|
|
|
|
|
2020-10-26 18:21:59 +03:00
|
|
|
## Development ##
|
|
|
|
|
|
|
|
Build and install for development:
|
|
|
|
|
|
|
|
$ python setup.py develop
|
|
|
|
|
|
|
|
Uninstall:
|
|
|
|
|
|
|
|
$ pip uninstall nni
|
|
|
|
|
2022-03-19 11:47:40 +03:00
|
|
|
Remove generated files: (use "--all" to remove built wheel)
|
2020-10-26 18:21:59 +03:00
|
|
|
|
|
|
|
$ python setup.py clean [--all]
|
|
|
|
|
2021-08-03 17:22:16 +03:00
|
|
|
Compile TypeScript modules without re-install:
|
2020-10-26 18:21:59 +03:00
|
|
|
|
|
|
|
$ python setup.py build_ts
|
|
|
|
|
|
|
|
|
|
|
|
## Release ##
|
|
|
|
|
|
|
|
Build wheel package:
|
|
|
|
|
|
|
|
$ NNI_RELEASE=2.0 python setup.py build_ts
|
|
|
|
$ NNI_RELEASE=2.0 python setup.py bdist_wheel -p manylinux1_x86_64
|
|
|
|
|
2021-09-16 12:05:01 +03:00
|
|
|
for jupyterlab 2.x package:
|
|
|
|
$ JUPYTER_LAB_VERSION=2.3.1 NNI_RELEASE=2.0 python setup.py build_ts
|
|
|
|
$ JUPYTER_LAB_VERSION=2.3.1 NNI_RELEASE=2.0 python setup.py bdist_wheel -p manylinux1_x86_64
|
|
|
|
|
2020-10-26 18:21:59 +03:00
|
|
|
Where "2.0" is version string and "manylinux1_x86_64" is platform.
|
|
|
|
The platform may also be "macosx_10_9_x86_64" or "win_amd64".
|
|
|
|
|
|
|
|
`build_ts` must be manually invoked before `bdist_wheel`,
|
|
|
|
or setuptools cannot locate JS files which should be packed into wheel.
|
|
|
|
"""
|
|
|
|
|
|
|
|
from distutils.cmd import Command
|
|
|
|
from distutils.command.build import build
|
|
|
|
from distutils.command.clean import clean
|
|
|
|
import glob
|
2018-09-07 13:21:46 +03:00
|
|
|
import os
|
2020-10-26 18:21:59 +03:00
|
|
|
import shutil
|
2020-11-05 09:56:45 +03:00
|
|
|
import sys
|
2020-10-26 18:21:59 +03:00
|
|
|
|
|
|
|
import setuptools
|
|
|
|
from setuptools.command.develop import develop
|
|
|
|
|
|
|
|
import setup_ts
|
2020-10-20 01:57:09 +03:00
|
|
|
|
2020-10-26 18:21:59 +03:00
|
|
|
release = os.environ.get('NNI_RELEASE')
|
|
|
|
|
2021-09-16 12:05:01 +03:00
|
|
|
def _get_jupyter_lab_version():
|
|
|
|
try:
|
|
|
|
import jupyterlab
|
|
|
|
return jupyterlab.__version__
|
|
|
|
except ImportError:
|
|
|
|
return '3.x'
|
|
|
|
|
|
|
|
jupyter_lab_major_version = _get_jupyter_lab_version().split('.')[0]
|
|
|
|
|
|
|
|
def check_jupyter_lab_version():
|
|
|
|
environ_version = os.environ.get('JUPYTER_LAB_VERSION')
|
|
|
|
|
|
|
|
jupyter_lab_version = _get_jupyter_lab_version()
|
|
|
|
|
|
|
|
if environ_version:
|
|
|
|
if jupyter_lab_version.split('.')[0] != environ_version.split('.')[0]:
|
|
|
|
sys.exit(f'ERROR: To build a jupyter lab extension, run "JUPYTER_LAB_VERSION={jupyter_lab_version}", current: {environ_version} ')
|
|
|
|
elif jupyter_lab_version.split('.')[0] != '3':
|
|
|
|
sys.exit(f'ERROR: To build a jupyter lab extension, run "JUPYTER_LAB_VERSION={jupyter_lab_version}" first for nondefault version(3.x)')
|
|
|
|
|
2020-10-26 18:21:59 +03:00
|
|
|
def _setup():
|
|
|
|
setuptools.setup(
|
|
|
|
name = 'nni',
|
|
|
|
version = release or '999.dev0',
|
|
|
|
description = 'Neural Network Intelligence project',
|
|
|
|
long_description = open('README.md', encoding='utf-8').read(),
|
|
|
|
long_description_content_type = 'text/markdown',
|
|
|
|
url = 'https://github.com/Microsoft/nni',
|
|
|
|
author = 'Microsoft NNI Team',
|
|
|
|
author_email = 'nni@microsoft.com',
|
|
|
|
license = 'MIT',
|
|
|
|
classifiers = [
|
|
|
|
'License :: OSI Approved :: MIT License',
|
|
|
|
'Operating System :: MacOS :: MacOS X',
|
|
|
|
'Operating System :: Microsoft :: Windows :: Windows 10',
|
|
|
|
'Operating System :: POSIX :: Linux',
|
|
|
|
'Programming Language :: Python :: 3 :: Only',
|
|
|
|
'Topic :: Scientific/Engineering :: Artificial Intelligence',
|
|
|
|
],
|
|
|
|
|
|
|
|
packages = _find_python_packages(),
|
|
|
|
package_data = {
|
2020-12-21 06:32:41 +03:00
|
|
|
'nni': _find_requirements_txt() + _find_default_config(), # setuptools issue #1806
|
2022-03-18 12:43:50 +03:00
|
|
|
'nni_assets': _find_asset_files(),
|
2020-10-26 18:21:59 +03:00
|
|
|
'nni_node': _find_node_files() # note: this does not work before building
|
|
|
|
},
|
|
|
|
|
2021-09-16 12:05:01 +03:00
|
|
|
data_files = _get_data_files(),
|
|
|
|
|
2022-01-21 13:39:38 +03:00
|
|
|
python_requires = '>=3.7',
|
2021-01-25 06:17:02 +03:00
|
|
|
install_requires = _read_requirements_txt('dependencies/required.txt'),
|
2020-12-11 20:53:48 +03:00
|
|
|
extras_require = {
|
2021-02-09 11:59:25 +03:00
|
|
|
'SMAC': _read_requirements_txt('dependencies/required_extra.txt', 'SMAC'),
|
|
|
|
'BOHB': _read_requirements_txt('dependencies/required_extra.txt', 'BOHB'),
|
2021-05-28 04:19:21 +03:00
|
|
|
'PPOTuner': _read_requirements_txt('dependencies/required_extra.txt', 'PPOTuner'),
|
|
|
|
'DNGO': _read_requirements_txt('dependencies/required_extra.txt', 'DNGO'),
|
2022-03-19 11:47:40 +03:00
|
|
|
'all': _read_requirements_txt('dependencies/required_extra.txt'),
|
2020-12-11 20:53:48 +03:00
|
|
|
},
|
2020-10-26 18:21:59 +03:00
|
|
|
setup_requires = ['requests'],
|
|
|
|
|
|
|
|
entry_points = {
|
|
|
|
'console_scripts' : [
|
|
|
|
'nnictl = nni.tools.nnictl.nnictl:parse_args'
|
|
|
|
]
|
|
|
|
},
|
|
|
|
|
|
|
|
cmdclass = {
|
|
|
|
'build': Build,
|
|
|
|
'build_ts': BuildTs,
|
|
|
|
'clean': Clean,
|
|
|
|
'develop': Develop,
|
|
|
|
}
|
|
|
|
)
|
2020-10-20 01:57:09 +03:00
|
|
|
|
2021-09-16 12:05:01 +03:00
|
|
|
def _get_data_files():
|
|
|
|
data_files = []
|
|
|
|
if jupyter_lab_major_version == '2':
|
|
|
|
extension_file = glob.glob("nni_node/jupyter-extension/extensions/nni-jupyter-extension*.tgz")
|
|
|
|
data_files = [('share/jupyter/lab/extensions', extension_file)]
|
|
|
|
return data_files
|
2020-10-20 01:57:09 +03:00
|
|
|
|
|
|
|
def _find_python_packages():
|
|
|
|
packages = []
|
|
|
|
for dirpath, dirnames, filenames in os.walk('nni'):
|
2020-12-21 06:32:41 +03:00
|
|
|
if '/__pycache__' not in dirpath and '/.mypy_cache' not in dirpath and '/default_config' not in dirpath:
|
2020-10-20 01:57:09 +03:00
|
|
|
packages.append(dirpath.replace('/', '.'))
|
2022-03-24 07:00:53 +03:00
|
|
|
return sorted(packages) + ['nni_assets', 'nni_node']
|
2020-10-20 01:57:09 +03:00
|
|
|
|
2020-12-05 10:54:12 +03:00
|
|
|
def _find_requirements_txt():
|
|
|
|
requirement_files = []
|
|
|
|
for dirpath, dirnames, filenames in os.walk('nni'):
|
|
|
|
if 'requirements.txt' in filenames:
|
|
|
|
requirement_files.append(os.path.join(dirpath[len('nni/'):], 'requirements.txt'))
|
|
|
|
return requirement_files
|
|
|
|
|
2020-12-21 06:32:41 +03:00
|
|
|
def _find_default_config():
|
|
|
|
return ['runtime/default_config/' + name for name in os.listdir('nni/runtime/default_config')]
|
|
|
|
|
2022-03-18 12:43:50 +03:00
|
|
|
def _find_asset_files():
|
|
|
|
files = []
|
|
|
|
for dirpath, dirnames, filenames in os.walk('nni_assets'):
|
|
|
|
for filename in filenames:
|
|
|
|
if os.path.splitext(filename)[1] == '.py':
|
|
|
|
files.append(os.path.join(dirpath[len('nni_assets/'):], filename))
|
|
|
|
return sorted(files)
|
|
|
|
|
2020-10-20 01:57:09 +03:00
|
|
|
def _find_node_files():
|
2020-10-30 07:39:34 +03:00
|
|
|
if not os.path.exists('nni_node'):
|
2020-12-21 06:32:41 +03:00
|
|
|
if release and 'build_ts' not in sys.argv and 'clean' not in sys.argv:
|
2020-12-05 10:54:12 +03:00
|
|
|
sys.exit('ERROR: To build a release version, run "python setup.py build_ts" first')
|
2020-10-30 07:39:34 +03:00
|
|
|
return []
|
2020-10-20 01:57:09 +03:00
|
|
|
files = []
|
|
|
|
for dirpath, dirnames, filenames in os.walk('nni_node'):
|
|
|
|
for filename in filenames:
|
2020-12-05 10:54:12 +03:00
|
|
|
files.append(os.path.join(dirpath[len('nni_node/'):], filename))
|
2020-10-30 07:39:34 +03:00
|
|
|
if '__init__.py' in files:
|
|
|
|
files.remove('__init__.py')
|
2020-10-20 01:57:09 +03:00
|
|
|
return sorted(files)
|
2018-09-07 13:21:46 +03:00
|
|
|
|
2021-01-25 06:17:02 +03:00
|
|
|
def _read_requirements_txt(file_path, section=None):
|
|
|
|
with open(file_path) as f:
|
|
|
|
lines = [line.strip() for line in f.readlines() if line.strip()] # remove whitespaces and empty lines
|
|
|
|
if section is None:
|
|
|
|
return [line for line in lines if not line.startswith('#')]
|
|
|
|
selected_lines = []
|
|
|
|
started = False
|
|
|
|
for line in lines:
|
|
|
|
if started:
|
|
|
|
if line.startswith('#'):
|
|
|
|
return selected_lines
|
|
|
|
else:
|
|
|
|
selected_lines.append(line)
|
|
|
|
elif line.startswith('# ' + section):
|
|
|
|
started = True
|
|
|
|
return selected_lines
|
|
|
|
|
2020-11-05 09:56:45 +03:00
|
|
|
def _using_conda_or_virtual_environment():
|
|
|
|
return sys.prefix != sys.base_prefix or os.path.isdir(os.path.join(sys.prefix, 'conda-meta'))
|
|
|
|
|
2020-10-26 18:21:59 +03:00
|
|
|
class BuildTs(Command):
|
|
|
|
description = 'build TypeScript modules'
|
|
|
|
|
|
|
|
user_options = []
|
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def finalize_options(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def run(self):
|
2021-09-16 12:05:01 +03:00
|
|
|
check_jupyter_lab_version()
|
2020-10-26 18:21:59 +03:00
|
|
|
setup_ts.build(release)
|
|
|
|
|
|
|
|
class Build(build):
|
|
|
|
def run(self):
|
2020-12-05 10:54:12 +03:00
|
|
|
if not release:
|
|
|
|
sys.exit('Please set environment variable "NNI_RELEASE=<release_version>"')
|
2021-09-16 12:05:01 +03:00
|
|
|
|
|
|
|
check_jupyter_lab_version()
|
|
|
|
|
2020-12-05 10:54:12 +03:00
|
|
|
if os.path.islink('nni_node/main.js'):
|
2022-03-19 11:47:40 +03:00
|
|
|
sys.exit('A development build already exists. Please uninstall NNI and run "python3 setup.py clean".')
|
2020-12-25 12:51:35 +03:00
|
|
|
open('nni/version.py', 'w').write(f"__version__ = '{release}'")
|
2020-10-26 18:21:59 +03:00
|
|
|
super().run()
|
|
|
|
|
|
|
|
class Develop(develop):
|
2020-11-05 09:56:45 +03:00
|
|
|
user_options = develop.user_options + [
|
2020-12-09 02:18:52 +03:00
|
|
|
('no-user', None, 'Prevent automatically adding "--user"'),
|
|
|
|
('skip-ts', None, 'Prevent building TypeScript modules')
|
2020-11-05 09:56:45 +03:00
|
|
|
]
|
|
|
|
|
2020-12-09 02:18:52 +03:00
|
|
|
boolean_options = develop.boolean_options + ['no-user', 'skip-ts']
|
2020-11-05 09:56:45 +03:00
|
|
|
|
|
|
|
def initialize_options(self):
|
|
|
|
super().initialize_options()
|
|
|
|
self.no_user = None
|
2020-12-09 02:18:52 +03:00
|
|
|
self.skip_ts = None
|
2020-11-05 09:56:45 +03:00
|
|
|
|
2020-10-26 18:21:59 +03:00
|
|
|
def finalize_options(self):
|
2020-11-05 09:56:45 +03:00
|
|
|
# if `--user` or `--no-user` is explicitly set, do nothing
|
|
|
|
# otherwise activate `--user` if using system python
|
|
|
|
if not self.user and not self.no_user:
|
|
|
|
self.user = not _using_conda_or_virtual_environment()
|
2020-10-26 18:21:59 +03:00
|
|
|
super().finalize_options()
|
|
|
|
|
|
|
|
def run(self):
|
2020-12-25 12:51:35 +03:00
|
|
|
open('nni/version.py', 'w').write("__version__ = '999.dev0'")
|
2020-12-09 02:18:52 +03:00
|
|
|
if not self.skip_ts:
|
|
|
|
setup_ts.build(release=None)
|
2020-10-26 18:21:59 +03:00
|
|
|
super().run()
|
|
|
|
|
|
|
|
class Clean(clean):
|
|
|
|
def finalize_options(self):
|
|
|
|
self._all = self.all
|
|
|
|
self.all = True # always use `clean --all`
|
|
|
|
super().finalize_options()
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
super().run()
|
2022-03-19 11:47:40 +03:00
|
|
|
setup_ts.clean()
|
2020-10-26 18:21:59 +03:00
|
|
|
_clean_temp_files()
|
|
|
|
shutil.rmtree('nni.egg-info', ignore_errors=True)
|
|
|
|
if self._all:
|
|
|
|
shutil.rmtree('dist', ignore_errors=True)
|
|
|
|
|
|
|
|
|
|
|
|
def _clean_temp_files():
|
|
|
|
for pattern in _temp_files:
|
|
|
|
for path in glob.glob(pattern):
|
|
|
|
if os.path.islink(path) or os.path.isfile(path):
|
|
|
|
os.remove(path)
|
|
|
|
else:
|
|
|
|
shutil.rmtree(path)
|
|
|
|
|
|
|
|
_temp_files = [
|
|
|
|
# unit test
|
|
|
|
'test/model_path/',
|
|
|
|
'test/temp.json',
|
2020-10-30 07:39:34 +03:00
|
|
|
'test/ut/sdk/*.pth',
|
2022-03-18 12:43:50 +03:00
|
|
|
'test/ut/tools/annotation/_generated/',
|
|
|
|
|
|
|
|
# example
|
|
|
|
'nni_assets/**/data/',
|
2020-10-26 18:21:59 +03:00
|
|
|
]
|
|
|
|
|
|
|
|
|
2020-12-05 10:54:12 +03:00
|
|
|
if __name__ == '__main__':
|
|
|
|
_setup()
|