oaknut-basic 12.12.0__tar.gz → 12.14.0__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.
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/PKG-INFO +1 -1
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/__init__.py +1 -1
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/cli.py +25 -9
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut_basic.egg-info/PKG-INFO +1 -1
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_cli.py +77 -3
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/LICENSE +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/README.md +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/pyproject.toml +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/setup.cfg +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/datafile.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/detect.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/detokeniser.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/dialect.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/exceptions.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/float5.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/linenumber.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/numbering.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/scanner.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/tokeniser.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut/basic/tokens.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut_basic.egg-info/SOURCES.txt +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut_basic.egg-info/dependency_links.txt +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut_basic.egg-info/entry_points.txt +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut_basic.egg-info/requires.txt +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut_basic.egg-info/top_level.txt +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_basic.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_basic_v.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_crunch_rules.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_data_cli.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_datafile.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_detect.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_detokeniser.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_float5.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_keyword_coverage.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_linenumber.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_numbering.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_rom_golden.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_rom_golden_detokenise.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_scanner.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_tokeniser.py +0 -0
- {oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/tests/test_tokens.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oaknut-basic
|
|
3
|
-
Version: 12.
|
|
3
|
+
Version: 12.14.0
|
|
4
4
|
Summary: BBC BASIC tools: program tokeniser/de-tokeniser and PRINT#/INPUT# data-file reader/writer
|
|
5
5
|
Author-email: Robert Smallshire <robert@smallshire.org.uk>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -13,6 +13,7 @@ from __future__ import annotations
|
|
|
13
13
|
|
|
14
14
|
import click
|
|
15
15
|
from asyoulikeit.cli import report_output
|
|
16
|
+
from oaknut.cli.help import use_plain_help
|
|
16
17
|
|
|
17
18
|
from . import __version__
|
|
18
19
|
|
|
@@ -107,12 +108,14 @@ def number(input_stream, output_stream, encoding: str, start: int, step: int) ->
|
|
|
107
108
|
|
|
108
109
|
Reads BASIC source text from INPUT and writes the numbered program
|
|
109
110
|
to OUTPUT. Both default to ``-``: INPUT to standard input, OUTPUT to
|
|
110
|
-
standard output, so the command works file-to-file
|
|
111
|
+
standard output, so the command works file-to-file:
|
|
111
112
|
|
|
113
|
+
\b
|
|
112
114
|
oaknut-basic number menu.bas menu-numbered.bas
|
|
113
115
|
|
|
114
|
-
and as a pipe stage between ``disc get`` and ``disc put
|
|
116
|
+
and as a pipe stage between ``disc get`` and ``disc put``:
|
|
115
117
|
|
|
118
|
+
\b
|
|
116
119
|
disc get game.ssd MENU - | oaknut-basic number --encoding acorn | disc put game.ssd MENU -
|
|
117
120
|
|
|
118
121
|
Text is read and written in ``--encoding`` (``utf-8`` by default; pass
|
|
@@ -216,15 +219,17 @@ def tokenise(
|
|
|
216
219
|
|
|
217
220
|
Reads numbered BASIC source from INPUT and writes the tokenised
|
|
218
221
|
program bytes to OUTPUT. Both default to ``-`` (stdin / stdout), so it
|
|
219
|
-
drops in alongside ``disc put
|
|
222
|
+
drops in alongside ``disc put``:
|
|
220
223
|
|
|
224
|
+
\b
|
|
221
225
|
oaknut-basic tokenise menu.bas MENU
|
|
222
226
|
cat menu.bas | oaknut-basic tokenise | disc put game.ssd MENU -
|
|
223
227
|
|
|
224
228
|
Passing --start and/or --step auto-numbers unnumbered source, exactly
|
|
225
229
|
as typing it under ``AUTO`` would; it is an error to use them on source
|
|
226
|
-
that already carries line numbers
|
|
230
|
+
that already carries line numbers:
|
|
227
231
|
|
|
232
|
+
\b
|
|
228
233
|
oaknut-basic tokenise --start 10 unnumbered.bas MENU
|
|
229
234
|
|
|
230
235
|
INPUT is read in --encoding (``utf-8`` by default, for source authored
|
|
@@ -274,8 +279,9 @@ def detokenise(input_stream, output_stream, encoding: str, dialect: str) -> None
|
|
|
274
279
|
|
|
275
280
|
Reads a tokenised program from INPUT and writes numbered source text
|
|
276
281
|
to OUTPUT. Both default to ``-`` (stdin / stdout), so it drops in
|
|
277
|
-
alongside ``disc get
|
|
282
|
+
alongside ``disc get``:
|
|
278
283
|
|
|
284
|
+
\b
|
|
279
285
|
oaknut-basic detokenise MENU menu.bas
|
|
280
286
|
disc get game.ssd MENU - | oaknut-basic detokenise
|
|
281
287
|
|
|
@@ -317,8 +323,9 @@ def detect(ctx: click.Context, inputs, quiet: bool) -> None:
|
|
|
317
323
|
line walk the BBC BASIC ROM performs to ``LIST`` a program — without
|
|
318
324
|
de-tokenising, so unlabelled files harvested from disc images can be
|
|
319
325
|
filtered. With no FILE, or ``-``, reads a single blob from standard
|
|
320
|
-
input
|
|
326
|
+
input:
|
|
321
327
|
|
|
328
|
+
\b
|
|
322
329
|
oaknut-basic detect *
|
|
323
330
|
disc get game.ssd MENU - | oaknut-basic detect
|
|
324
331
|
|
|
@@ -405,8 +412,9 @@ def decode(input_stream, encoding: str) -> None:
|
|
|
405
412
|
to standard output, one element per record: integers and reals as JSON
|
|
406
413
|
numbers, strings as JSON strings, and raw bytes as ``{"bytes": "hex"}``.
|
|
407
414
|
Reals keep their full ``float`` repr (e.g. ``5.0``) so they round-trip
|
|
408
|
-
back to reals rather than integers
|
|
415
|
+
back to reals rather than integers:
|
|
409
416
|
|
|
417
|
+
\b
|
|
410
418
|
oaknut-basic data decode scores.dat | jq '.[0]'
|
|
411
419
|
|
|
412
420
|
The output is consumed by ``oaknut-basic data encode`` to rebuild the
|
|
@@ -447,8 +455,9 @@ def encode(input_stream, output_stream, encoding: str) -> None:
|
|
|
447
455
|
INPUT and writes the tagged data file to OUTPUT. Each element becomes
|
|
448
456
|
one ``PRINT#`` record: a JSON integer becomes an integer, a JSON
|
|
449
457
|
number with a fractional part a real, a JSON string a string, and
|
|
450
|
-
``{"bytes": "hex"}`` raw (untagged) bytes
|
|
458
|
+
``{"bytes": "hex"}`` raw (untagged) bytes:
|
|
451
459
|
|
|
460
|
+
\b
|
|
452
461
|
echo '[42, "HELLO", 3.5]' | oaknut-basic data encode - scores.dat
|
|
453
462
|
|
|
454
463
|
A hand-authored real must carry a decimal point (``3.0``, not ``3``),
|
|
@@ -505,8 +514,9 @@ def inspect(input_stream, encoding: str):
|
|
|
505
514
|
"""Show the records in a BBC BASIC data file as a table.
|
|
506
515
|
|
|
507
516
|
Reads a ``PRINT#``-tagged data file from INPUT and reports each record
|
|
508
|
-
with its byte offset, type and value
|
|
517
|
+
with its byte offset, type and value:
|
|
509
518
|
|
|
519
|
+
\b
|
|
510
520
|
oaknut-basic data inspect scores.dat
|
|
511
521
|
oaknut-basic data inspect scores.dat --as json
|
|
512
522
|
|
|
@@ -527,5 +537,11 @@ def inspect(input_stream, encoding: str):
|
|
|
527
537
|
return Reports(records=Report(data=table))
|
|
528
538
|
|
|
529
539
|
|
|
540
|
+
# With the whole tree assembled, render every command's help with RST inline
|
|
541
|
+
# markup stripped — the docstrings keep their markup for the Sphinx command
|
|
542
|
+
# reference, but a terminal sees plain text, not stray backticks.
|
|
543
|
+
use_plain_help(cli)
|
|
544
|
+
|
|
545
|
+
|
|
530
546
|
if __name__ == "__main__": # pragma: no cover
|
|
531
547
|
cli()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oaknut-basic
|
|
3
|
-
Version: 12.
|
|
3
|
+
Version: 12.14.0
|
|
4
4
|
Summary: BBC BASIC tools: program tokeniser/de-tokeniser and PRINT#/INPUT# data-file reader/writer
|
|
5
5
|
Author-email: Robert Smallshire <robert@smallshire.org.uk>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -6,6 +6,7 @@ usage, the option parsing, and the byte/text (Acorn-encoding) boundary —
|
|
|
6
6
|
rather than re-testing the numbering or tokenising logic itself.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
import inspect
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
11
12
|
import oaknut.basic as basic
|
|
@@ -141,6 +142,81 @@ class TestTopLevel:
|
|
|
141
142
|
assert "number" in result.output
|
|
142
143
|
|
|
143
144
|
|
|
145
|
+
def _walk_commands(command, path=()):
|
|
146
|
+
"""Yield ``(argv, command)`` for every command and sub-command."""
|
|
147
|
+
yield list(path), command
|
|
148
|
+
for name, child in getattr(command, "commands", {}).items():
|
|
149
|
+
yield from _walk_commands(child, (*path, name))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _no_rewrap_lines(help_text):
|
|
153
|
+
"""Return the stripped lines of a docstring's ``\\b`` no-rewrap blocks."""
|
|
154
|
+
if not help_text:
|
|
155
|
+
return []
|
|
156
|
+
lines = inspect.cleandoc(help_text).splitlines()
|
|
157
|
+
marked = []
|
|
158
|
+
in_block = False
|
|
159
|
+
for line in lines:
|
|
160
|
+
if line.strip() == "\b":
|
|
161
|
+
in_block = True
|
|
162
|
+
elif not line.strip():
|
|
163
|
+
in_block = False
|
|
164
|
+
elif in_block:
|
|
165
|
+
# The asyoulikeit reports epilog is a \b block of prose that
|
|
166
|
+
# the help formatter deliberately re-wraps.
|
|
167
|
+
if line.strip() == "Produces reports:":
|
|
168
|
+
in_block = False
|
|
169
|
+
continue
|
|
170
|
+
marked.append(line.strip())
|
|
171
|
+
return marked
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
_ALL_COMMANDS = [
|
|
175
|
+
pytest.param(argv, id=" ".join(argv) or "oaknut-basic") for argv, _ in _walk_commands(cli)
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class TestHelpFormatting:
|
|
180
|
+
"""The example blocks in command docstrings must survive Click's rewrapper.
|
|
181
|
+
|
|
182
|
+
Click reflows every paragraph of a docstring unless it is preceded by
|
|
183
|
+
a ``\\b`` no-rewrap marker. Without one, a block of example command
|
|
184
|
+
lines is run together into a single paragraph and re-broken at
|
|
185
|
+
arbitrary points, which reads as two commands spliced together.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
@pytest.mark.parametrize("argv", _ALL_COMMANDS)
|
|
189
|
+
def test_docstring_example_lines_survive_verbatim(self, argv):
|
|
190
|
+
command = cli
|
|
191
|
+
for name in argv:
|
|
192
|
+
command = command.commands[name]
|
|
193
|
+
expected = _no_rewrap_lines(command.help)
|
|
194
|
+
if not expected:
|
|
195
|
+
pytest.skip("no example block in this command's docstring")
|
|
196
|
+
runner = CliRunner()
|
|
197
|
+
result = runner.invoke(cli, [*argv, "--help"])
|
|
198
|
+
assert result.exit_code == 0
|
|
199
|
+
rendered = {line.strip() for line in result.output.splitlines()}
|
|
200
|
+
for line in expected:
|
|
201
|
+
assert line in rendered, (
|
|
202
|
+
f"example line reflowed away in `{' '.join(argv)} --help`: {line!r}"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
@pytest.mark.parametrize("argv", _ALL_COMMANDS)
|
|
206
|
+
def test_no_rst_inline_markup_leaks(self, argv):
|
|
207
|
+
runner = CliRunner()
|
|
208
|
+
result = runner.invoke(cli, [*argv, "--help"])
|
|
209
|
+
assert result.exit_code == 0
|
|
210
|
+
assert "`" not in result.output
|
|
211
|
+
|
|
212
|
+
@pytest.mark.parametrize("argv", _ALL_COMMANDS)
|
|
213
|
+
def test_no_rst_literal_block_markers_leak(self, argv):
|
|
214
|
+
runner = CliRunner()
|
|
215
|
+
result = runner.invoke(cli, [*argv, "--help"])
|
|
216
|
+
assert result.exit_code == 0
|
|
217
|
+
assert " ::" not in result.output
|
|
218
|
+
|
|
219
|
+
|
|
144
220
|
class TestTokeniseCommand:
|
|
145
221
|
def test_pipe_tokenises_to_stdout(self):
|
|
146
222
|
runner = CliRunner()
|
|
@@ -192,9 +268,7 @@ class TestTokeniseEncoding:
|
|
|
192
268
|
# --encoding acorn treats the input as Acorn bytes already, so a
|
|
193
269
|
# 0x60 byte is the £ literal verbatim.
|
|
194
270
|
runner = CliRunner()
|
|
195
|
-
result = runner.invoke(
|
|
196
|
-
cli, ["tokenise", "--encoding", "acorn"], input=b'10 PRINT "\x60"\n'
|
|
197
|
-
)
|
|
271
|
+
result = runner.invoke(cli, ["tokenise", "--encoding", "acorn"], input=b'10 PRINT "\x60"\n')
|
|
198
272
|
assert result.exit_code == 0
|
|
199
273
|
assert b'"\x60"' in result.stdout_bytes
|
|
200
274
|
|
|
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
|
{oaknut_basic-12.12.0 → oaknut_basic-12.14.0}/src/oaknut_basic.egg-info/dependency_links.txt
RENAMED
|
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
|