mirror of
https://github.com/modelscope/FunASR.git
synced 2026-10-12 02:19:18 +00:00
release(onnx): prepare 0.4.3 with installed artifact regressions
Signed-off-by: zhifu gao <[email protected]>
This commit is contained in:
@@ -6,6 +6,7 @@ on:
|
||||
- ".github/workflows/test-funasr-onnx-package.yml"
|
||||
- "runtime/python/onnxruntime/**"
|
||||
- "tests/test_funasr_onnx_release.py"
|
||||
- "tests/test_funasr_onnx_installed.py"
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
@@ -13,6 +14,7 @@ on:
|
||||
- ".github/workflows/test-funasr-onnx-package.yml"
|
||||
- "runtime/python/onnxruntime/**"
|
||||
- "tests/test_funasr_onnx_release.py"
|
||||
- "tests/test_funasr_onnx_installed.py"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
@@ -60,7 +62,7 @@ jobs:
|
||||
import importlib.util
|
||||
from importlib.metadata import requires, version
|
||||
|
||||
assert version("funasr-onnx") == "0.4.2"
|
||||
assert version("funasr-onnx") == "0.4.3"
|
||||
assert importlib.util.find_spec("torch") is None
|
||||
|
||||
requirements = requires("funasr-onnx") or []
|
||||
@@ -76,10 +78,19 @@ jobs:
|
||||
)
|
||||
PY
|
||||
|
||||
- name: Verify installed wrapper error paths
|
||||
run: python tests/test_funasr_onnx_installed.py
|
||||
|
||||
- name: Verify source distribution error paths
|
||||
run: |
|
||||
python -m pip install --force-reinstall --no-deps dist/funasr-onnx/*.tar.gz
|
||||
python -m pip check
|
||||
python tests/test_funasr_onnx_installed.py
|
||||
|
||||
- name: Upload release candidate
|
||||
if: matrix.python-version == '3.12'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: funasr-onnx-0.4.2
|
||||
name: funasr-onnx-0.4.3
|
||||
path: dist/funasr-onnx/*
|
||||
if-no-files-found: error
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
## Install `funasr-onnx`
|
||||
|
||||
`funasr-onnx` is a separate distribution from `funasr`. Upgrading `funasr`
|
||||
does not update the installed ONNX wrappers. Check their versions separately
|
||||
with `python -m pip show funasr-onnx funasr`; use the source installation below
|
||||
when a required wrapper fix is newer than the published PyPI package.
|
||||
|
||||
install from pip
|
||||
|
||||
```shell
|
||||
|
||||
@@ -13,7 +13,7 @@ def get_readme():
|
||||
|
||||
|
||||
MODULE_NAME = "funasr_onnx"
|
||||
VERSION_NUM = "0.4.2"
|
||||
VERSION_NUM = "0.4.3"
|
||||
|
||||
setuptools.setup(
|
||||
name=MODULE_NAME,
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
"""Run against an installed wheel/sdist, outside the source package directory."""
|
||||
|
||||
import ast
|
||||
import builtins
|
||||
import contextlib
|
||||
import importlib.metadata
|
||||
import importlib.util
|
||||
import io
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
if importlib.util.find_spec('funasr_onnx') is None:
|
||||
raise unittest.SkipTest('Install the standalone funasr-onnx distribution first.')
|
||||
|
||||
import funasr_onnx
|
||||
from funasr_onnx.paraformer_online_bin import Paraformer as ParaformerOnline
|
||||
|
||||
|
||||
ENTRYPOINTS = (
|
||||
funasr_onnx.Paraformer,
|
||||
funasr_onnx.ContextualParaformer,
|
||||
funasr_onnx.SeacoParaformer,
|
||||
ParaformerOnline,
|
||||
funasr_onnx.Fsmn_vad,
|
||||
funasr_onnx.Fsmn_vad_online,
|
||||
funasr_onnx.CT_Transformer,
|
||||
funasr_onnx.CT_Transformer_VadRealtime,
|
||||
funasr_onnx.SenseVoiceSmall,
|
||||
)
|
||||
|
||||
|
||||
class InstalledOnnxPackageTest(unittest.TestCase):
|
||||
def test_installed_distribution_version_and_origin(self):
|
||||
distribution = importlib.metadata.distribution('funasr-onnx')
|
||||
self.assertEqual(distribution.version, '0.4.3')
|
||||
self.assertEqual(
|
||||
Path(funasr_onnx.__file__).resolve().parent,
|
||||
Path(distribution.locate_file('funasr_onnx')).resolve(),
|
||||
)
|
||||
|
||||
def test_installed_modules_have_no_string_exceptions(self):
|
||||
offenders = []
|
||||
for source in Path(funasr_onnx.__file__).parent.rglob('*.py'):
|
||||
for node in ast.walk(ast.parse(source.read_text(encoding='utf-8'))):
|
||||
if not isinstance(node, ast.Raise):
|
||||
continue
|
||||
literal = node.exc
|
||||
if (
|
||||
isinstance(literal, ast.Call)
|
||||
and isinstance(literal.func, ast.Attribute)
|
||||
and literal.func.attr == 'format'
|
||||
):
|
||||
literal = literal.func.value
|
||||
if isinstance(literal, ast.Constant) and isinstance(literal.value, str):
|
||||
offenders.append(f'{source.name}:{node.lineno}')
|
||||
self.assertEqual(offenders, [])
|
||||
|
||||
def check_export_import_error(self, error, expected_type, preserves_cause):
|
||||
original_import = builtins.__import__
|
||||
|
||||
def broken_export_import(name, *args, **kwargs):
|
||||
if name == 'funasr':
|
||||
raise error
|
||||
return original_import(name, *args, **kwargs)
|
||||
|
||||
# Only the optional exporter import is replaced; constructors are installed code.
|
||||
with tempfile.TemporaryDirectory() as model_dir:
|
||||
for entrypoint in ENTRYPOINTS:
|
||||
with self.subTest(entrypoint=entrypoint.__name__):
|
||||
error.__traceback__ = None
|
||||
with patch('builtins.__import__', side_effect=broken_export_import):
|
||||
with contextlib.redirect_stdout(io.StringIO()):
|
||||
with self.assertRaises(expected_type) as raised:
|
||||
entrypoint(model_dir)
|
||||
if preserves_cause:
|
||||
self.assertIs(raised.exception.__cause__, error)
|
||||
else:
|
||||
self.assertIs(raised.exception, error)
|
||||
|
||||
def test_missing_transitive_export_dependency_remains_visible(self):
|
||||
error = ModuleNotFoundError("No module named 'torchaudio'", name='torchaudio')
|
||||
self.check_export_import_error(error, ImportError, preserves_cause=True)
|
||||
|
||||
def test_unrelated_export_import_failure_is_not_misreported(self):
|
||||
error = RuntimeError('exporter initialization failed')
|
||||
self.check_export_import_error(error, RuntimeError, preserves_cause=False)
|
||||
|
||||
def test_failed_model_download_preserves_cause(self):
|
||||
original_import = builtins.__import__
|
||||
error = OSError('model download failed')
|
||||
|
||||
def failed_download(*args, **kwargs):
|
||||
raise error
|
||||
|
||||
def controlled_download_import(name, *args, **kwargs):
|
||||
if name == 'modelscope.hub.snapshot_download':
|
||||
return SimpleNamespace(snapshot_download=failed_download)
|
||||
return original_import(name, *args, **kwargs)
|
||||
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
missing_model = str(Path(directory) / 'not-downloaded')
|
||||
for entrypoint in ENTRYPOINTS:
|
||||
with self.subTest(entrypoint=entrypoint.__name__):
|
||||
error.__traceback__ = None
|
||||
with patch('builtins.__import__', side_effect=controlled_download_import):
|
||||
with self.assertRaises(RuntimeError) as raised:
|
||||
entrypoint(missing_model)
|
||||
self.assertIs(raised.exception.__cause__, error)
|
||||
|
||||
def test_missing_onnxruntime_import_preserves_cause(self):
|
||||
script = '''
|
||||
import builtins
|
||||
import json
|
||||
original_import = builtins.__import__
|
||||
def broken_import(name, *args, **kwargs):
|
||||
if name == 'onnxruntime':
|
||||
raise ModuleNotFoundError("No module named 'onnxruntime'", name='onnxruntime')
|
||||
return original_import(name, *args, **kwargs)
|
||||
builtins.__import__ = broken_import
|
||||
try:
|
||||
import funasr_onnx
|
||||
except Exception as error:
|
||||
print(json.dumps({
|
||||
'type': type(error).__name__,
|
||||
'cause': type(error.__cause__).__name__,
|
||||
'missing': getattr(error.__cause__, 'name', None),
|
||||
}))
|
||||
else:
|
||||
print(json.dumps({'type': None}))
|
||||
'''
|
||||
result = subprocess.run(
|
||||
[sys.executable, '-c', script], capture_output=True, text=True, timeout=60,
|
||||
check=True,
|
||||
)
|
||||
self.assertEqual(json.loads(result.stdout.splitlines()[-1]), {
|
||||
'type': 'ImportError', 'cause': 'ModuleNotFoundError', 'missing': 'onnxruntime',
|
||||
})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -7,7 +7,7 @@ import unittest
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PACKAGE_ROOT = ROOT / "runtime" / "python" / "onnxruntime"
|
||||
SETUP_PATH = PACKAGE_ROOT / "setup.py"
|
||||
EXPECTED_VERSION = "0.4.2"
|
||||
EXPECTED_VERSION = "0.4.3"
|
||||
REQUIREMENT_NAME_PATTERN = re.compile(r"^\s*([A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?)")
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ def normalized_requirement_name(requirement):
|
||||
|
||||
|
||||
class FunASROnnxReleaseContractTest(unittest.TestCase):
|
||||
def test_release_version_is_0_4_2(self):
|
||||
def test_release_version_is_0_4_3(self):
|
||||
self.assertEqual(assigned_literal(read_setup_tree(), "VERSION_NUM"), EXPECTED_VERSION)
|
||||
|
||||
def test_runtime_dependencies_keep_onnx_install_torch_free(self):
|
||||
|
||||
Reference in New Issue
Block a user