briskapi 0.2.0__tar.gz → 0.2.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.
- {briskapi-0.2.0 → briskapi-0.2.2}/PKG-INFO +22 -10
- {briskapi-0.2.0 → briskapi-0.2.2}/README.md +8 -9
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/__init__.py +1 -1
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/_live.py +2 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/cli.py +27 -1
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi.egg-info/PKG-INFO +22 -10
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi.egg-info/SOURCES.txt +1 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/pyproject.toml +16 -1
- {briskapi-0.2.0 → briskapi-0.2.2}/tests/test_archive.py +2 -0
- briskapi-0.2.2/tests/test_package.py +92 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/LICENSE +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/LICENSE-pybrisk.txt +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/__main__.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/_archive.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/_market.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/_recording.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/archive.json +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/decoder/assets.json +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/decoder/decoder.cjs +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/decoder/sbi.cjs +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/decoder/web.cjs +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/references/historical_mock.json +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/sbi.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/schema.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi/timing.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi.egg-info/dependency_links.txt +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi.egg-info/entry_points.txt +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi.egg-info/requires.txt +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/briskapi.egg-info/top_level.txt +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/setup.cfg +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/tests/test_api.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/tests/test_sbi.py +0 -0
- {briskapi-0.2.0 → briskapi-0.2.2}/tests/test_timing.py +0 -0
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: briskapi
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Unofficial Python API, live feed and shared archive for BRiSK auction data
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Source, https://github.com/honvl/BRiSKapi
|
|
7
|
+
Project-URL: Issues, https://github.com/honvl/BRiSKapi/issues
|
|
8
|
+
Project-URL: Releases, https://github.com/honvl/BRiSKapi/releases
|
|
9
|
+
Project-URL: Privacy, https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md
|
|
10
|
+
Keywords: brisk,market-data,auction,tokyo-stock-exchange,japan,sbi
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
7
20
|
Requires-Python: >=3.12
|
|
8
21
|
Description-Content-Type: text/markdown
|
|
9
22
|
License-File: LICENSE
|
|
@@ -14,7 +27,7 @@ Dynamic: license-file
|
|
|
14
27
|
|
|
15
28
|
# briskapi
|
|
16
29
|
|
|
17
|
-
[English](README.md) | [日本語](README.ja.md)
|
|
30
|
+
[English](https://github.com/honvl/BRiSKapi/blob/main/README.md) | [日本語](https://github.com/honvl/BRiSKapi/blob/main/README.ja.md)
|
|
18
31
|
|
|
19
32
|
An unofficial, pybrisk-style Python API and `brisk` command line for BRiSK auction
|
|
20
33
|
data. Consume a live feed, query recordings at any point in time, pull shared
|
|
@@ -179,7 +192,7 @@ API never asks: until you decide, sessions stay on your computer.
|
|
|
179
192
|
alias (random `anon-…` by default) and license. Your IP address is used only to
|
|
180
193
|
rate limit uploads.
|
|
181
194
|
- **Visibility:** published recordings are public and permanent, and you cannot
|
|
182
|
-
delete them yourself. See [PRIVACY.md](PRIVACY.md).
|
|
195
|
+
delete them yourself. See [PRIVACY.md](https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md).
|
|
183
196
|
- **Opting out:** `brisk consent --revoke`, `BRISK_CONTRIBUTE=0`, or `--no-upload`
|
|
184
197
|
for one run.
|
|
185
198
|
- **License:** accepting declares that you may redistribute the recordings under
|
|
@@ -190,12 +203,11 @@ API never asks: until you decide, sessions stay on your computer.
|
|
|
190
203
|
|
|
191
204
|
## More documentation
|
|
192
205
|
|
|
193
|
-
- [ARCHITECTURE.md](ARCHITECTURE.md): how it works, data format, archive integrity and limits
|
|
194
|
-
- [PRIVACY.md](PRIVACY.md): privacy policy
|
|
195
|
-
- [CONTRIBUTING.md](CONTRIBUTING.md): development, tests and releases
|
|
196
|
-
- [tools/brisk_mock/README.md](tools/brisk_mock/README.md): Rust collector, field definitions, timing and latency
|
|
197
|
-
- [
|
|
198
|
-
- [
|
|
199
|
-
- [THIRD_PARTY.md](THIRD_PARTY.md): decoder, data and pybrisk attribution
|
|
206
|
+
- [ARCHITECTURE.md](https://github.com/honvl/BRiSKapi/blob/main/ARCHITECTURE.md): how it works, data format, archive integrity and limits
|
|
207
|
+
- [PRIVACY.md](https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md): privacy policy
|
|
208
|
+
- [CONTRIBUTING.md](https://github.com/honvl/BRiSKapi/blob/main/CONTRIBUTING.md): development, tests and releases
|
|
209
|
+
- [tools/brisk_mock/README.md](https://github.com/honvl/BRiSKapi/blob/main/tools/brisk_mock/README.md): Rust collector, field definitions, timing and latency
|
|
210
|
+
- [infra/README.md](https://github.com/honvl/BRiSKapi/blob/main/infra/README.md): deploying your own archive
|
|
211
|
+
- [THIRD_PARTY.md](https://github.com/honvl/BRiSKapi/blob/main/THIRD_PARTY.md): decoder, data and pybrisk attribution
|
|
200
212
|
|
|
201
213
|
Software is MIT licensed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# briskapi
|
|
2
2
|
|
|
3
|
-
[English](README.md) | [日本語](README.ja.md)
|
|
3
|
+
[English](https://github.com/honvl/BRiSKapi/blob/main/README.md) | [日本語](https://github.com/honvl/BRiSKapi/blob/main/README.ja.md)
|
|
4
4
|
|
|
5
5
|
An unofficial, pybrisk-style Python API and `brisk` command line for BRiSK auction
|
|
6
6
|
data. Consume a live feed, query recordings at any point in time, pull shared
|
|
@@ -165,7 +165,7 @@ API never asks: until you decide, sessions stay on your computer.
|
|
|
165
165
|
alias (random `anon-…` by default) and license. Your IP address is used only to
|
|
166
166
|
rate limit uploads.
|
|
167
167
|
- **Visibility:** published recordings are public and permanent, and you cannot
|
|
168
|
-
delete them yourself. See [PRIVACY.md](PRIVACY.md).
|
|
168
|
+
delete them yourself. See [PRIVACY.md](https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md).
|
|
169
169
|
- **Opting out:** `brisk consent --revoke`, `BRISK_CONTRIBUTE=0`, or `--no-upload`
|
|
170
170
|
for one run.
|
|
171
171
|
- **License:** accepting declares that you may redistribute the recordings under
|
|
@@ -176,12 +176,11 @@ API never asks: until you decide, sessions stay on your computer.
|
|
|
176
176
|
|
|
177
177
|
## More documentation
|
|
178
178
|
|
|
179
|
-
- [ARCHITECTURE.md](ARCHITECTURE.md): how it works, data format, archive integrity and limits
|
|
180
|
-
- [PRIVACY.md](PRIVACY.md): privacy policy
|
|
181
|
-
- [CONTRIBUTING.md](CONTRIBUTING.md): development, tests and releases
|
|
182
|
-
- [tools/brisk_mock/README.md](tools/brisk_mock/README.md): Rust collector, field definitions, timing and latency
|
|
183
|
-
- [
|
|
184
|
-
- [
|
|
185
|
-
- [THIRD_PARTY.md](THIRD_PARTY.md): decoder, data and pybrisk attribution
|
|
179
|
+
- [ARCHITECTURE.md](https://github.com/honvl/BRiSKapi/blob/main/ARCHITECTURE.md): how it works, data format, archive integrity and limits
|
|
180
|
+
- [PRIVACY.md](https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md): privacy policy
|
|
181
|
+
- [CONTRIBUTING.md](https://github.com/honvl/BRiSKapi/blob/main/CONTRIBUTING.md): development, tests and releases
|
|
182
|
+
- [tools/brisk_mock/README.md](https://github.com/honvl/BRiSKapi/blob/main/tools/brisk_mock/README.md): Rust collector, field definitions, timing and latency
|
|
183
|
+
- [infra/README.md](https://github.com/honvl/BRiSKapi/blob/main/infra/README.md): deploying your own archive
|
|
184
|
+
- [THIRD_PARTY.md](https://github.com/honvl/BRiSKapi/blob/main/THIRD_PARTY.md): decoder, data and pybrisk attribution
|
|
186
185
|
|
|
187
186
|
Software is MIT licensed.
|
|
@@ -18,7 +18,7 @@ from briskapi._live import Feed, connect as _connect, record as _record, stream
|
|
|
18
18
|
from briskapi._market import Market, Ticker
|
|
19
19
|
from briskapi._recording import JST, BriskError, NotFoundError, Recording, Table
|
|
20
20
|
|
|
21
|
-
__version__ = '0.2.
|
|
21
|
+
__version__ = '0.2.2'
|
|
22
22
|
__all__ = ['JST', 'Archive', 'BriskError', 'Feed', 'Market', 'NotFoundError', 'Recording', 'Table', 'Ticker',
|
|
23
23
|
'connect', 'consent', 'current', 'load', 'pull', 'record', 'recordings', 'stream']
|
|
24
24
|
|
|
@@ -45,6 +45,7 @@ def _stop(process):
|
|
|
45
45
|
|
|
46
46
|
def stream(web=False, cache=None, codes=None, speed=1, limit_frames=None, node='node') -> Iterator[dict]:
|
|
47
47
|
"""Yield raw decoded batches as each frame replays (bootstrap, quote deltas, end)."""
|
|
48
|
+
cli.check_node(node)
|
|
48
49
|
process = _decoder(web, cache, codes, speed, limit_frames, node)
|
|
49
50
|
try:
|
|
50
51
|
for line in process.stdout:
|
|
@@ -90,6 +91,7 @@ class Feed:
|
|
|
90
91
|
history=False, node='node', *, command=None, env=None, timing=None):
|
|
91
92
|
# `command` runs another decoder host (SBI live). Its market data is never
|
|
92
93
|
# contributed; with `timing` set, a timing-only summary may be.
|
|
94
|
+
cli.check_node(command[0] if command else node)
|
|
93
95
|
if command is None:
|
|
94
96
|
choice, upload = _consent(contribute, limit_frames)
|
|
95
97
|
self._choice, self._timing = (choice if upload else None), None
|
|
@@ -20,12 +20,14 @@ import warnings
|
|
|
20
20
|
import boto3
|
|
21
21
|
from botocore import UNSIGNED
|
|
22
22
|
from botocore.config import Config
|
|
23
|
+
from briskapi._recording import BriskError
|
|
23
24
|
from briskapi.schema import (SCHEMA, MAX_TIMING_BYTES, canonical_lines, compress, digest, inspect_package, validate_manifest,
|
|
24
25
|
validate_stream, validate_timing, require)
|
|
25
26
|
|
|
26
27
|
PACKAGE = Path(__file__).resolve().parent
|
|
27
28
|
# BRiSK's own WASM decoder runs under Node; the package ships only this host and SHA-256 pins.
|
|
28
29
|
DECODER = PACKAGE / 'decoder' / 'decoder.cjs'
|
|
30
|
+
MIN_NODE = 22
|
|
29
31
|
LICENSES = ('CC0-1.0', 'CC-BY-4.0')
|
|
30
32
|
# Bump with any PRIVACY.md change to what is collected; saved choices then lapse.
|
|
31
33
|
POLICY_VERSION = 2
|
|
@@ -46,6 +48,20 @@ Policy: https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md
|
|
|
46
48
|
Opt out at any time: `brisk consent --revoke` or BRISK_CONTRIBUTE=0.
|
|
47
49
|
'''
|
|
48
50
|
|
|
51
|
+
def check_node(node='node'):
|
|
52
|
+
"""Fail early, with the fix, when Node is missing or older than the decoder hosts support."""
|
|
53
|
+
advice = f'Install Node.js {MIN_NODE} or newer from https://nodejs.org, or pass the path to it.'
|
|
54
|
+
try:
|
|
55
|
+
out = subprocess.run([node, '--version'], capture_output=True, text=True, timeout=30).stdout
|
|
56
|
+
except FileNotFoundError:
|
|
57
|
+
raise BriskError(f'Node.js was not found (looked for {str(node)!r}). BRiSK\'s decoder runs under Node. {advice}') from None
|
|
58
|
+
except (OSError, subprocess.SubprocessError) as error:
|
|
59
|
+
raise BriskError(f'Could not run {str(node)!r} --version: {error}. {advice}') from error
|
|
60
|
+
found = re.match(r'v(\d+)\.', out.strip())
|
|
61
|
+
if found and int(found[1]) < MIN_NODE:
|
|
62
|
+
raise BriskError(f'Node.js {out.strip()} is too old; the decoder hosts need Node {MIN_NODE}+. {advice}')
|
|
63
|
+
|
|
64
|
+
|
|
49
65
|
def settings(path=None):
|
|
50
66
|
return json.loads((path or PACKAGE / 'archive.json').read_text())
|
|
51
67
|
|
|
@@ -211,6 +227,7 @@ def record_events(events, web=False, cache=None, codes=None, limit_frames=None,
|
|
|
211
227
|
Needs only Node. A Rust collector binary (`brisk_quote_ingest`) is optional; it
|
|
212
228
|
records the same batches and adds its own state validation and latency display.
|
|
213
229
|
"""
|
|
230
|
+
check_node(node)
|
|
214
231
|
options = ['--web'] if web else ['--cache', str(cache)]
|
|
215
232
|
options += ['--speed', str(speed)]
|
|
216
233
|
if codes:
|
|
@@ -250,7 +267,16 @@ def live(args):
|
|
|
250
267
|
print(json.dumps({'contribution': feed.contribution}), file=sys.stderr)
|
|
251
268
|
|
|
252
269
|
def main(argv=None):
|
|
253
|
-
|
|
270
|
+
try:
|
|
271
|
+
_main(argv)
|
|
272
|
+
except BriskError as error:
|
|
273
|
+
sys.exit(f'brisk: error: {error}')
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _main(argv):
|
|
277
|
+
from briskapi import __version__
|
|
278
|
+
parser = argparse.ArgumentParser(prog='brisk', description=__doc__)
|
|
279
|
+
parser.add_argument('--version', action='version', version=f'%(prog)s {__version__}')
|
|
254
280
|
parser.add_argument('--config', type=Path, default=PACKAGE / 'archive.json')
|
|
255
281
|
sub = parser.add_subparsers(dest='command', required=True)
|
|
256
282
|
for name in ('record', 'package'):
|
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: briskapi
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Unofficial Python API, live feed and shared archive for BRiSK auction data
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Source, https://github.com/honvl/BRiSKapi
|
|
7
|
+
Project-URL: Issues, https://github.com/honvl/BRiSKapi/issues
|
|
8
|
+
Project-URL: Releases, https://github.com/honvl/BRiSKapi/releases
|
|
9
|
+
Project-URL: Privacy, https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md
|
|
10
|
+
Keywords: brisk,market-data,auction,tokyo-stock-exchange,japan,sbi
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
7
20
|
Requires-Python: >=3.12
|
|
8
21
|
Description-Content-Type: text/markdown
|
|
9
22
|
License-File: LICENSE
|
|
@@ -14,7 +27,7 @@ Dynamic: license-file
|
|
|
14
27
|
|
|
15
28
|
# briskapi
|
|
16
29
|
|
|
17
|
-
[English](README.md) | [日本語](README.ja.md)
|
|
30
|
+
[English](https://github.com/honvl/BRiSKapi/blob/main/README.md) | [日本語](https://github.com/honvl/BRiSKapi/blob/main/README.ja.md)
|
|
18
31
|
|
|
19
32
|
An unofficial, pybrisk-style Python API and `brisk` command line for BRiSK auction
|
|
20
33
|
data. Consume a live feed, query recordings at any point in time, pull shared
|
|
@@ -179,7 +192,7 @@ API never asks: until you decide, sessions stay on your computer.
|
|
|
179
192
|
alias (random `anon-…` by default) and license. Your IP address is used only to
|
|
180
193
|
rate limit uploads.
|
|
181
194
|
- **Visibility:** published recordings are public and permanent, and you cannot
|
|
182
|
-
delete them yourself. See [PRIVACY.md](PRIVACY.md).
|
|
195
|
+
delete them yourself. See [PRIVACY.md](https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md).
|
|
183
196
|
- **Opting out:** `brisk consent --revoke`, `BRISK_CONTRIBUTE=0`, or `--no-upload`
|
|
184
197
|
for one run.
|
|
185
198
|
- **License:** accepting declares that you may redistribute the recordings under
|
|
@@ -190,12 +203,11 @@ API never asks: until you decide, sessions stay on your computer.
|
|
|
190
203
|
|
|
191
204
|
## More documentation
|
|
192
205
|
|
|
193
|
-
- [ARCHITECTURE.md](ARCHITECTURE.md): how it works, data format, archive integrity and limits
|
|
194
|
-
- [PRIVACY.md](PRIVACY.md): privacy policy
|
|
195
|
-
- [CONTRIBUTING.md](CONTRIBUTING.md): development, tests and releases
|
|
196
|
-
- [tools/brisk_mock/README.md](tools/brisk_mock/README.md): Rust collector, field definitions, timing and latency
|
|
197
|
-
- [
|
|
198
|
-
- [
|
|
199
|
-
- [THIRD_PARTY.md](THIRD_PARTY.md): decoder, data and pybrisk attribution
|
|
206
|
+
- [ARCHITECTURE.md](https://github.com/honvl/BRiSKapi/blob/main/ARCHITECTURE.md): how it works, data format, archive integrity and limits
|
|
207
|
+
- [PRIVACY.md](https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md): privacy policy
|
|
208
|
+
- [CONTRIBUTING.md](https://github.com/honvl/BRiSKapi/blob/main/CONTRIBUTING.md): development, tests and releases
|
|
209
|
+
- [tools/brisk_mock/README.md](https://github.com/honvl/BRiSKapi/blob/main/tools/brisk_mock/README.md): Rust collector, field definitions, timing and latency
|
|
210
|
+
- [infra/README.md](https://github.com/honvl/BRiSKapi/blob/main/infra/README.md): deploying your own archive
|
|
211
|
+
- [THIRD_PARTY.md](https://github.com/honvl/BRiSKapi/blob/main/THIRD_PARTY.md): decoder, data and pybrisk attribution
|
|
200
212
|
|
|
201
213
|
Software is MIT licensed.
|
|
@@ -4,18 +4,33 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "briskapi"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "Unofficial Python API, live feed and shared archive for BRiSK auction data"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
11
11
|
requires-python = ">=3.12"
|
|
12
12
|
dependencies = ["boto3>=1.41,<2"]
|
|
13
|
+
keywords = ["brisk", "market-data", "auction", "tokyo-stock-exchange", "japan", "sbi"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
24
|
+
]
|
|
13
25
|
|
|
14
26
|
[project.optional-dependencies]
|
|
15
27
|
pandas = ["pandas>=2"]
|
|
16
28
|
|
|
17
29
|
[project.urls]
|
|
18
30
|
Source = "https://github.com/honvl/BRiSKapi"
|
|
31
|
+
Issues = "https://github.com/honvl/BRiSKapi/issues"
|
|
32
|
+
Releases = "https://github.com/honvl/BRiSKapi/releases"
|
|
33
|
+
Privacy = "https://github.com/honvl/BRiSKapi/blob/main/PRIVACY.md"
|
|
19
34
|
|
|
20
35
|
[project.scripts]
|
|
21
36
|
brisk = "briskapi.cli:main"
|
|
@@ -448,6 +448,7 @@ def harness(tmp_path, monkeypatch):
|
|
|
448
448
|
else:
|
|
449
449
|
Path(cmd[cmd.index('--events') + 1]).write_bytes(raw(batches()))
|
|
450
450
|
monkeypatch.setattr(cli.subprocess, 'run', run)
|
|
451
|
+
monkeypatch.setattr(cli, 'check_node', lambda node='node': None)
|
|
451
452
|
(tmp_path / 'source.jsonl').write_bytes(raw(batches()))
|
|
452
453
|
def main(*args):
|
|
453
454
|
cli.main(['--config', str(config), *args])
|
|
@@ -529,6 +530,7 @@ def test_consent_controls(tmp_path, monkeypatch, harness, capsys):
|
|
|
529
530
|
def test_record_events_command(monkeypatch, tmp_path):
|
|
530
531
|
calls = []
|
|
531
532
|
monkeypatch.setattr(cli.subprocess, 'run', lambda cmd, check, stdout=None: calls.append((cmd, stdout)))
|
|
533
|
+
monkeypatch.setattr(cli, 'check_node', lambda node='node': None)
|
|
532
534
|
cli.record_events(tmp_path / 'e.jsonl', cache=tmp_path, codes=['7203', '6758'], limit_frames=5, speed=0)
|
|
533
535
|
cmd, stdout = calls[0]
|
|
534
536
|
assert cmd[:2] == ['node', str(cli.DECODER)] and stdout is not None and cli.DECODER.exists()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Install-time behavior: the Node preflight, --version and the PyPI package description."""
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
import tomllib
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
import briskapi
|
|
10
|
+
import briskapi.cli as cli
|
|
11
|
+
from briskapi import _live, sbi
|
|
12
|
+
|
|
13
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture(autouse=True)
|
|
17
|
+
def isolated(tmp_path, monkeypatch):
|
|
18
|
+
monkeypatch.setenv('XDG_CONFIG_HOME', str(tmp_path / 'config'))
|
|
19
|
+
monkeypatch.delenv('BRISK_CONTRIBUTE', raising=False)
|
|
20
|
+
monkeypatch.setattr(briskapi, '_current', None)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def fake_node(tmp_path, output, executable=True):
|
|
24
|
+
script = tmp_path / 'fake-node'
|
|
25
|
+
script.write_text(f'#!/bin/sh\necho {output}\n')
|
|
26
|
+
script.chmod(0o755 if executable else 0o644)
|
|
27
|
+
return str(script)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_check_node_accepts_supported_versions(tmp_path):
|
|
31
|
+
for output in ('v22.0.0', 'v25.2.1', 'unrecognised output'):
|
|
32
|
+
cli.check_node(fake_node(tmp_path, output))
|
|
33
|
+
cli.check_node() # The real node on PATH, as the other tests need.
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_check_node_explains_how_to_fix_it(tmp_path):
|
|
37
|
+
with pytest.raises(briskapi.BriskError, match=r'Node\.js was not found.*nodejs\.org'):
|
|
38
|
+
cli.check_node(str(tmp_path / 'missing'))
|
|
39
|
+
with pytest.raises(briskapi.BriskError, match=r'v20\.11\.0 is too old.*Node 22\+.*nodejs\.org'):
|
|
40
|
+
cli.check_node(fake_node(tmp_path, 'v20.11.0'))
|
|
41
|
+
with pytest.raises(briskapi.BriskError, match=r'Could not run.*nodejs\.org'):
|
|
42
|
+
cli.check_node(fake_node(tmp_path, 'v22.0.0', executable=False))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_check_node_reports_a_hung_node(monkeypatch):
|
|
46
|
+
def hang(*args, **kwargs):
|
|
47
|
+
raise subprocess.TimeoutExpired('node', 30)
|
|
48
|
+
|
|
49
|
+
monkeypatch.setattr(cli.subprocess, 'run', hang)
|
|
50
|
+
with pytest.raises(briskapi.BriskError, match='Could not run'):
|
|
51
|
+
cli.check_node()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_every_entry_point_checks_node_first(tmp_path):
|
|
55
|
+
missing = str(tmp_path / 'missing')
|
|
56
|
+
with pytest.raises(briskapi.BriskError, match='not found'):
|
|
57
|
+
next(_live.stream(cache=tmp_path, node=missing))
|
|
58
|
+
with pytest.raises(briskapi.BriskError, match='not found'):
|
|
59
|
+
briskapi.Feed(cache=tmp_path, node=missing)
|
|
60
|
+
with pytest.raises(briskapi.BriskError, match='not found'):
|
|
61
|
+
briskapi.connect(cache=tmp_path, node=missing)
|
|
62
|
+
with pytest.raises(briskapi.BriskError, match='not found'):
|
|
63
|
+
cli.record_events(tmp_path / 'events.jsonl', cache=tmp_path, node=missing)
|
|
64
|
+
sbi.login({'session_bfaf77a2': 'v'})
|
|
65
|
+
with pytest.raises(briskapi.BriskError, match='not found'):
|
|
66
|
+
sbi.connect(node=missing)
|
|
67
|
+
assert briskapi._current is None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_cli_reports_errors_without_a_traceback(tmp_path, monkeypatch):
|
|
71
|
+
monkeypatch.setenv('PATH', str(tmp_path))
|
|
72
|
+
with pytest.raises(SystemExit) as stopped:
|
|
73
|
+
cli.main(['live', '--cache', str(tmp_path)])
|
|
74
|
+
assert str(stopped.value.code).startswith('brisk: error: Node.js was not found')
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_cli_version(capsys):
|
|
78
|
+
with pytest.raises(SystemExit) as stopped:
|
|
79
|
+
cli.main(['--version'])
|
|
80
|
+
assert stopped.value.code == 0
|
|
81
|
+
assert capsys.readouterr().out.strip() == f'brisk {briskapi.__version__}'
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_version_matches_pyproject():
|
|
85
|
+
project = tomllib.loads((ROOT / 'pyproject.toml').read_text())['project']
|
|
86
|
+
assert project['version'] == briskapi.__version__
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_readme_links_work_on_pypi():
|
|
90
|
+
# README.md is the PyPI description, where relative links do not resolve.
|
|
91
|
+
readme = (ROOT / 'README.md').read_text()
|
|
92
|
+
assert not re.findall(r'\]\((?!https?://|#|mailto:)[^)]+\)', readme)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|