diff --git a/.github/workflows/build_linux_v2.yml b/.github/workflows/build_linux_v2.yml new file mode 100644 index 0000000..0c345c4 --- /dev/null +++ b/.github/workflows/build_linux_v2.yml @@ -0,0 +1,57 @@ +name: Build Wheels (Linux) + +on: + workflow_dispatch: + inputs: {} + +jobs: + linux: + strategy: + matrix: + arch: + - x86_64 + - i686 + - aarch64 + - ppc64le + - armv7l + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: all + + - name: Cache pip + uses: actions/cache@v4 + with: + key: cache--${{ hashFiles('./requirements-dev.txt') }} + path: ~/.cache/pip + + - name: Setup python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - run: python -m pip install -U pip wheel setuptools + - run: python -m pip install -Ur requirements-dev.txt + - run: python -m pip install -U 'cibuildwheel==2.*' + + - run: make prepare + + - run: python -m cibuildwheel --output-dir wheelhouse + env: + CIBW_ARCHS_LINUX: ${{ matrix.arch }} + CIBW_BUILD_FRONTEND: build + CIBW_SKIP: 'cp27-* pp*' + CIBW_DEPENDENCY_VERSIONS: pinned + CIBW_PLATFORM: linux + CIBW_TEST_COMMAND: python {project}/scripts/run-tests.py + + - uses: actions/upload-artifact@v4 + with: + name: linux-${{ matrix.arch }} + path: ./wheelhouse diff --git a/scripts/make_unicode_categories.py b/scripts/make_unicode_categories.py index 51d89d9..54d3a31 100755 --- a/scripts/make_unicode_categories.py +++ b/scripts/make_unicode_categories.py @@ -77,8 +77,13 @@ def main(input_file, output_file): demiplane_to_idx = OrderedDict() # demiplane_idx → data_idx data_to_idx = [None] * 18 * 0x100 # demiplane data → data_idx print(" // A 'demiplane' is a 1/256th of a Unicode plane.", file=output_file) - print(" // This way a 'demiplane' fits nicely into a cache line.", file=output_file) - print(" alignas(64) static const std::uint8_t demiplane_data[][0x100 / 4] = {", file=output_file) + print( + " // This way a 'demiplane' fits nicely into a cache line.", file=output_file + ) + print( + " alignas(64) static const std::uint8_t demiplane_data[][0x100 / 4] = {", + file=output_file, + ) for i in range(18 * 0x100): plane_data = "" plane = planes[i] @@ -95,7 +100,10 @@ def main(input_file, output_file): produced_idx = demiplane_to_idx.get(plane_data) if produced_idx is None: produced_idx = len(demiplane_to_idx) - print(" {{ // {} -> 0x{:02x}u".format(i, produced_idx), file=output_file) + print( + " {{ // {} -> 0x{:02x}u".format(i, produced_idx), + file=output_file, + ) print(plane_data, file=output_file, end="") print(" },", file=output_file) demiplane_to_idx[plane_data] = produced_idx @@ -106,7 +114,10 @@ def main(input_file, output_file): snd_lookup_lines = OrderedDict() snd_lookup_indices = OrderedDict() - print(" alignas(64) static const std::uint8_t demiplane_snd_data[][64] = {", file=output_file) + print( + " alignas(64) static const std::uint8_t demiplane_snd_data[][64] = {", + file=output_file, + ) for start in range(0, 18 * 0x100, 64): snd_lookup_line: str for i in range(start, min(start + 64, 18 * 0x100)): @@ -116,11 +127,14 @@ def main(input_file, output_file): else: snd_lookup_line += "\n " snd_lookup_line += " 0x{:02x}u,".format(data_to_idx[i]) - + snd_lookup_idx = snd_lookup_lines.get(snd_lookup_line, None) if snd_lookup_idx is None: snd_lookup_idx = len(snd_lookup_lines) - print(" {{ // {} -> 0x{:02x}u".format(start // 64, snd_lookup_idx), file=output_file) + print( + " {{ // {} -> 0x{:02x}u".format(start // 64, snd_lookup_idx), + file=output_file, + ) print(snd_lookup_line, file=output_file) print(" },", file=output_file) snd_lookup_lines[snd_lookup_line] = snd_lookup_idx @@ -128,7 +142,13 @@ def main(input_file, output_file): print(" };", file=output_file) print(file=output_file) - print(" alignas(64) static const std::uint8_t demiplane_snd[18 * 0x100 / 64] = {{".format(68), end="", file=output_file) + print( + " alignas(64) static const std::uint8_t demiplane_snd[18 * 0x100 / 64] = {{".format( + 68 + ), + end="", + file=output_file, + ) for i in range(18 * 0x100 // 64): if i % 16 == 0: print("\n ", end="", file=output_file) @@ -138,7 +158,10 @@ def main(input_file, output_file): print(file=output_file) print(" if (JSON5EncoderCpp_expect(codepoint < 256, true)) {", file=output_file) - print(" return (demiplane_data[0][codepoint / 4] >> (2 * (codepoint % 4))) % 4;", file=output_file) + print( + " return (demiplane_data[0][codepoint / 4] >> (2 * (codepoint % 4))) % 4;", + file=output_file, + ) print(" }", file=output_file) print(file=output_file) print(" if (codepoint > 0x110000) codepoint = 0x110000;", file=output_file) @@ -147,8 +170,13 @@ def main(input_file, output_file): print(" std::uint32_t snd_row = fst_row / 64;", file=output_file) print(" std::uint32_t snd_col = fst_row % 64;", file=output_file) print(file=output_file) - print(" const std::uint8_t *cell = demiplane_data[demiplane_snd_data[demiplane_snd[snd_row]][snd_col]];", file=output_file) - print(" return (cell[fst_col / 4] >> (2 * (fst_col % 4))) % 4;", file=output_file) + print( + " const std::uint8_t *cell = demiplane_data[demiplane_snd_data[demiplane_snd[snd_row]][snd_col]];", + file=output_file, + ) + print( + " return (cell[fst_col / 4] >> (2 * (fst_col % 4))) % 4;", file=output_file + ) print("}", file=output_file) print(file=output_file) print("}", file=output_file) diff --git a/scripts/run-minefield-test.py b/scripts/run-minefield-test.py index f631b61..5238af9 100755 --- a/scripts/run-minefield-test.py +++ b/scripts/run-minefield-test.py @@ -2,14 +2,11 @@ from argparse import ArgumentParser from logging import basicConfig, INFO, getLogger -from os import name +from os import chdir, name from pathlib import Path from subprocess import Popen from sys import executable -from colorama import init, Fore -from pyjson5 import decode_io - argparser = ArgumentParser(description="Run JSON5 parser tests") argparser.add_argument( @@ -28,21 +25,32 @@ if __name__ == "__main__": basicConfig(level=INFO) logger = getLogger(__name__) - - init() + chdir(Path(__file__).absolute().parent.parent) good = bad = errors = severe = 0 - if name != "nt": - code_severe = Fore.RED + "😱" - code_good = Fore.CYAN + "😄" - code_bad = Fore.YELLOW + "😠" - code_ignored = Fore.BLUE + "🙅" + try: + from colorama import init, Fore + + init() + except Exception: + code_severe = "SEVERE" + code_good = "GOOD" + code_bad = "BAD" + code_ignored = "IGNORED" + reset = "" else: - code_severe = Fore.RED + "SEVERE" - code_good = Fore.CYAN + "GOOD" - code_bad = Fore.YELLOW + "BAD" - code_ignored = Fore.BLUE + "IGNORED" + if name != "nt": + code_severe = Fore.RED + "😱" + code_good = Fore.CYAN + "😄" + code_bad = Fore.YELLOW + "😠" + code_ignored = Fore.BLUE + "🙅" + else: + code_severe = Fore.RED + "SEVERE" + code_good = Fore.CYAN + "GOOD" + code_bad = Fore.YELLOW + "BAD" + code_ignored = Fore.BLUE + "IGNORED" + reset = Fore.RESET script = str(Path(__file__).absolute().parent / "transcode-to-json.py") @@ -98,7 +106,7 @@ "> | " "Actual <", "pass" if outcome == 0 else "FAIL", ">", - Fore.RESET, + reset, sep="", ) @@ -115,7 +123,7 @@ " wrong outcomes | ", severe, " severe errors", - Fore.RESET, + reset, sep="", ) raise SystemExit(2 if is_severe else 0 if is_good else 1) diff --git a/scripts/run-tests.py b/scripts/run-tests.py index 372d19b..c62fdcf 100755 --- a/scripts/run-tests.py +++ b/scripts/run-tests.py @@ -2,13 +2,11 @@ from argparse import ArgumentParser from logging import basicConfig, INFO, getLogger -from os import name +from os import chdir, name from pathlib import Path from subprocess import Popen from sys import executable -from colorama import init, Fore - argparser = ArgumentParser(description="Run JSON5 parser tests") argparser.add_argument( @@ -24,17 +22,27 @@ if __name__ == "__main__": basicConfig(level=INFO) logger = getLogger(__name__) + chdir(Path(__file__).absolute().parent.parent) - init() + try: + from colorama import init, Fore - if name != "nt": - code_severe = Fore.RED + "😱" - code_good = Fore.CYAN + "😄" - code_bad = Fore.YELLOW + "😠" + init() + except Exception: + code_severe = "SEVERE" + code_good = "GOOD" + code_bad = "BAD" + reset = "" else: - code_severe = Fore.RED + "SEVERE" - code_good = Fore.CYAN + "GOOD" - code_bad = Fore.YELLOW + "BAD" + if name != "nt": + code_severe = Fore.RED + "😱" + code_good = Fore.CYAN + "😄" + code_bad = Fore.YELLOW + "😠" + else: + code_severe = Fore.RED + "SEVERE" + code_good = Fore.CYAN + "GOOD" + code_bad = Fore.YELLOW + "BAD" + reset = Fore.RESET good = 0 bad = 0 @@ -82,7 +90,7 @@ "> | " "Actual <", "pass" if is_success else "FAIL", ">", - Fore.RESET, + reset, sep="", ) if is_severe: @@ -105,7 +113,7 @@ " × wrong outcome | ", severe, " × severe errors", - Fore.RESET, + reset, sep="", ) raise SystemExit(2 if is_severe else 0 if is_good else 1)