transcribe-cpp 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/PKG-INFO +3 -3
  2. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/pyproject.toml +3 -3
  3. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/src/transcribe_cpp/__init__.py +1 -1
  4. transcribe_cpp-0.1.2/tests/test_utf8_paths.py +87 -0
  5. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/.gitignore +0 -0
  6. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/LICENSE +0 -0
  7. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/README.md +0 -0
  8. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/_generate/README.md +0 -0
  9. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/_generate/check_version_sync.py +0 -0
  10. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/_generate/generate.py +0 -0
  11. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/examples/stream_wav.py +0 -0
  12. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/examples/transcribe_wav.py +0 -0
  13. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/src/transcribe_cpp/_abi.py +0 -0
  14. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/src/transcribe_cpp/_generated.py +0 -0
  15. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/src/transcribe_cpp/_library.py +0 -0
  16. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/src/transcribe_cpp/errors.py +0 -0
  17. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/src/transcribe_cpp/py.typed +0 -0
  18. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/conftest.py +0 -0
  19. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_abi.py +0 -0
  20. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_backends.py +0 -0
  21. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_device_select.py +0 -0
  22. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_errors.py +0 -0
  23. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_example.py +0 -0
  24. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_family_ext.py +0 -0
  25. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_lifetime.py +0 -0
  26. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_pcm.py +0 -0
  27. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_provider_discovery.py +0 -0
  28. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_streaming.py +0 -0
  29. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/tests/test_transcribe.py +0 -0
  30. {transcribe_cpp-0.1.0 → transcribe_cpp-0.1.2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: transcribe-cpp
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Python bindings for transcribe.cpp
5
5
  Project-URL: Homepage, https://github.com/handy-computer/transcribe.cpp
6
6
  Project-URL: Repository, https://github.com/handy-computer/transcribe.cpp
@@ -21,9 +21,9 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
22
22
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
23
  Requires-Python: >=3.9
24
- Requires-Dist: transcribe-cpp-native==0.1.0.*
24
+ Requires-Dist: transcribe-cpp-native==0.1.2.*
25
25
  Provides-Extra: cu12
26
- Requires-Dist: transcribe-cpp-native-cu12==0.1.0.*; extra == 'cu12'
26
+ Requires-Dist: transcribe-cpp-native-cu12==0.1.2.*; extra == 'cu12'
27
27
  Provides-Extra: test
28
28
  Requires-Dist: numpy; extra == 'test'
29
29
  Requires-Dist: pytest>=7; extra == 'test'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "transcribe-cpp"
7
- version = "0.1.0"
7
+ version = "0.1.2"
8
8
  description = "Python bindings for transcribe.cpp"
9
9
  readme = "README.md"
10
10
  # 3.8 is EOL (2024-10); 3.9 is the floor. The binding is ctypes-only, so there
@@ -34,13 +34,13 @@ classifiers = [
34
34
  # packaging fix still resolves); the import-time version/header-hash check in
35
35
  # _library.py is the runtime backstop. check_version_sync.py gates this pin
36
36
  # against include/transcribe.h.
37
- dependencies = ["transcribe-cpp-native==0.1.0.*"]
37
+ dependencies = ["transcribe-cpp-native==0.1.2.*"]
38
38
 
39
39
  [project.optional-dependencies]
40
40
  # Opt-in accelerator providers — ADDITIVE: they install alongside the default
41
41
  # provider and the best one wins at runtime. Same base-version pin contract
42
42
  # as the hard dependency (gated by check_version_sync.py).
43
- cu12 = ["transcribe-cpp-native-cu12==0.1.0.*"]
43
+ cu12 = ["transcribe-cpp-native-cu12==0.1.2.*"]
44
44
  # Test-only deps. Run with: uv run --extra test pytest (from bindings/python).
45
45
  # numpy is here so the numpy PCM-input tests run in every lane instead of
46
46
  # silently skipping wherever numpy happens to be absent.
@@ -46,7 +46,7 @@ from .errors import (
46
46
  raise_for_status,
47
47
  )
48
48
 
49
- __version__ = "0.1.0"
49
+ __version__ = "0.1.2"
50
50
 
51
51
  # String-enum types, exported so callers (and type checkers) can name them.
52
52
  Backend = Literal["auto", "cpu", "metal", "vulkan", "cpu_accel", "cuda"]
@@ -0,0 +1,87 @@
1
+ """Non-ASCII (UTF-8) path handling through the C ABI.
2
+
3
+ Regression coverage for Handy issue #1585: on Windows, model loading
4
+ and backend artifact-dir validation failed for non-ASCII paths because
5
+ the library's narrow ``::stat()`` / ``ifstream`` calls read the UTF-8
6
+ path bytes in the process ANSI code page. src/transcribe-path.h now
7
+ converts UTF-8 to wide paths on Windows.
8
+
9
+ The C++ counterpart (tests/utf8_path_unit.cpp) pins the same contract,
10
+ but ctest only runs on Linux/macOS in CI — this file is what executes
11
+ on a real Windows runner (the wheel lanes run the pytest suite via
12
+ scripts/ci/wheel_smoke.py).
13
+
14
+ Model-free tests always run; the full-load test skips without a model
15
+ (``TRANSCRIBE_SMOKE_MODEL``, set by the wheel lanes).
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import os
21
+ import shutil
22
+ from pathlib import Path
23
+
24
+ import pytest
25
+
26
+ import transcribe_cpp as t
27
+ from transcribe_cpp import errors
28
+
29
+ # Same characters as the C++ counterpart's directory name.
30
+ NON_ASCII_DIR = "transcribe-utf8-café-日本語"
31
+
32
+
33
+ def _nonascii_dir(tmp_path: Path) -> Path:
34
+ d = tmp_path / NON_ASCII_DIR
35
+ try:
36
+ d.mkdir()
37
+ except OSError as e: # filesystem that cannot represent the name
38
+ pytest.skip(f"cannot create non-ASCII directory: {e}")
39
+ return d
40
+
41
+
42
+ def test_missing_file_in_nonascii_dir_raises_file_not_found(tmp_path):
43
+ # The not-found classification must survive the wide-path port: a
44
+ # genuinely absent file is FILE_NOT_FOUND, not some generic error.
45
+ d = _nonascii_dir(tmp_path)
46
+ with pytest.raises(t.ModelFileNotFound) as ei:
47
+ t.Model(d / "definitely-missing.gguf")
48
+ assert ei.value.status == errors.ERR_FILE_NOT_FOUND
49
+
50
+
51
+ def test_junk_file_in_nonascii_dir_is_found_then_rejected(tmp_path):
52
+ # The #1585 failure shape: the file EXISTS at the non-ASCII path,
53
+ # but pre-fix Windows raised ModelFileNotFound (the ANSI-code-page
54
+ # stat could not see it). ModelLoadError is a sibling class, so
55
+ # this cannot pass via FILE_NOT_FOUND.
56
+ d = _nonascii_dir(tmp_path)
57
+ junk = d / "junk.gguf"
58
+ junk.write_bytes(b"this is not a gguf file" * 64)
59
+ with pytest.raises(t.ModelLoadError):
60
+ t.Model(junk)
61
+
62
+
63
+ def test_smoke_model_loads_from_nonascii_dir(model_path, tmp_path):
64
+ # Full successful load through the non-ASCII path: existence
65
+ # pre-check, magic sniff, gguf parse, and the tensor-data streaming
66
+ # reopen all consume the path. Constructing the Model is the
67
+ # assertion.
68
+ d = _nonascii_dir(tmp_path)
69
+ local = d / model_path.name
70
+ shutil.copyfile(model_path, local)
71
+ with t.Model(local):
72
+ pass
73
+
74
+
75
+ def test_init_backends_nonascii_dirs(tmp_path):
76
+ # The existing non-ASCII dir must not be misread as absent;
77
+ # FILE_NOT_FOUND specifically is the #1585 encoding bug. We do not
78
+ # assert OK: a module-less dir may legitimately report ERR_BACKEND
79
+ # depending on build posture.
80
+ lib = t._lib
81
+ d = _nonascii_dir(tmp_path)
82
+ st = lib.transcribe_init_backends(os.fspath(d).encode("utf-8"))
83
+ assert st != errors.ERR_FILE_NOT_FOUND
84
+
85
+ missing = d / "missing-subdir"
86
+ st = lib.transcribe_init_backends(os.fspath(missing).encode("utf-8"))
87
+ assert st == errors.ERR_FILE_NOT_FOUND
File without changes
File without changes
File without changes