mst-python 0.5.0__cp313-cp313-macosx_11_0_arm64.whl

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.
mst/__init__.py ADDED
@@ -0,0 +1,68 @@
1
+ """mst: CGO Python bindings for mst (Meta-Search Tool).
2
+
3
+ Concurrent multi-engine web search with RRF ranking, zero subprocess overhead.
4
+
5
+ Usage:
6
+ import mst
7
+
8
+ result = mst.search("rust async runtime comparison")
9
+ for item in result["results"]:
10
+ print(f"{item['rank']}. {item['title']}")
11
+
12
+ engines = mst.list_engines()
13
+ """
14
+
15
+ import asyncio
16
+
17
+ from ._mst import MSTError, list_engines, search
18
+
19
+ __all__ = ["search", "search_async", "list_engines", "MSTError"]
20
+
21
+
22
+ async def search_async(
23
+ query: str,
24
+ engines=None,
25
+ limit: int = 10,
26
+ offset: int = 0,
27
+ rrf_k: int = 60,
28
+ timeout: str = "8s",
29
+ weights=None,
30
+ ) -> dict:
31
+ """Async wrapper around :func:`search`.
32
+
33
+ The native CGO call is blocking (the Go runtime releases the GIL while it
34
+ runs), so this thin wrapper offloads it to the event loop's default executor
35
+ via :func:`asyncio.to_thread`. It returns the same envelope and raises the
36
+ same :class:`MSTError` as :func:`search`.
37
+
38
+ This is intentionally *not* a second search implementation: every argument
39
+ is forwarded unchanged.
40
+ """
41
+ return await asyncio.to_thread(
42
+ search,
43
+ query,
44
+ engines=engines,
45
+ limit=limit,
46
+ offset=offset,
47
+ rrf_k=rrf_k,
48
+ timeout=timeout,
49
+ weights=weights,
50
+ )
51
+
52
+ # Reflect the installed distribution version (populated by setup.py from the
53
+ # release tag). Falls back when run from a source tree that isn't installed.
54
+ try:
55
+ from importlib.metadata import PackageNotFoundError, version as _dist_version
56
+
57
+ # The PyPI distribution is `mst-python` while the import package is `mst`;
58
+ # accept either name so editable/source installs and wheels both work.
59
+ for _dist in ("mst-python", "mst"):
60
+ try:
61
+ __version__ = _dist_version(_dist)
62
+ break
63
+ except PackageNotFoundError:
64
+ continue
65
+ else:
66
+ __version__ = "0.0.0-dev"
67
+ except ImportError: # Python <3.8 (unsupported, but stay safe)
68
+ __version__ = "0.0.0-dev"
Binary file
mst/_mst.so ADDED
Binary file
@@ -0,0 +1,136 @@
1
+ Metadata-Version: 2.4
2
+ Name: mst-python
3
+ Version: 0.5.0
4
+ Summary: CGO Python bindings for mst (Meta-Search Tool) — concurrent multi-engine web search with RRF ranking
5
+ Author: mst contributors
6
+ License-Expression: Apache-2.0
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Python: >=3.11
14
+ Description-Content-Type: text/markdown
15
+
16
+ # mst-python — Meta Search Tool (Python bindings)
17
+
18
+ [![Release](https://github.com/openmtx/meta-search-tool/actions/workflows/release.yml/badge.svg)](https://github.com/openmtx/meta-search-tool/actions/workflows/release.yml)
19
+ [![PyPI](https://img.shields.io/pypi/v/mst-python)](https://pypi.org/project/mst-python/)
20
+ [![Python Versions](https://img.shields.io/pypi/pyversions/mst-python)](https://pypi.org/project/mst-python/)
21
+
22
+ CGO Python bindings for **mst** — a concurrent multi-engine web search tool with
23
+ transparent RRF ranking. Fan out to 12+ engines in parallel, get merged JSON
24
+ results with scores. No server, no setup.
25
+
26
+ ```python
27
+ import mst
28
+
29
+ # Search across all enabled engines
30
+ result = mst.search("rust async runtime comparison")
31
+
32
+ # Or pick specific engines
33
+ result = mst.search("riscv paging", engines=["ddg", "google"], limit=10)
34
+
35
+ print(f"Found {len(result['results'])} results in {result['took_ms']}ms")
36
+ for r in result['results']:
37
+ print(f" #{r['rank']} {r['title']} (score={r['score']})")
38
+ ```
39
+
40
+ ## Features
41
+
42
+ - **14 engines** across general web, academic, reference, Q&A, and AI categories
43
+ - **Concurrent fan-out** with per-engine timeouts — a slow engine never blocks the run
44
+ - **RRF ranking** with configurable per-engine weights and smoothing constant
45
+ - **Keyless engines** work out of the box: DuckDuckGo, Google, Wikipedia, arXiv, Europe PMC, and more
46
+ - **Keyed engines** (Brave, Bing, Tavily, Jina) ready when you set their API keys
47
+ - **Async API** (`search_async`) for asyncio consumers; the native call releases the GIL
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install mst-python
53
+ ```
54
+
55
+ Works on Linux (manylinux_2_34 x86_64) and macOS (Apple Silicon arm64).
56
+
57
+ ## Quick start
58
+
59
+ ```python
60
+ import mst
61
+
62
+ # List all engines and their status
63
+ engines = mst.list_engines()
64
+ for e in engines:
65
+ print(f"{e['name']:20s} {e['status']:15s} weight={e['weight']}")
66
+
67
+ # Run a search
68
+ result = mst.search("python asyncio vs threading", limit=5)
69
+ print(result)
70
+ ```
71
+
72
+ ## API
73
+
74
+ ### `mst.search(query, engines=None, limit=10, offset=0, rrf_k=60, timeout="8s", weights=None)`
75
+
76
+ | Param | Type | Default | Description |
77
+ |-------|------|---------|-------------|
78
+ | `query` | `str` | — | Search query |
79
+ | `engines` | `list[str]` or `None` | `None` | Engine whitelist (`None` = all enabled engines) |
80
+ | `limit` | `int` | `10` | Max merged results (1–100) |
81
+ | `offset` | `int` | `0` | Skip first N results |
82
+ | `rrf_k` | `int` | `60` | RRF smoothing constant |
83
+ | `timeout` | `str` | `"8s"` | Per-engine timeout duration |
84
+ | `weights` | `dict[str, float]` or `None` | `None` | Per-engine weight overrides |
85
+
86
+ Returns a dict with `query`, `took_ms`, `results` (list of ranked results).
87
+
88
+ ### `await mst.search_async(...)`
89
+
90
+ Async wrapper around `mst.search()` with the same arguments, return value, and
91
+ `MSTError` behavior. It is **additive**: existing consumers that call
92
+ `asyncio.to_thread(mst.search, ...)` keep working and can adopt the wrapper
93
+ later without a breaking change. It forwards the blocking native call to
94
+ `asyncio.to_thread`, so the event loop keeps running during a search. The native
95
+ CGO library releases the GIL, so concurrent `search_async()` calls overlap
96
+ instead of serializing.
97
+
98
+ ```python
99
+ import asyncio
100
+ import mst
101
+
102
+ async def main():
103
+ results = await asyncio.gather(
104
+ mst.search_async("rust async", limit=5),
105
+ mst.search_async("python asyncio", limit=5),
106
+ mst.search_async("go concurrency", limit=5),
107
+ )
108
+ for result in results:
109
+ print(result["query"], len(result["results"]))
110
+
111
+ asyncio.run(main())
112
+ ```
113
+
114
+ Cancellation note: `asyncio.wait_for(asyncio.shield(...))` and task cancellation
115
+ stop the *await*, not the native call. The `timeout` argument bounds the Go-side
116
+ search; a cancelled worker may finish in the background, and subsequent calls
117
+ are unaffected.
118
+
119
+ ### `mst.list_engines()`
120
+
121
+ Returns a list of engine dicts with `name`, `enabled`, `keyed`, `weight`, `category`, `status`.
122
+
123
+ ### `mst.__version__`
124
+
125
+ Package version string (derived from the release tag when installed via PyPI).
126
+
127
+ ## Requirements
128
+
129
+ - Python ≥ 3.11
130
+ - Linux (x86_64, glibc ≥ 2.34) or macOS (arm64)
131
+
132
+ No runtime dependencies — the CGO shared library is bundled in the wheel.
133
+
134
+ ## License
135
+
136
+ Apache-2.0. See [`LICENSE`](https://github.com/openmtx/meta-search-tool/blob/master/LICENSE).
@@ -0,0 +1,7 @@
1
+ mst/__init__.py,sha256=4MfzqZrtwPVQ_HelYZZtRKOMEZAH2CKB9knJhY-L30w,2018
2
+ mst/_mst.cpython-313-darwin.so,sha256=ugHIFSpJ2QQ0jqFs2gez4AAl2hFtfQPO3-wFYWD-Hj4,225784
3
+ mst/_mst.so,sha256=HWSOg0W5IGJSio-EvCzaEX_5CA9QNkW8GCuwbb4cKs0,8143618
4
+ mst_python-0.5.0.dist-info/METADATA,sha256=7CWAWi-5VaxLhA4Q_NwLLIKYkrL978jVuV2lOLA4ons,4876
5
+ mst_python-0.5.0.dist-info/WHEEL,sha256=jwhzPYYq_elOrllGS_u-swnOG8oOXKyYlwLR2jLV2VE,109
6
+ mst_python-0.5.0.dist-info/top_level.txt,sha256=wWnObFIH0CbsgenDXlDpKZv1zdBkbCM4iASswi0Vofw,4
7
+ mst_python-0.5.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: false
4
+ Tag: cp313-cp313-macosx_11_0_arm64
5
+
@@ -0,0 +1 @@
1
+ mst