diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index fa8e6b04..0eadd339 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -22,7 +22,10 @@ jobs: - name: Install wheel run: pip install wheel && pip install -r requirements/framework.txt - name: Build ModelScope - run: python setup.py sdist bdist_wheel + # Build AST template before packaging + run: | + python -c "from modelscope.utils.ast_utils import generate_ast_template; generate_ast_template()" + python setup.py sdist bdist_wheel - name: Publish package to PyPI run: | pip install twine diff --git a/MANIFEST.in b/MANIFEST.in index 5e076f95..c9691801 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,3 @@ -recursive-include modelscope/configs *.py *.cu *.h *.cpp +recursive-include modelscope/ops *.py *.cu *.h *.cpp recursive-include modelscope/cli/template *.tpl recursive-include modelscope/utils *.json diff --git a/modelscope/cli/cli.py b/modelscope/cli/cli.py index 139f14a5..acf9ad39 100644 --- a/modelscope/cli/cli.py +++ b/modelscope/cli/cli.py @@ -16,6 +16,7 @@ from modelscope.cli.server import ServerCMD from modelscope.cli.upload import UploadCMD from modelscope.hub.constants import MODELSCOPE_ASCII from modelscope.utils.logger import get_logger +from modelscope.version import __version__ logger = get_logger(log_level=logging.WARNING) @@ -24,6 +25,11 @@ def run_cmd(): print(MODELSCOPE_ASCII) parser = argparse.ArgumentParser( 'ModelScope Command Line tool', usage='modelscope []') + parser.add_argument( + '-V', + '--version', + action='version', + version=f'ModelScope CLI {__version__}') parser.add_argument( '--token', default=None, help='Specify ModelScope SDK token.') subparsers = parser.add_subparsers(help='modelscope commands helpers') diff --git a/modelscope/utils/ast_utils.py b/modelscope/utils/ast_utils.py index 657ebb33..ec7a8457 100644 --- a/modelscope/utils/ast_utils.py +++ b/modelscope/utils/ast_utils.py @@ -768,7 +768,7 @@ def load_from_prebuilt(file_path=None): if os.path.exists(file_path): index = _load_index(file_path, with_template=True) else: - index = None + index = generate_ast_template() return index diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..d3036994 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,76 @@ +[project] +name = "modelscope" +dynamic = ["version", "dependencies", "optional-dependencies"] +description = "ModelScope: bring the notion of Model-as-a-Service to life." +readme = {file = "README.md", content-type = "text/markdown"} +license = "Apache-2.0" +license-files = ["LICENSE"] +authors = [ + {name = "ModelScope team"}, + {email = "contact@modelscope.cn"} +] +keywords = ["python", "nlp", "science", "cv", "speech", "multi-modal"] +requires-python = ">=3.9" +classifiers = [ + 'Development Status :: 4 - Beta', + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', +] + +[project.urls] +Homepage = "https://github.com/modelscope/modelscope" + +[project.scripts] +modelscope = "modelscope.cli.cli:run_cmd" + +[build-system] +requires = ["setuptools>=69", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.packages.find] +where = ["."] +include = ["modelscope*"] + +[tool.setuptools.dynamic] +version = {attr = "modelscope.version.__version__"} +dependencies = {file = ["requirements/hub.txt"]} + +[tool.setuptools.dynamic.optional-dependencies] +hub = {file = ["requirements/hub.txt"]} +datasets = {file = ["requirements/datasets.txt"]} +framework = {file = ["requirements/framework.txt"]} +server = {file = ["requirements/server.txt"]} + +# domain specific with framework base +cv = {file = ["requirements/framework.txt", "requirements/cv.txt"]} +nlp = {file = ["requirements/framework.txt", "requirements/nlp.txt"]} +multi-modal = {file = ["requirements/framework.txt", "requirements/multi-modal.txt"]} +science = {file = ["requirements/framework.txt", "requirements/science.txt"]} + +# audio specific with framework base +audio_asr = {file = ["requirements/framework.txt", "requirements/audio/audio_asr.txt"]} +audio_codec = {file = ["requirements/framework.txt", "requirements/audio/audio_codec.txt"]} +audio_tts = {file = ["requirements/framework.txt", "requirements/audio/audio_tts.txt"]} +audio_kws = {file = ["requirements/framework.txt", "requirements/audio/audio_kws.txt"]} +audio_signal = {file = ["requirements/framework.txt", "requirements/audio/audio_signal.txt"]} + +docs = {file = ["requirements/docs.txt"]} +tests = {file = ["requirements/tests.txt"]} + +# skip audio requirements due to its hard dependency which may cause installation failure +all = {file = [ + "requirements/hub.txt", + "requirements/datasets.txt", + "requirements/framework.txt", + "requirements/cv.txt", + "requirements/nlp.txt", + "requirements/multi-modal.txt", + "requirements/science.txt", + "requirements/server.txt", +]} diff --git a/requirements/multi-modal.txt b/requirements/multi-modal.txt index b2f767c5..af12af06 100644 --- a/requirements/multi-modal.txt +++ b/requirements/multi-modal.txt @@ -2,11 +2,11 @@ accelerate cloudpickle decord>=0.6.0 diffusers>=0.25.0 -ftfy>=6.0.3 # 0.12.1 has issue of No such file or directory: 'fairseq/version.txt' # 0.12.2 not support py311 #fairseq==0.12.2 -https://github.com/liyaodev/fairseq/releases/download/v0.12.3.1/fairseq-0.12.3.1-cp311-cp311-linux_x86_64.whl +fairseq @ https://github.com/liyaodev/fairseq/releases/download/v0.12.3.1/fairseq-0.12.3.1-cp311-cp311-linux_x86_64.whl ; python_version == "3.11" and platform_system == "Linux" and platform_machine == "x86_64" +ftfy>=6.0.3 librosa==0.10.1 opencv-python pycocoevalcap>=1.2 diff --git a/setup.py b/setup.py index 76a6a7bf..70fb2673 100644 --- a/setup.py +++ b/setup.py @@ -1,239 +1,6 @@ # Copyright (c) Alibaba, Inc. and its affiliates. -# !/usr/bin/env python -import os -import shutil -import subprocess -from setuptools import find_packages, setup +# -*- coding: utf-8 -*- -from modelscope.utils.constant import Fields +from setuptools import setup - -def readme(): - with open('README.md', encoding='utf-8') as f: - content = f.read() - return content - - -version_file = 'modelscope/version.py' - - -def get_git_hash(): - - def _minimal_ext_cmd(cmd): - # construct minimal environment - env = {} - for k in ['SYSTEMROOT', 'PATH', 'HOME']: - v = os.environ.get(k) - if v is not None: - env[k] = v - # LANGUAGE is used on win32 - env['LANGUAGE'] = 'C' - env['LANG'] = 'C' - env['LC_ALL'] = 'C' - out = subprocess.Popen( - cmd, stdout=subprocess.PIPE, env=env).communicate()[0] - return out - - try: - out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) - sha = out.strip().decode('ascii') - except OSError: - sha = 'unknown' - - return sha - - -def get_hash(): - assert os.path.exists('.git'), '.git directory does not exist' - sha = get_git_hash()[:7] - return sha - - -def get_version(): - with open(version_file, 'r', encoding='utf-8') as f: - exec(compile(f.read(), version_file, 'exec')) - return locals()['__version__'] - - -def parse_requirements(fname='requirements.txt', with_version=True): - """ - Parse the package dependencies listed in a requirements file but strips - specific versioning information. - - Args: - fname (str): path to requirements file - with_version (bool, default=False): if True include version specs - - Returns: - List[str]: list of requirements items - - CommandLine: - python -c "import setup; print(setup.parse_requirements())" - """ - import re - import sys - from os.path import exists - require_fpath = fname - - def parse_line(line): - """ - Parse information from a line in a requirements text file - """ - if line.startswith('-r '): - # Allow specifying requirements in other files - target = line.split(' ')[1] - relative_base = os.path.dirname(fname) - absolute_target = os.path.join(relative_base, target) - for info in parse_require_file(absolute_target): - yield info - else: - info = {'line': line} - if line.startswith('-e '): - info['package'] = line.split('#egg=')[1] - else: - # Remove versioning from the package - pat = '(' + '|'.join(['>=', '==', '>']) + ')' - parts = re.split(pat, line, maxsplit=1) - parts = [p.strip() for p in parts] - - info['package'] = parts[0] - if len(parts) > 1: - op, rest = parts[1:] - if ';' in rest: - # Handle platform specific dependencies - # http://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-platform-specific-dependencies - version, platform_deps = map(str.strip, - rest.split(';')) - info['platform_deps'] = platform_deps - else: - version = rest # NOQA - info['version'] = (op, version) - yield info - - def parse_require_file(fpath): - with open(fpath, 'r', encoding='utf-8') as f: - for line in f.readlines(): - line = line.strip() - if line.startswith('http'): - print('skip http requirements %s' % line) - continue - if line and not line.startswith('#') and not line.startswith( - '--'): - for info in parse_line(line): - yield info - elif line and line.startswith('--find-links'): - eles = line.split() - for e in eles: - e = e.strip() - if 'http' in e: - info = dict(dependency_links=e) - yield info - - def gen_packages_items(): - items = [] - deps_link = [] - if exists(require_fpath): - for info in parse_require_file(require_fpath): - if 'dependency_links' not in info: - parts = [info['package']] - if with_version and 'version' in info: - parts.extend(info['version']) - if not sys.version.startswith('3.4'): - # apparently package_deps are broken in 3.4 - platform_deps = info.get('platform_deps') - if platform_deps is not None: - parts.append(';' + platform_deps) - item = ''.join(parts) - items.append(item) - else: - deps_link.append(info['dependency_links']) - return items, deps_link - - return gen_packages_items() - - -def pack_resource(): - # pack resource such as configs and tools - root_dir = 'package/' - if os.path.isdir(root_dir): - shutil.rmtree(root_dir) - os.makedirs(root_dir) - - proj_dir = root_dir + 'modelscope/' - shutil.copytree('./modelscope', proj_dir) - shutil.copytree('./configs', proj_dir + 'configs') - shutil.copytree('./requirements', 'package/requirements') - shutil.copy('./requirements.txt', 'package/requirements.txt') - shutil.copy('./MANIFEST.in', 'package/MANIFEST.in') - shutil.copy('./README.md', 'package/README.md') - - -if __name__ == '__main__': - # write_version_py() - from modelscope.utils.ast_utils import generate_ast_template - generate_ast_template() - pack_resource() - os.chdir('package') - install_requires, deps_link = parse_requirements('requirements.txt') - extra_requires = {} - all_requires = [] - for field in dir(Fields): - if field.startswith('_'): - continue - field = getattr(Fields, field) - extra_requires[field], _ = parse_requirements( - f'requirements/{field}.txt') - - # skip audio requirements due to its hard dependency which - # result in mac/windows compatibility problems - if field != Fields.audio: - all_requires.append(extra_requires[field]) - for subfiled in ['asr', 'kws', 'signal', 'tts']: - filed_name = f'audio_{subfiled}' - extra_requires[filed_name], _ = parse_requirements( - f'requirements/audio/{filed_name}.txt') - framework_requires = extra_requires['framework'] - # add framework dependencies to every field - for field, requires in extra_requires.items(): - if field not in [ - 'server', 'framework', 'hub', 'datasets' - ]: # server need install model's field dependencies before. - extra_requires[field] = framework_requires + extra_requires[field] - extra_requires['all'] = all_requires - - setup( - name='modelscope', - version=get_version(), - description= - 'ModelScope: bring the notion of Model-as-a-Service to life.', - long_description=readme(), - long_description_content_type='text/markdown', - author='ModelScope team', - author_email='contact@modelscope.cn', - keywords='python,nlp,science,cv,speech,multi-modal', - url='https://github.com/modelscope/modelscope', - packages=find_packages(exclude=('configs', 'demo')), - include_package_data=True, - package_data={ - '': ['*.h', '*.cpp', '*.cu'], - }, - classifiers=[ - 'Development Status :: 4 - Beta', - 'License :: OSI Approved :: Apache Software License', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - ], - license='Apache License 2.0', - tests_require=parse_requirements('requirements/tests.txt'), - install_requires=install_requires, - extras_require=extra_requires, - entry_points={ - 'console_scripts': ['modelscope=modelscope.cli.cli:run_cmd'] - }, - dependency_links=deps_link, - zip_safe=False) +setup()