From ec3e9278fba07c98e470b0ea273f5b3dcd5ff4aa Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 5 Jan 2024 08:25:04 -0500 Subject: [PATCH] prep --- .coveragerc | 3 +- .flake8 | 8 +- .github/workflows/benchmarks.yml | 4 +- .github/workflows/test-single.yml | 4 +- .github/workflows/test.yml | 8 +- .github/workflows/upload-pypi-source.yml | 6 +- .pre-commit-config.yaml | 4 +- CONTRIBUTING.md | 2 +- benchmarks/blockchains.py | 2 +- benchmarks/jsonify.py | 2 +- .../puzzles/deployed_puzzle_hashes.json | 2 + move-tests.sh | 7 + mypy-exclusions.txt | 148 +++++++++--------- mypy.ini.template | 2 +- pytest.ini | 2 +- tests/__init__.py | 4 + tests/build-init-files.py | 4 +- tests/build-job-matrix.py | 17 +- tests/core/util/test_keychain.py | 2 +- tests/generator/test_compression.py | 6 +- tests/util/test_build_job_matrix.py | 4 +- 21 files changed, 131 insertions(+), 110 deletions(-) create mode 100755 move-tests.sh diff --git a/.coveragerc b/.coveragerc index 444d45e91a26..ec4426c53cc4 100644 --- a/.coveragerc +++ b/.coveragerc @@ -5,9 +5,8 @@ disable_warnings= relative_files=True source_pkgs= chia - tests omit= - tests/**/config.py + chia/_tests/**/config.py concurrency=multiprocessing, thread parallel=True diff --git a/.flake8 b/.flake8 index 9c5194b95620..bbc9be13234e 100644 --- a/.flake8 +++ b/.flake8 @@ -3,7 +3,7 @@ max-line-length = 120 exclude = ./typings/**/* ignore = E203,W503 per-file-ignores = - tests/util/build_network_protocol_files.py:F405 - tests/util/test_network_protocol_files.py:F405 - tests/util/test_network_protocol_json.py:F405 - tests/util/protocol_messages_json.py:E501 + chia/_tests/util/build_network_protocol_files.py:F405 + chia/_tests/util/test_network_protocol_files.py:F405 + chia/_tests/util/test_network_protocol_json.py:F405 + chia/_tests/util/protocol_messages_json.py:E501 diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index eeaf00a2d5a2..9f1b163c89d3 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -106,7 +106,7 @@ jobs: - name: pytest run: | - pytest -n 0 --capture no -m benchmark -o 'junit_suite_name=benchmarks' --junitxml=junit-data/benchmarks.raw.xml --benchmark-repeats ${{ needs.setup.outputs.repeats }} tests + pytest -n 0 --capture no -m benchmark -o 'junit_suite_name=benchmarks' --junitxml=junit-data/benchmarks.raw.xml --benchmark-repeats ${{ needs.setup.outputs.repeats }} chia/_tests/ - name: Format JUnit data and prepare results if: always() @@ -124,4 +124,4 @@ jobs: - name: Add benchmark results to workflow summary if: always() run: | - python -m tests.process_benchmarks --xml junit-data/benchmarks.xml --markdown --link-prefix ${{ github.event.repository.html_url }}/blob/${{ github.sha }}/ --link-line-separator \#L >> "$GITHUB_STEP_SUMMARY" + python -m chia._tests.process_benchmarks --xml junit-data/benchmarks.xml --markdown --link-prefix ${{ github.event.repository.html_url }}/blob/${{ github.sha }}/ --link-line-separator \#L >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/test-single.yml b/.github/workflows/test-single.yml index 56a91b988c25..32eaa43b4b2f 100644 --- a/.github/workflows/test-single.yml +++ b/.github/workflows/test-single.yml @@ -221,7 +221,7 @@ jobs: env: ENABLE_PYTEST_MONITOR: ${{ matrix.os.matrix == 'ubuntu' && matrix.configuration.enable_pytest_monitor || '' }} run: | - pytest --cov=chia --cov=tests --cov-config=.coveragerc --cov-report= -o 'junit_suite_name=${{ env.JOB_FILE_NAME }}' --junitxml=junit-data/junit.${{ env.JOB_FILE_NAME }}.xml --durations=10 ${{ matrix.configuration.pytest_parallel_args[matrix.os.matrix] }} -m "not benchmark" ${{ env.ENABLE_PYTEST_MONITOR }} ${{ matrix.configuration.test_files }} + pytest --cov=chia --cov-config=.coveragerc --cov-report= -o 'junit_suite_name=${{ env.JOB_FILE_NAME }}' --junitxml=junit-data/junit.${{ env.JOB_FILE_NAME }}.xml --durations=10 ${{ matrix.configuration.pytest_parallel_args[matrix.os.matrix] }} -m "not benchmark" ${{ env.ENABLE_PYTEST_MONITOR }} ${{ matrix.configuration.test_files }} - name: Move back to chia/ for coverage run: | @@ -253,4 +253,4 @@ jobs: if: matrix.os.matrix == 'ubuntu' && matrix.configuration.check_resource_usage run: | sqlite3 -readonly -separator " " .pymon "select item,cpu_usage,total_time,mem_usage from TEST_METRICS order by mem_usage desc;" >metrics.out - ./tests/check_pytest_monitor_output.py matrix.json + python chia/_tests/build-job-matrix.py --per directory --verbose > matrix.json cat matrix.json echo configuration=$(cat matrix.json) >> "$GITHUB_OUTPUT" echo matrix_mode=${{ ( github.event_name == 'schedule' ) && 'all' || ( github.event_name == 'workflow_dispatch' ) && 'all' || ( github.repository_owner == 'Chia-Network' && github.repository != 'Chia-Network/chia-blockchain' ) && 'limited' || ( github.repository_owner == 'Chia-Network' && github.repository == 'Chia-Network/chia-blockchain' && github.ref == 'refs/heads/main' ) && 'main' || ( github.repository_owner == 'Chia-Network' && github.repository == 'Chia-Network/chia-blockchain' && startsWith(github.ref, 'refs/heads/release/') ) && 'all' || ( github.repository_owner == 'Chia-Network' && github.repository == 'Chia-Network/chia-blockchain' && startsWith(github.base_ref, 'release/') ) && 'all' || 'main' }} >> "$GITHUB_OUTPUT" @@ -184,13 +184,13 @@ jobs: if: always() run: | set -o pipefail - coverage report --rcfile=.coveragerc --data-file=coverage-reports/.coverage --include='chia/**/*' --show-missing | tee coverage-reports/coverage-chia-stdout + coverage report --rcfile=.coveragerc --data-file=coverage-reports/.coverage --include='chia/**/*' --omit='chia/_tests/**/*' --show-missing | tee coverage-reports/coverage-chia-stdout - - name: Coverage report (tests/) + - name: Coverage report (chia/_tests/) if: always() run: | set -o pipefail - coverage report --rcfile=.coveragerc --data-file=coverage-reports/.coverage --include='tests/**/*' --show-missing | tee coverage-reports/coverage-tests-stdout + coverage report --rcfile=.coveragerc --data-file=coverage-reports/.coverage --include='chia/_tests/**/*' --show-missing | tee coverage-reports/coverage-tests-stdout - name: Coverage report (diff) if: (github.base_ref != '' || github.event.before != '') && always() diff --git a/.github/workflows/upload-pypi-source.yml b/.github/workflows/upload-pypi-source.yml index 960c2cbc4893..b6f1e0d4bc6a 100644 --- a/.github/workflows/upload-pypi-source.yml +++ b/.github/workflows/upload-pypi-source.yml @@ -128,12 +128,12 @@ jobs: - name: black command: black --check --diff . - name: flake8 - command: flake8 benchmarks build_scripts chia tests tools *.py + command: flake8 benchmarks build_scripts chia tools *.py - name: pylint - command: pylint benchmarks build_scripts chia tests tools *.py + command: pylint benchmarks build_scripts chia tools *.py - name: generated protocol tests command: | - python3 -m tests.util.build_network_protocol_files + python3 -m chia._tests.util.build_network_protocol_files git diff --exit-code steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3820f3d6e5ec..545a20457d89 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,14 +3,14 @@ repos: hooks: - id: check-sql name: Validate SQL statements - entry: ./activated.py python -m tests.check_sql_statements + entry: ./activated.py python -m chia._tests.check_sql_statements language: system pass_filenames: false - repo: local hooks: - id: init_py_files name: __init__.py files - entry: ./activated.py python tests/build-init-files.py -v --root . + entry: ./activated.py python chia/_tests/build-init-files.py -v --root . language: system pass_filenames: false - repo: local diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b565402327d0..5d6e871094f3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,7 +87,7 @@ provided configuration with `pre-commit install`. 4. Preferences > Settings > Python > Linting > flake8 enabled 5. Preferences > Settings > Python > Linting > mypy enabled 6. Preferences > Settings > Formatting > Python > Provider > black -7. Preferences > Settings > mypy > Targets: set to `./chia` and `./tests` +7. Preferences > Settings > mypy > Targets: set to `./chia` ## Configure Pycharm diff --git a/benchmarks/blockchains.py b/benchmarks/blockchains.py index 162399533eb1..6430d25b5077 100644 --- a/benchmarks/blockchains.py +++ b/benchmarks/blockchains.py @@ -7,10 +7,10 @@ from subprocess import check_call from typing import Iterator +from chia._tests.util.blockchain import persistent_blocks from chia.simulator.block_tools import create_block_tools_async, test_constants from chia.simulator.keyring import TempKeyring from chia.util.keyring_wrapper import KeyringWrapper -from tests.util.blockchain import persistent_blocks @contextmanager diff --git a/benchmarks/jsonify.py b/benchmarks/jsonify.py index a96244777e6e..5444e7fa42c9 100644 --- a/benchmarks/jsonify.py +++ b/benchmarks/jsonify.py @@ -3,7 +3,7 @@ import random from time import perf_counter -from tests.util.test_full_block_utils import get_full_blocks +from chia._tests.util.test_full_block_utils import get_full_blocks random.seed(123456789) diff --git a/chia/wallet/puzzles/deployed_puzzle_hashes.json b/chia/wallet/puzzles/deployed_puzzle_hashes.json index 332222e8d618..ff0ac1e8c67d 100644 --- a/chia/wallet/puzzles/deployed_puzzle_hashes.json +++ b/chia/wallet/puzzles/deployed_puzzle_hashes.json @@ -61,5 +61,7 @@ "singleton_top_layer_v1_1": "7faa3253bfddd1e0decb0906b2dc6247bbc4cf608f58345d173adb63e8b47c9f", "standard_vc_backdoor_puzzle": "fbce76408ebaf9b3d0b8cd90cc68607755eeca67cd7432d5eea85f3f498cc002", "std_parent_morpher": "8c3f1dc2e46c0d7ec4c2cbd007e23c0368ff8f80c5bc0101647a5c27626ebce6", + "test_generator_deserialize": "52add794fc76e89512e4a063c383418bda084c8a78c74055abe80179e4a7832c", + "test_multiple_generator_input_arguments": "156dafbddc3e1d3bfe1f2a84e48e5e46b287b8358bf65c3c091c93e855fbfc5b", "viral_backdoor": "00848115554ea674131f89f311707a959ad3f4647482648f3fe91ba289131f51" } diff --git a/move-tests.sh b/move-tests.sh new file mode 100755 index 000000000000..d849528817d5 --- /dev/null +++ b/move-tests.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -vx + +git mv tests/ chia/_tests/ +find chia/_tests/ benchmarks/ -name '*.py' -exec sed -i -E 's/(from|import) tests/\1 chia._tests/' {} \; +python tools/manage_clvm.py build diff --git a/mypy-exclusions.txt b/mypy-exclusions.txt index 6ae12d616962..0a847b204ea2 100644 --- a/mypy-exclusions.txt +++ b/mypy-exclusions.txt @@ -47,80 +47,80 @@ chia.wallet.wallet_puzzle_store chia.wallet.wallet_transaction_store chia.wallet.wallet_user_store installhelper -tests.blockchain.blockchain_test_utils -tests.blockchain.test_blockchain -tests.build-init-files -tests.clvm.coin_store -tests.clvm.test_chialisp_deserialization -tests.clvm.test_program -tests.clvm.test_puzzle_compression -tests.clvm.test_puzzles -tests.clvm.test_singletons -tests.clvm.test_spend_sim -tests.conftest -tests.connection_utils -tests.core.cmds.test_keys -tests.core.consensus.test_pot_iterations -tests.core.custom_types.test_coin -tests.core.custom_types.test_spend_bundle -tests.core.daemon.test_daemon -tests.core.full_node.full_sync.test_full_sync -tests.core.full_node.stores.test_sync_store -tests.core.full_node.test_address_manager -tests.core.full_node.test_full_node -tests.core.full_node.test_node_load -tests.core.full_node.test_peer_store_resolver -tests.core.full_node.test_performance -tests.core.full_node.test_transactions -tests.core.mempool.test_mempool -tests.core.server.test_dos -tests.core.server.test_rate_limits -tests.core.ssl.test_ssl -tests.core.test_crawler_rpc -tests.core.test_daemon_rpc -tests.core.test_db_conversion -tests.core.test_filter -tests.core.test_full_node_rpc -tests.core.test_merkle_set -tests.core.util.test_cached_bls -tests.core.util.test_config -tests.core.util.test_file_keyring_synchronization -tests.core.util.test_files -tests.core.util.test_keychain -tests.core.util.test_keyring_wrapper -tests.core.util.test_lru_cache -tests.core.util.test_significant_bits -tests.generator.test_scan -tests.plotting.test_plot_manager -tests.pools.test_pool_cmdline -tests.pools.test_pool_config -tests.pools.test_pool_puzzles_lifecycle -tests.pools.test_wallet_pool_store -tests.simulation.test_simulation -tests.tools.test_run_block -tests.util.benchmark_cost -tests.util.generator_tools_testing -tests.util.test_full_block_utils -tests.util.test_misc -tests.util.test_network -tests.util.time_out_assert -tests.wallet.cat_wallet.test_cat_wallet -tests.wallet.cat_wallet.test_trades -tests.wallet.did_wallet.test_did -tests.wallet.rpc.test_wallet_rpc -tests.wallet.simple_sync.test_simple_sync_protocol -tests.wallet.sync.test_wallet_sync -tests.wallet.test_bech32m -tests.wallet.test_chialisp -tests.wallet.test_puzzle_store -tests.wallet.test_singleton -tests.wallet.test_singleton_lifecycle -tests.wallet.test_singleton_lifecycle_fast -tests.wallet.test_taproot -tests.wallet.test_wallet_blockchain -tests.wallet.test_wallet_interested_store -tests.wallet.test_wallet_key_val_store -tests.wallet.test_wallet_user_store +chia._tests.blockchain.blockchain_test_utils +chia._tests.blockchain.test_blockchain +chia._tests.build-init-files +chia._tests.clvm.coin_store +chia._tests.clvm.test_chialisp_deserialization +chia._tests.clvm.test_program +chia._tests.clvm.test_puzzle_compression +chia._tests.clvm.test_puzzles +chia._tests.clvm.test_singletons +chia._tests.clvm.test_spend_sim +chia._tests.conftest +chia._tests.connection_utils +chia._tests.core.cmds.test_keys +chia._tests.core.consensus.test_pot_iterations +chia._tests.core.custom_types.test_coin +chia._tests.core.custom_types.test_spend_bundle +chia._tests.core.daemon.test_daemon +chia._tests.core.full_node.full_sync.test_full_sync +chia._tests.core.full_node.stores.test_sync_store +chia._tests.core.full_node.test_address_manager +chia._tests.core.full_node.test_full_node +chia._tests.core.full_node.test_node_load +chia._tests.core.full_node.test_peer_store_resolver +chia._tests.core.full_node.test_performance +chia._tests.core.full_node.test_transactions +chia._tests.core.mempool.test_mempool +chia._tests.core.server.test_dos +chia._tests.core.server.test_rate_limits +chia._tests.core.ssl.test_ssl +chia._tests.core.test_crawler_rpc +chia._tests.core.test_daemon_rpc +chia._tests.core.test_db_conversion +chia._tests.core.test_filter +chia._tests.core.test_full_node_rpc +chia._tests.core.test_merkle_set +chia._tests.core.util.test_cached_bls +chia._tests.core.util.test_config +chia._tests.core.util.test_file_keyring_synchronization +chia._tests.core.util.test_files +chia._tests.core.util.test_keychain +chia._tests.core.util.test_keyring_wrapper +chia._tests.core.util.test_lru_cache +chia._tests.core.util.test_significant_bits +chia._tests.generator.test_scan +chia._tests.plotting.test_plot_manager +chia._tests.pools.test_pool_cmdline +chia._tests.pools.test_pool_config +chia._tests.pools.test_pool_puzzles_lifecycle +chia._tests.pools.test_wallet_pool_store +chia._tests.simulation.test_simulation +chia._tests.tools.test_run_block +chia._tests.util.benchmark_cost +chia._tests.util.generator_tools_testing +chia._tests.util.test_full_block_utils +chia._tests.util.test_misc +chia._tests.util.test_network +chia._tests.util.time_out_assert +chia._tests.wallet.cat_wallet.test_cat_wallet +chia._tests.wallet.cat_wallet.test_trades +chia._tests.wallet.did_wallet.test_did +chia._tests.wallet.rpc.test_wallet_rpc +chia._tests.wallet.simple_sync.test_simple_sync_protocol +chia._tests.wallet.sync.test_wallet_sync +chia._tests.wallet.test_bech32m +chia._tests.wallet.test_chialisp +chia._tests.wallet.test_puzzle_store +chia._tests.wallet.test_singleton +chia._tests.wallet.test_singleton_lifecycle +chia._tests.wallet.test_singleton_lifecycle_fast +chia._tests.wallet.test_taproot +chia._tests.wallet.test_wallet_blockchain +chia._tests.wallet.test_wallet_interested_store +chia._tests.wallet.test_wallet_key_val_store +chia._tests.wallet.test_wallet_user_store tools.analyze-chain tools.run_block tools.test_full_sync diff --git a/mypy.ini.template b/mypy.ini.template index 69f04397cc6c..e0c9afa7d7c3 100644 --- a/mypy.ini.template +++ b/mypy.ini.template @@ -1,5 +1,5 @@ [mypy] -files = benchmarks,build_scripts,chia,tests,tools,*.py +files = benchmarks,build_scripts,chia,tools,*.py ignore_missing_imports = True show_error_codes = True warn_unused_ignores = True diff --git a/pytest.ini b/pytest.ini index 1ba22675f7f0..e33bd536c400 100644 --- a/pytest.ini +++ b/pytest.ini @@ -12,7 +12,7 @@ markers = test_mark_a2: used in testing test utilities test_mark_b1: used in testing test utilities test_mark_b2: used in testing test utilities -testpaths = tests +testpaths = chia/_tests/ filterwarnings = error ignore:JSON contains both `coin_solutions` and `coin_spends`, just use `coin_spends` diff --git a/tests/__init__.py b/tests/__init__.py index e69de29bb2d1..efd7e43136e3 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,4 @@ +import multiprocessing + +# TODO: better isolate these contexts, is this just for 'that monitoring plugin'? +multiprocessing.set_start_method("spawn") diff --git a/tests/build-init-files.py b/tests/build-init-files.py index 27b93a5397a9..19bc08bc3103 100755 --- a/tests/build-init-files.py +++ b/tests/build-init-files.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# Create missing `__init__.py` files in the source code folders (in "chia/" and "tests/"). +# Create missing `__init__.py` files in the source code folders (in "chia/"). # # They are required by the python interpreter to properly identify modules/packages so that tools like `mypy` or an IDE # can work with their full capabilities. @@ -64,7 +64,7 @@ def command(verbose, root_str): stream_handler = logging.StreamHandler() logger.addHandler(stream_handler) - tree_roots = ["benchmarks", "build_scripts", "chia", "tests", "tools"] + tree_roots = ["benchmarks", "build_scripts", "chia", "tools"] failed = False root = pathlib.Path(root_str).resolve() directories = [ diff --git a/tests/build-job-matrix.py b/tests/build-job-matrix.py index 4bc526359600..55d24ffd24b0 100644 --- a/tests/build-job-matrix.py +++ b/tests/build-job-matrix.py @@ -11,11 +11,11 @@ import testconfig root_path = Path(__file__).parent.absolute() -project_root_path = root_path.parent +project_root_path = root_path.parent.parent def skip(path: Path) -> bool: - return any(part.startswith(("_", ".")) for part in path.parts) + return any(part.startswith(("_", ".")) and part != "_tests" for part in path.parts) def subdirs(per: str) -> List[Path]: @@ -113,13 +113,20 @@ def update_config(parent: Dict[str, Any], child: Dict[str, Any]) -> Dict[str, An for path in test_paths: if path.is_dir(): test_files = sorted(path.glob("test_*.py")) - test_file_paths = [file.relative_to(project_root_path) for file in test_files] - paths_for_cli = " ".join(path.as_posix() for path in test_file_paths) + paths_for_cli_list = [file.relative_to(project_root_path) for file in test_files] config_path = path else: - paths_for_cli = path.relative_to(project_root_path).as_posix() + paths_for_cli_list = [path.relative_to(project_root_path)] config_path = path.parent + def mung_path(path: Path) -> str: + parts = list(path.parts) + parts[0] = "notchia" + # TODO: shell escaping, but that's per platform... + return Path(*parts).as_posix() + + paths_for_cli = " ".join(mung_path(path) for path in paths_for_cli_list) + try: conf = update_config(module_dict(testconfig), dir_config(config_path)) except SpecifiedDefaultsError as e: diff --git a/tests/core/util/test_keychain.py b/tests/core/util/test_keychain.py index 226cf05c69a3..87142cc0451b 100644 --- a/tests/core/util/test_keychain.py +++ b/tests/core/util/test_keychain.py @@ -172,7 +172,7 @@ def test_bip39_test_vectors_short(self): """ Tests that the first 4 letters of each mnemonic phrase matches as if it were the full phrase """ - test_vectors_path = pathlib.Path(tests.__file__).parent.joinpath("util", "bip39_test_vectors.json") + test_vectors_path = pathlib.Path(chia._tests.__file__).parent.joinpath("util", "bip39_test_vectors.json") with open(test_vectors_path) as f: all_vectors = json.load(f) diff --git a/tests/generator/test_compression.py b/tests/generator/test_compression.py index f69115c92cee..9c798e269151 100644 --- a/tests/generator/test_compression.py +++ b/tests/generator/test_compression.py @@ -31,7 +31,9 @@ from tests.core.make_block_generator import make_spend_bundle from tests.generator.test_rom import run_generator -TEST_GEN_DESERIALIZE = load_clvm("test_generator_deserialize.clsp", package_or_requirement="tests.generator.puzzles") +TEST_GEN_DESERIALIZE = load_clvm( + "test_generator_deserialize.clsp", package_or_requirement="chia._tests.generator.puzzles" +) DESERIALIZE_MOD = load_clvm("chialisp_deserialisation.clsp", package_or_requirement="chia.consensus.puzzles") DECOMPRESS_PUZZLE = load_clvm("decompress_puzzle.clsp", package_or_requirement="chia.full_node.puzzles") @@ -42,7 +44,7 @@ ) DECOMPRESS_BLOCK = load_clvm("block_program_zero.clsp", package_or_requirement="chia.full_node.puzzles") TEST_MULTIPLE = load_clvm( - "test_multiple_generator_input_arguments.clsp", package_or_requirement="tests.generator.puzzles" + "test_multiple_generator_input_arguments.clsp", package_or_requirement="chia._tests.generator.puzzles" ) Nil = Program.from_bytes(b"\x80") diff --git a/tests/util/test_build_job_matrix.py b/tests/util/test_build_job_matrix.py index f90edb982275..cc2e14d43f60 100644 --- a/tests/util/test_build_job_matrix.py +++ b/tests/util/test_build_job_matrix.py @@ -6,9 +6,9 @@ import sys from typing import Dict, List -import tests +import chia._tests -build_job_matrix_path = pathlib.Path(tests.__file__).with_name("build-job-matrix.py") +build_job_matrix_path = pathlib.Path(chia._tests.__file__).with_name("build-job-matrix.py") def run(args: List[str]) -> str: