diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 4d5688725..12608ad76 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -312,6 +312,136 @@ ] } }, + "@@aspect_rules_js+//npm:extensions.bzl%pnpm": { + "general": { + "bzlTransitiveDigest": "c1Q7VkLeafam8apaxHVrYHpOEETl0bYTUqiCLs3p7DE=", + "usagesDigest": "kbjSw2REjlSC0HtTZDf2p+l/dmiMt3NHLoiWEXYAoQI=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "pnpm": { + "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_rule", + "attributes": { + "package": "pnpm", + "version": "8.6.7", + "root_package": "", + "link_workspace": "", + "link_packages": {}, + "integrity": "sha512-vRIWpD/L4phf9Bk2o/O2TDR8fFoJnpYrp2TKqTIZF/qZ2/rgL3qKXzHofHgbXsinwMoSEigz28sqk3pQ+yMEQQ==", + "url": "", + "commit": "", + "patch_args": [ + "-p0" + ], + "patches": [], + "custom_postinstall": "", + "npm_auth": "", + "npm_auth_basic": "", + "npm_auth_username": "", + "npm_auth_password": "", + "lifecycle_hooks": [], + "extra_build_content": "load(\"@aspect_rules_js//js:defs.bzl\", \"js_binary\")\njs_binary(name = \"pnpm\", data = glob([\"package/**\"]), entry_point = \"package/dist/pnpm.cjs\", visibility = [\"//visibility:public\"])", + "generate_bzl_library_targets": false, + "extract_full_archive": true, + "exclude_package_contents": [], + "system_tar": "auto" + } + }, + "pnpm__links": { + "repoRuleId": "@@aspect_rules_js+//npm/private:npm_import.bzl%npm_import_links", + "attributes": { + "package": "pnpm", + "version": "8.6.7", + "dev": false, + "root_package": "", + "link_packages": {}, + "deps": {}, + "transitive_closure": {}, + "lifecycle_build_target": false, + "lifecycle_hooks_env": [], + "lifecycle_hooks_execution_requirements": [ + "no-sandbox" + ], + "lifecycle_hooks_use_default_shell_env": false, + "bins": {}, + "package_visibility": [ + "//visibility:public" + ], + "replace_package": "", + "exclude_package_contents": [] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "aspect_bazel_lib+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "aspect_bazel_lib+", + "bazel_tools", + "bazel_tools" + ], + [ + "aspect_bazel_lib+", + "tar.bzl", + "tar.bzl+" + ], + [ + "aspect_rules_js+", + "aspect_bazel_lib", + "aspect_bazel_lib+" + ], + [ + "aspect_rules_js+", + "aspect_rules_js", + "aspect_rules_js+" + ], + [ + "aspect_rules_js+", + "bazel_features", + "bazel_features+" + ], + [ + "aspect_rules_js+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "aspect_rules_js+", + "bazel_tools", + "bazel_tools" + ], + [ + "bazel_features+", + "bazel_features_globals", + "bazel_features++version_extension+bazel_features_globals" + ], + [ + "bazel_features+", + "bazel_features_version", + "bazel_features++version_extension+bazel_features_version" + ], + [ + "tar.bzl+", + "aspect_bazel_lib", + "aspect_bazel_lib+" + ], + [ + "tar.bzl+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "tar.bzl+", + "tar.bzl", + "tar.bzl+" + ] + ] + } + }, "@@aspect_rules_ts+//ts:extensions.bzl%ext": { "general": { "bzlTransitiveDigest": "aVqwKoRPrSXO367SJABlye04kmpR/9VM2xiXB3nh3Ls=", @@ -346,6 +476,57 @@ ] } }, + "@@bazel_bats+//:extensions.bzl%bazel_bats_deps": { + "general": { + "bzlTransitiveDigest": "dMxpmRKtIYzMONCZV8oDEdFhT7orcOnBrTyMoCa+ppA=", + "usagesDigest": "t+ex/oJhALiD6nk6VMpJT83/RVXO6TaIVwWMSo4V6sA=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "bats_core": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file_content": "\nsh_library(\n name = \"bats_lib\",\n srcs = glob([\"libexec/**\"]),\n)\n\nsh_binary(\n name = \"bats\",\n srcs = [\"bin/bats\"],\n visibility = [\"//visibility:public\"],\n deps = [\":bats_lib\"],\n)\n\nsh_library(\n name = \"file_setup_teardown_lib\",\n srcs = [\"test/file_setup_teardown.bats\"],\n visibility = [\"//visibility:public\"],\n data = glob([\"test/fixtures/file_setup_teardown/**\"]),\n)\n\nsh_library(\n name = \"junit_formatter_lib\",\n srcs = [\"test/junit-formatter.bats\"],\n visibility = [\"//visibility:public\"],\n data = glob([\"test/fixtures/junit-formatter/**\"]),\n)\n\nsh_library(\n name = \"parallel_lib\",\n srcs = [\"test/parallel.bats\"],\n visibility = [\"//visibility:public\"],\n data = glob([\n \"test/concurrent-coordination.bash\",\n \"test/fixtures/parallel/**\",\n ]),\n)\n\nsh_library(\n name = \"run_lib\",\n srcs = [\"test/run.bats\"],\n visibility = [\"//visibility:public\"],\n data = glob([\"test/fixtures/run/**\"]),\n)\n\nsh_library(\n name = \"suite_lib\",\n srcs = [\"test/suite.bats\"],\n visibility = [\"//visibility:public\"],\n data = glob([\"test/fixtures/suite/**\"]),\n)\n\nsh_library(\n name = \"test_helper\",\n srcs = [\"test/test_helper.bash\"],\n visibility = [\"//visibility:public\"],\n)\n\nsh_library(\n name = \"trace_lib\",\n srcs = [\"test/trace.bats\"],\n visibility = [\"//visibility:public\"],\n data = glob([\"test/fixtures/trace/**\"]),\n)\n\nexports_files(glob([\"test/*.bats\"]))\n", + "urls": [ + "https://github.com/bats-core/bats-core/archive/refs/tags/v1.7.0.tar.gz" + ], + "strip_prefix": "bats-core-1.7.0", + "sha256": "ac70c2a153f108b1ac549c2eaa4154dea4a7c1cc421e3352f0ce6ea49435454e" + } + }, + "bats_assert": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file_content": "\nfilegroup(\n name = \"load_files\",\n srcs = [\n \"load.bash\",\n ] + glob([\n \"src/**/*.bash\",\n ]),\n visibility = [\"//visibility:public\"],\n)\n", + "sha256": "15dbf1abb98db785323b9327c86ee2b3114541fe5aa150c410a1632ec06d9903", + "strip_prefix": "bats-assert-2.0.0", + "urls": [ + "https://github.com/bats-core/bats-assert/archive/refs/tags/v2.0.0.tar.gz" + ] + } + }, + "bats_support": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file_content": "\nfilegroup(\n name = \"load_files\",\n srcs = [\n \"load.bash\",\n ] + glob([\n \"src/**/*.bash\",\n ]),\n visibility = [\"//visibility:public\"],\n)\n", + "sha256": "7815237aafeb42ddcc1b8c698fc5808026d33317d8701d5ec2396e9634e2918f", + "strip_prefix": "bats-support-0.3.0", + "urls": [ + "https://github.com/bats-core/bats-support/archive/refs/tags/v0.3.0.tar.gz" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "bazel_bats+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, "@@buildifier_prebuilt+//:defs.bzl%buildifier_prebuilt_deps_extension": { "general": { "bzlTransitiveDigest": "u4exIm/Ie7MnBJpWnXNoPRCqYpyYnW2ns2kmg+V/3To=", @@ -501,6 +682,40 @@ "recordedRepoMappingEntries": [] } }, + "@@pybind11_bazel+//:python_configure.bzl%extension": { + "general": { + "bzlTransitiveDigest": "OMjJ8aOAn337bDg7jdyvF/juIrC2PpUcX6Dnf+nhcF0=", + "usagesDigest": "fycyB39YnXIJkfWCIXLUKJMZzANcuLy9ZE73hRucjFk=", + "recordedFileInputs": { + "@@pybind11_bazel+//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e" + }, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "local_config_python": { + "repoRuleId": "@@pybind11_bazel+//:python_configure.bzl%python_configure", + "attributes": {} + }, + "pybind11": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file": "@@pybind11_bazel+//:pybind11.BUILD", + "strip_prefix": "pybind11-2.11.1", + "urls": [ + "https://github.com/pybind/pybind11/archive/v2.11.1.zip" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "pybind11_bazel+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, "@@rules_android+//bzlmod_extensions:apksig.bzl%apksig_extension": { "general": { "bzlTransitiveDigest": "6NJSHjev77G4XUXqswn+uU8LwqBD5JUgxtcFMWhBJUQ=", @@ -923,6 +1138,89 @@ ] } }, + "@@rules_fuzzing+//fuzzing/private:extensions.bzl%non_module_dependencies": { + "general": { + "bzlTransitiveDigest": "lxvzPQyluk241QRYY81nZHOcv5Id/5U2y6dp42qibis=", + "usagesDigest": "wy6ISK6UOcBEjj/mvJ/S3WeXoO67X+1llb9yPyFtPgc=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "platforms": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "urls": [ + "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz", + "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz" + ], + "sha256": "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74" + } + }, + "rules_python": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8", + "strip_prefix": "rules_python-0.28.0", + "url": "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz" + } + }, + "bazel_skylib": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", + "urls": [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz" + ] + } + }, + "com_google_absl": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "urls": [ + "https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.1.zip" + ], + "strip_prefix": "abseil-cpp-20240116.1", + "integrity": "sha256-7capMWOvWyoYbUaHF/b+I2U6XLMaHmky8KugWvfXYuk=" + } + }, + "rules_fuzzing_oss_fuzz": { + "repoRuleId": "@@rules_fuzzing+//fuzzing/private/oss_fuzz:repository.bzl%oss_fuzz_repository", + "attributes": {} + }, + "honggfuzz": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "build_file": "@@rules_fuzzing+//:honggfuzz.BUILD", + "sha256": "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e", + "url": "https://github.com/google/honggfuzz/archive/2.5.zip", + "strip_prefix": "honggfuzz-2.5" + } + }, + "rules_fuzzing_jazzer": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar", + "attributes": { + "sha256": "ee6feb569d88962d59cb59e8a31eb9d007c82683f3ebc64955fd5b96f277eec2", + "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer/0.20.1/jazzer-0.20.1.jar" + } + }, + "rules_fuzzing_jazzer_api": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_jar", + "attributes": { + "sha256": "f5a60242bc408f7fa20fccf10d6c5c5ea1fcb3c6f44642fec5af88373ae7aa1b", + "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer-api/0.20.1/jazzer-api-0.20.1.jar" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_fuzzing+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { "bzlTransitiveDigest": "CgSFQ7VRhs6G8nojJKNB6szAhYnHEblrCU/AruTOxtw=", @@ -1150,6 +1448,2655 @@ "recordedRepoMappingEntries": [] } }, + "@@rules_python+//python/extensions:pip.bzl%pip": { + "general": { + "bzlTransitiveDigest": "+Axnk/K7KLa1phIMd8uP2eZjKDtvrIX/ipSZZnlu/Mg=", + "usagesDigest": "ngGqXeODRuOjHb6v0DsJ4oyFvV0nhcFNXcy7gVm7bEc=", + "recordedFileInputs": { + "@@protobuf+//python/requirements.txt": "983be60d3cec4b319dcab6d48aeb3f5b2f7c3350f26b3a9e97486c37967c73c5", + "@@rules_fuzzing+//fuzzing/requirements.txt": "ab04664be026b632a0d2a2446c4f65982b7654f5b6851d2f9d399a19b7242a5b", + "@@rules_python+//tools/publish/requirements_darwin.txt": "095d4a4f3d639dce831cd493367631cd51b53665292ab20194bac2c0c6458fa8", + "@@rules_python+//tools/publish/requirements_linux.txt": "d576e0d8542df61396a9b38deeaa183c24135ed5e8e73bb9622f298f2671811e", + "@@rules_python+//tools/publish/requirements_windows.txt": "d18538a3982beab378fd5687f4db33162ee1ece69801f9a451661b1b64286b76" + }, + "recordedDirentsInputs": {}, + "envVariables": { + "RULES_PYTHON_REPO_DEBUG": null, + "RULES_PYTHON_REPO_DEBUG_VERBOSITY": null + }, + "generatedRepoSpecs": { + "pip_deps_310_numpy": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python", + "repo": "pip_deps_310", + "requirement": "numpy<=1.26.1" + } + }, + "pip_deps_310_setuptools": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python", + "repo": "pip_deps_310", + "requirement": "setuptools<=70.3.0" + } + }, + "pip_deps_311_numpy": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "pip_deps_311", + "requirement": "numpy<=1.26.1" + } + }, + "pip_deps_311_setuptools": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "pip_deps_311", + "requirement": "setuptools<=70.3.0" + } + }, + "pip_deps_312_numpy": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python", + "repo": "pip_deps_312", + "requirement": "numpy<=1.26.1" + } + }, + "pip_deps_312_setuptools": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python", + "repo": "pip_deps_312", + "requirement": "setuptools<=70.3.0" + } + }, + "pip_deps_38_numpy": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python", + "repo": "pip_deps_38", + "requirement": "numpy<=1.26.1" + } + }, + "pip_deps_38_setuptools": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python", + "repo": "pip_deps_38", + "requirement": "setuptools<=70.3.0" + } + }, + "pip_deps_39_numpy": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python", + "repo": "pip_deps_39", + "requirement": "numpy<=1.26.1" + } + }, + "pip_deps_39_setuptools": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@pip_deps//{name}:{target}", + "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python", + "repo": "pip_deps_39", + "requirement": "setuptools<=70.3.0" + } + }, + "rules_fuzzing_py_deps_310_absl_py": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python", + "repo": "rules_fuzzing_py_deps_310", + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3" + } + }, + "rules_fuzzing_py_deps_310_six": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_10_host//:python", + "repo": "rules_fuzzing_py_deps_310", + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + } + }, + "rules_fuzzing_py_deps_311_absl_py": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_fuzzing_py_deps_311", + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3" + } + }, + "rules_fuzzing_py_deps_311_six": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_fuzzing_py_deps_311", + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + } + }, + "rules_fuzzing_py_deps_312_absl_py": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python", + "repo": "rules_fuzzing_py_deps_312", + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3" + } + }, + "rules_fuzzing_py_deps_312_six": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_12_host//:python", + "repo": "rules_fuzzing_py_deps_312", + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + } + }, + "rules_fuzzing_py_deps_38_absl_py": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python", + "repo": "rules_fuzzing_py_deps_38", + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3" + } + }, + "rules_fuzzing_py_deps_38_six": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_8_host//:python", + "repo": "rules_fuzzing_py_deps_38", + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + } + }, + "rules_fuzzing_py_deps_39_absl_py": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python", + "repo": "rules_fuzzing_py_deps_39", + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3" + } + }, + "rules_fuzzing_py_deps_39_six": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_fuzzing_py_deps//{name}:{target}", + "extra_pip_args": [ + "--require-hashes" + ], + "python_interpreter_target": "@@rules_python++python+python_3_9_host//:python", + "repo": "rules_fuzzing_py_deps_39", + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + } + }, + "rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "backports.tarfile-1.2.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "backports-tarfile==1.2.0", + "sha256": "77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", + "urls": [ + "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "backports_tarfile-1.2.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "backports-tarfile==1.2.0", + "sha256": "d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", + "urls": [ + "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_certifi_py3_none_any_922820b5": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "certifi-2024.8.30-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "certifi==2024.8.30", + "sha256": "922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8", + "urls": [ + "https://files.pythonhosted.org/packages/12/90/3c9ff0512038035f59d279fddeb79f5f1eccd8859f06d6163c58798b9487/certifi-2024.8.30-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_certifi_sdist_bec941d2": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "certifi-2024.8.30.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "certifi==2024.8.30", + "sha256": "bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9", + "urls": [ + "https://files.pythonhosted.org/packages/b0/ee/9b19140fe824b367c04c5e1b369942dd754c4c5462d5674002f75c4dedc1/certifi-2024.8.30.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", + "urls": [ + "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", + "urls": [ + "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", + "urls": [ + "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", + "urls": [ + "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", + "urls": [ + "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cffi_sdist_1c39c601": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "cffi-1.17.1.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cffi==1.17.1", + "sha256": "1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", + "urls": [ + "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c", + "urls": [ + "https://files.pythonhosted.org/packages/9c/61/73589dcc7a719582bf56aae309b6103d2762b526bffe189d635a7fcfd998/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944", + "urls": [ + "https://files.pythonhosted.org/packages/77/d5/8c982d58144de49f59571f940e329ad6e8615e1e82ef84584c5eeb5e1d72/charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee", + "urls": [ + "https://files.pythonhosted.org/packages/bf/19/411a64f01ee971bed3231111b69eb56f9331a769072de479eae7de52296d/charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c", + "urls": [ + "https://files.pythonhosted.org/packages/4c/92/97509850f0d00e9f14a46bc751daabd0ad7765cff29cdfb66c68b6dad57f/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea", + "urls": [ + "https://files.pythonhosted.org/packages/13/bc/87c2c9f2c144bedfa62f894c3007cd4530ba4b5351acb10dc786428a50f0/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc", + "urls": [ + "https://files.pythonhosted.org/packages/eb/5b/6f10bad0f6461fa272bfbbdf5d0023b5fb9bc6217c92bf068fa5a99820f5/charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594", + "urls": [ + "https://files.pythonhosted.org/packages/d7/a1/493919799446464ed0299c8eef3c3fad0daf1c3cd48bff9263c731b0d9e2/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129", + "urls": [ + "https://files.pythonhosted.org/packages/8d/c9/27e41d481557be53d51e60750b85aa40eaf52b841946b3cdeff363105737/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236", + "urls": [ + "https://files.pythonhosted.org/packages/ee/44/4f62042ca8cdc0cabf87c0fc00ae27cd8b53ab68be3605ba6d071f742ad3/charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27", + "urls": [ + "https://files.pythonhosted.org/packages/0b/6e/b13bd47fa9023b3699e94abf565b5a2f0b0be6e9ddac9812182596ee62e4/charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "charset_normalizer-3.4.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079", + "urls": [ + "https://files.pythonhosted.org/packages/bf/9b/08c0432272d77b04803958a4598a51e2a4b51c06640af8b8f0f908c18bf2/charset_normalizer-3.4.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_charset_normalizer_sdist_223217c3": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "charset_normalizer-3.4.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "charset-normalizer==3.4.0", + "sha256": "223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e", + "urls": [ + "https://files.pythonhosted.org/packages/f2/4f/e1808dc01273379acc506d18f1504eb2d299bd4131743b9fc54d7be4df1e/charset_normalizer-3.4.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5", + "urls": [ + "https://files.pythonhosted.org/packages/2f/78/55356eb9075d0be6e81b59f45c7b48df87f76a20e73893872170471f3ee8/cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4", + "urls": [ + "https://files.pythonhosted.org/packages/2a/2c/488776a3dc843f95f86d2f957ca0fc3407d0242b50bede7fad1e339be03f/cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7", + "urls": [ + "https://files.pythonhosted.org/packages/7c/04/2345ca92f7a22f601a9c62961741ef7dd0127c39f7310dffa0041c80f16f/cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405", + "urls": [ + "https://files.pythonhosted.org/packages/ac/25/e715fa0bc24ac2114ed69da33adf451a38abb6f3f24ec207908112e9ba53/cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16", + "urls": [ + "https://files.pythonhosted.org/packages/21/ce/b9c9ff56c7164d8e2edfb6c9305045fbc0df4508ccfdb13ee66eb8c95b0e/cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73", + "urls": [ + "https://files.pythonhosted.org/packages/2a/33/b3682992ab2e9476b9c81fff22f02c8b0a1e6e1d49ee1750a67d85fd7ed2/cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_cryptography_sdist_315b9001": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "cryptography-43.0.3.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "cryptography==43.0.3", + "sha256": "315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805", + "urls": [ + "https://files.pythonhosted.org/packages/0d/05/07b55d1fa21ac18c3a8c79f764e2514e6f6a9698f1be44994f5adf0d29db/cryptography-43.0.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "docutils-0.21.2-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "docutils==0.21.2", + "sha256": "dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", + "urls": [ + "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_docutils_sdist_3a6b1873": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "docutils-0.21.2.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "docutils==0.21.2", + "sha256": "3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", + "urls": [ + "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_idna_py3_none_any_946d195a": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "idna-3.10-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "idna==3.10", + "sha256": "946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", + "urls": [ + "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_idna_sdist_12f65c9b": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "idna-3.10.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "idna==3.10", + "sha256": "12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", + "urls": [ + "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "importlib_metadata-8.5.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "importlib-metadata==8.5.0", + "sha256": "45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", + "urls": [ + "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_importlib_metadata_sdist_71522656": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "importlib_metadata-8.5.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "importlib-metadata==8.5.0", + "sha256": "71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", + "urls": [ + "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "jaraco.classes-3.4.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-classes==3.4.0", + "sha256": "f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", + "urls": [ + "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jaraco.classes-3.4.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-classes==3.4.0", + "sha256": "47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", + "urls": [ + "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "jaraco.context-6.0.1-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-context==6.0.1", + "sha256": "f797fc481b490edb305122c9181830a3a5b76d84ef6d1aef2fb9b47ab956f9e4", + "urls": [ + "https://files.pythonhosted.org/packages/ff/db/0c52c4cf5e4bd9f5d7135ec7669a3a767af21b3a308e1ed3674881e52b62/jaraco.context-6.0.1-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jaraco_context-6.0.1.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-context==6.0.1", + "sha256": "9bae4ea555cf0b14938dc0aee7c9f32ed303aa20a3b73e7dc80111628792d1b3", + "urls": [ + "https://files.pythonhosted.org/packages/df/ad/f3777b81bf0b6e7bc7514a1656d3e637b2e8e15fab2ce3235730b3e7a4e6/jaraco_context-6.0.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "jaraco.functools-4.1.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-functools==4.1.0", + "sha256": "ad159f13428bc4acbf5541ad6dec511f91573b90fba04df61dafa2a1231cf649", + "urls": [ + "https://files.pythonhosted.org/packages/9f/4f/24b319316142c44283d7540e76c7b5a6dbd5db623abd86bb7b3491c21018/jaraco.functools-4.1.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jaraco_functools-4.1.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jaraco-functools==4.1.0", + "sha256": "70f7e0e2ae076498e212562325e805204fc092d7b4c17e0e86c959e249701a9d", + "urls": [ + "https://files.pythonhosted.org/packages/ab/23/9894b3df5d0a6eb44611c36aec777823fc2e07740dabbd0b810e19594013/jaraco_functools-4.1.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "jeepney-0.8.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jeepney==0.8.0", + "sha256": "c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755", + "urls": [ + "https://files.pythonhosted.org/packages/ae/72/2a1e2290f1ab1e06f71f3d0f1646c9e4634e70e1d37491535e19266e8dc9/jeepney-0.8.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_jeepney_sdist_5efe48d2": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "jeepney-0.8.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "jeepney==0.8.0", + "sha256": "5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806", + "urls": [ + "https://files.pythonhosted.org/packages/d6/f4/154cf374c2daf2020e05c3c6a03c91348d59b23c5366e968feb198306fdf/jeepney-0.8.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_keyring_py3_none_any_5426f817": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "keyring-25.4.1-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "keyring==25.4.1", + "sha256": "5426f817cf7f6f007ba5ec722b1bcad95a75b27d780343772ad76b17cb47b0bf", + "urls": [ + "https://files.pythonhosted.org/packages/83/25/e6d59e5f0a0508d0dca8bb98c7f7fd3772fc943ac3f53d5ab18a218d32c0/keyring-25.4.1-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_keyring_sdist_b07ebc55": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "keyring-25.4.1.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "keyring==25.4.1", + "sha256": "b07ebc55f3e8ed86ac81dd31ef14e81ace9dd9c3d4b5d77a6e9a2016d0d71a1b", + "urls": [ + "https://files.pythonhosted.org/packages/a5/1c/2bdbcfd5d59dc6274ffb175bc29aa07ecbfab196830e0cfbde7bd861a2ea/keyring-25.4.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "markdown_it_py-3.0.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "markdown-it-py==3.0.0", + "sha256": "355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", + "urls": [ + "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "markdown-it-py-3.0.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "markdown-it-py==3.0.0", + "sha256": "e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", + "urls": [ + "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_mdurl_py3_none_any_84008a41": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "mdurl-0.1.2-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "mdurl==0.1.2", + "sha256": "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", + "urls": [ + "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_mdurl_sdist_bb413d29": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "mdurl-0.1.2.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "mdurl==0.1.2", + "sha256": "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", + "urls": [ + "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "more_itertools-10.5.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "more-itertools==10.5.0", + "sha256": "037b0d3203ce90cca8ab1defbbdac29d5f993fc20131f3664dc8d6acfa872aef", + "urls": [ + "https://files.pythonhosted.org/packages/48/7e/3a64597054a70f7c86eb0a7d4fc315b8c1ab932f64883a297bdffeb5f967/more_itertools-10.5.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_more_itertools_sdist_5482bfef": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "more-itertools-10.5.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "more-itertools==10.5.0", + "sha256": "5482bfef7849c25dc3c6dd53a6173ae4795da2a41a80faea6700d9f5846c5da6", + "urls": [ + "https://files.pythonhosted.org/packages/51/78/65922308c4248e0eb08ebcbe67c95d48615cc6f27854b6f2e57143e9178f/more-itertools-10.5.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "14c5a72e9fe82aea5fe3072116ad4661af5cf8e8ff8fc5ad3450f123e4925e86", + "urls": [ + "https://files.pythonhosted.org/packages/b3/89/1daff5d9ba5a95a157c092c7c5f39b8dd2b1ddb4559966f808d31cfb67e0/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "7b7c2a3c9eb1a827d42539aa64091640bd275b81e097cd1d8d82ef91ffa2e811", + "urls": [ + "https://files.pythonhosted.org/packages/2c/b6/42fc3c69cabf86b6b81e4c051a9b6e249c5ba9f8155590222c2622961f58/nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "42c64511469005058cd17cc1537578eac40ae9f7200bedcfd1fc1a05f4f8c200", + "urls": [ + "https://files.pythonhosted.org/packages/45/b9/833f385403abaf0023c6547389ec7a7acf141ddd9d1f21573723a6eab39a/nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "0411beb0589eacb6734f28d5497ca2ed379eafab8ad8c84b31bb5c34072b7164", + "urls": [ + "https://files.pythonhosted.org/packages/05/2b/85977d9e11713b5747595ee61f381bc820749daf83f07b90b6c9964cf932/nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "5f36b271dae35c465ef5e9090e1fdaba4a60a56f0bb0ba03e0932a66f28b9189", + "urls": [ + "https://files.pythonhosted.org/packages/72/f2/5c894d5265ab80a97c68ca36f25c8f6f0308abac649aaf152b74e7e854a8/nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "19aaba96e0f795bd0a6c56291495ff59364f4300d4a39b29a0abc9cb3774a84b", + "urls": [ + "https://files.pythonhosted.org/packages/c2/a8/3bb02d0c60a03ad3a112b76c46971e9480efa98a8946677b5a59f60130ca/nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "de3ceed6e661954871d6cd78b410213bdcb136f79aafe22aa7182e028b8c7307", + "urls": [ + "https://files.pythonhosted.org/packages/1b/63/6ab90d0e5225ab9780f6c9fb52254fa36b52bb7c188df9201d05b647e5e1/nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "f0eca9ca8628dbb4e916ae2491d72957fdd35f7a5d326b7032a345f111ac07fe", + "urls": [ + "https://files.pythonhosted.org/packages/a3/da/0c4e282bc3cff4a0adf37005fa1fb42257673fbc1bbf7d1ff639ec3d255a/nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "3a157ab149e591bb638a55c8c6bcb8cdb559c8b12c13a8affaba6cedfe51713a", + "urls": [ + "https://files.pythonhosted.org/packages/de/81/c291231463d21da5f8bba82c8167a6d6893cc5419b0639801ee5d3aeb8a9/nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "36c95d4b70530b320b365659bb5034341316e6a9b30f0b25fa9c9eff4c27a204", + "urls": [ + "https://files.pythonhosted.org/packages/eb/61/73a007c74c37895fdf66e0edcd881f5eaa17a348ff02f4bb4bc906d61085/nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "nh3-0.2.18-cp37-abi3-win_amd64.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "8ce0f819d2f1933953fca255db2471ad58184a60508f03e6285e5114b6254844", + "urls": [ + "https://files.pythonhosted.org/packages/26/8d/53c5b19c4999bdc6ba95f246f4ef35ca83d7d7423e5e38be43ad66544e5d/nh3-0.2.18-cp37-abi3-win_amd64.whl" + ] + } + }, + "rules_python_publish_deps_311_nh3_sdist_94a16692": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "nh3-0.2.18.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "nh3==0.2.18", + "sha256": "94a166927e53972a9698af9542ace4e38b9de50c34352b962f4d9a7d4c927af4", + "urls": [ + "https://files.pythonhosted.org/packages/62/73/10df50b42ddb547a907deeb2f3c9823022580a7a47281e8eae8e003a9639/nh3-0.2.18.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "pkginfo-1.10.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pkginfo==1.10.0", + "sha256": "889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097", + "urls": [ + "https://files.pythonhosted.org/packages/56/09/054aea9b7534a15ad38a363a2bd974c20646ab1582a387a95b8df1bfea1c/pkginfo-1.10.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_pkginfo_sdist_5df73835": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pkginfo-1.10.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pkginfo==1.10.0", + "sha256": "5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297", + "urls": [ + "https://files.pythonhosted.org/packages/2f/72/347ec5be4adc85c182ed2823d8d1c7b51e13b9a6b0c1aae59582eca652df/pkginfo-1.10.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "pycparser-2.22-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pycparser==2.22", + "sha256": "c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", + "urls": [ + "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_pycparser_sdist_491c8be9": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pycparser-2.22.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pycparser==2.22", + "sha256": "491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", + "urls": [ + "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "pygments-2.18.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pygments==2.18.0", + "sha256": "b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", + "urls": [ + "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_pygments_sdist_786ff802": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pygments-2.18.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pygments==2.18.0", + "sha256": "786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", + "urls": [ + "https://files.pythonhosted.org/packages/8e/62/8336eff65bcbc8e4cb5d05b55faf041285951b6e80f33e2bff2024788f31/pygments-2.18.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_windows_x86_64" + ], + "filename": "pywin32_ctypes-0.2.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pywin32-ctypes==0.2.3", + "sha256": "8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", + "urls": [ + "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "pywin32-ctypes-0.2.3.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "pywin32-ctypes==0.2.3", + "sha256": "d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", + "urls": [ + "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "readme_renderer-44.0-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "readme-renderer==44.0", + "sha256": "2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", + "urls": [ + "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_readme_renderer_sdist_8712034e": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "readme_renderer-44.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "readme-renderer==44.0", + "sha256": "8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", + "urls": [ + "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_requests_py3_none_any_70761cfe": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "requests-2.32.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests==2.32.3", + "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", + "urls": [ + "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_requests_sdist_55365417": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "requests-2.32.3.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests==2.32.3", + "sha256": "55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", + "urls": [ + "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "requests_toolbelt-1.0.0-py2.py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests-toolbelt==1.0.0", + "sha256": "cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", + "urls": [ + "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "requests-toolbelt-1.0.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "requests-toolbelt==1.0.0", + "sha256": "7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", + "urls": [ + "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "rfc3986-2.0.0-py2.py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rfc3986==2.0.0", + "sha256": "50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", + "urls": [ + "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_rfc3986_sdist_97aacf9d": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "rfc3986-2.0.0.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rfc3986==2.0.0", + "sha256": "97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", + "urls": [ + "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_rich_py3_none_any_6049d5e6": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "rich-13.9.4-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rich==13.9.4", + "sha256": "6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", + "urls": [ + "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_rich_sdist_43959497": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "rich-13.9.4.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "rich==13.9.4", + "sha256": "439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", + "urls": [ + "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "filename": "SecretStorage-3.3.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "secretstorage==3.3.3", + "sha256": "f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99", + "urls": [ + "https://files.pythonhosted.org/packages/54/24/b4293291fa1dd830f353d2cb163295742fa87f179fcc8a20a306a81978b7/SecretStorage-3.3.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_secretstorage_sdist_2403533e": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "SecretStorage-3.3.3.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "secretstorage==3.3.3", + "sha256": "2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77", + "urls": [ + "https://files.pythonhosted.org/packages/53/a4/f48c9d79cb507ed1373477dbceaba7401fd8a23af63b837fa61f1dcd3691/SecretStorage-3.3.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_twine_py3_none_any_215dbe7b": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "twine-5.1.1-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "twine==5.1.1", + "sha256": "215dbe7b4b94c2c50a7315c0275d2258399280fbb7d04182c7e55e24b5f93997", + "urls": [ + "https://files.pythonhosted.org/packages/5d/ec/00f9d5fd040ae29867355e559a94e9a8429225a0284a3f5f091a3878bfc0/twine-5.1.1-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_twine_sdist_9aa08251": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "twine-5.1.1.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "twine==5.1.1", + "sha256": "9aa0825139c02b3434d913545c7b847a21c835e11597f5255842d457da2322db", + "urls": [ + "https://files.pythonhosted.org/packages/77/68/bd982e5e949ef8334e6f7dcf76ae40922a8750aa2e347291ae1477a4782b/twine-5.1.1.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "urllib3-2.2.3-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "urllib3==2.2.3", + "sha256": "ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", + "urls": [ + "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_urllib3_sdist_e7d814a8": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "urllib3-2.2.3.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "urllib3==2.2.3", + "sha256": "e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", + "urls": [ + "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz" + ] + } + }, + "rules_python_publish_deps_311_zipp_py3_none_any_a817ac80": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "filename": "zipp-3.20.2-py3-none-any.whl", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "zipp==3.20.2", + "sha256": "a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", + "urls": [ + "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl" + ] + } + }, + "rules_python_publish_deps_311_zipp_sdist_bc9eb26f": { + "repoRuleId": "@@rules_python+//python/private/pypi:whl_library.bzl%whl_library", + "attributes": { + "dep_template": "@rules_python_publish_deps//{name}:{target}", + "experimental_target_platforms": [ + "cp311_linux_aarch64", + "cp311_linux_arm", + "cp311_linux_ppc", + "cp311_linux_s390x", + "cp311_linux_x86_64", + "cp311_osx_aarch64", + "cp311_osx_x86_64", + "cp311_windows_x86_64" + ], + "extra_pip_args": [ + "--index-url", + "https://pypi.org/simple" + ], + "filename": "zipp-3.20.2.tar.gz", + "python_interpreter_target": "@@rules_python++python+python_3_11_host//:python", + "repo": "rules_python_publish_deps_311", + "requirement": "zipp==3.20.2", + "sha256": "bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", + "urls": [ + "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz" + ] + } + }, + "pip_deps": { + "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository", + "attributes": { + "repo_name": "pip_deps", + "extra_hub_aliases": {}, + "whl_map": { + "numpy": "{\"pip_deps_310_numpy\":[{\"version\":\"3.10\"}],\"pip_deps_311_numpy\":[{\"version\":\"3.11\"}],\"pip_deps_312_numpy\":[{\"version\":\"3.12\"}],\"pip_deps_38_numpy\":[{\"version\":\"3.8\"}],\"pip_deps_39_numpy\":[{\"version\":\"3.9\"}]}", + "setuptools": "{\"pip_deps_310_setuptools\":[{\"version\":\"3.10\"}],\"pip_deps_311_setuptools\":[{\"version\":\"3.11\"}],\"pip_deps_312_setuptools\":[{\"version\":\"3.12\"}],\"pip_deps_38_setuptools\":[{\"version\":\"3.8\"}],\"pip_deps_39_setuptools\":[{\"version\":\"3.9\"}]}" + }, + "packages": [ + "numpy", + "setuptools" + ], + "groups": {} + } + }, + "rules_fuzzing_py_deps": { + "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository", + "attributes": { + "repo_name": "rules_fuzzing_py_deps", + "extra_hub_aliases": {}, + "whl_map": { + "absl_py": "{\"rules_fuzzing_py_deps_310_absl_py\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_absl_py\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_absl_py\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_absl_py\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_absl_py\":[{\"version\":\"3.9\"}]}", + "six": "{\"rules_fuzzing_py_deps_310_six\":[{\"version\":\"3.10\"}],\"rules_fuzzing_py_deps_311_six\":[{\"version\":\"3.11\"}],\"rules_fuzzing_py_deps_312_six\":[{\"version\":\"3.12\"}],\"rules_fuzzing_py_deps_38_six\":[{\"version\":\"3.8\"}],\"rules_fuzzing_py_deps_39_six\":[{\"version\":\"3.9\"}]}" + }, + "packages": [ + "absl_py", + "six" + ], + "groups": {} + } + }, + "rules_python_publish_deps": { + "repoRuleId": "@@rules_python+//python/private/pypi:hub_repository.bzl%hub_repository", + "attributes": { + "repo_name": "rules_python_publish_deps", + "extra_hub_aliases": {}, + "whl_map": { + "backports_tarfile": "{\"rules_python_publish_deps_311_backports_tarfile_py3_none_any_77e284d7\":[{\"filename\":\"backports.tarfile-1.2.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_backports_tarfile_sdist_d75e02c2\":[{\"filename\":\"backports_tarfile-1.2.0.tar.gz\",\"version\":\"3.11\"}]}", + "certifi": "{\"rules_python_publish_deps_311_certifi_py3_none_any_922820b5\":[{\"filename\":\"certifi-2024.8.30-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_certifi_sdist_bec941d2\":[{\"filename\":\"certifi-2024.8.30.tar.gz\",\"version\":\"3.11\"}]}", + "cffi": "{\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_aarch64_a1ed2dd2\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_s390x_a24ed04c\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_manylinux_2_17_x86_64_610faea7\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_aarch64_a9b15d49\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_cp311_cp311_musllinux_1_1_x86_64_fc48c783\":[{\"filename\":\"cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cffi_sdist_1c39c601\":[{\"filename\":\"cffi-1.17.1.tar.gz\",\"version\":\"3.11\"}]}", + "charset_normalizer": "{\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_universal2_0d99dd8f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_10_9_x86_64_c57516e5\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_macosx_11_0_arm64_6dba5d19\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_aarch64_bf4475b8\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_s390x_8ff4e7cd\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_manylinux_2_17_x86_64_3710a975\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_aarch64_47334db7\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_s390x_63bc5c4a\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_musllinux_1_2_x86_64_bcb4f8ea\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_cp311_cp311_win_amd64_cee4373f\":[{\"filename\":\"charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_py3_none_any_fe9f97fe\":[{\"filename\":\"charset_normalizer-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_charset_normalizer_sdist_223217c3\":[{\"filename\":\"charset_normalizer-3.4.0.tar.gz\",\"version\":\"3.11\"}]}", + "cryptography": "{\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_aarch64_846da004\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_17_x86_64_0f996e72\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_aarch64_f7b178f1\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_manylinux_2_28_x86_64_c2e6fc39\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_aarch64_e1be4655\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_cp39_abi3_musllinux_1_2_x86_64_df6b6c6d\":[{\"filename\":\"cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_cryptography_sdist_315b9001\":[{\"filename\":\"cryptography-43.0.3.tar.gz\",\"version\":\"3.11\"}]}", + "docutils": "{\"rules_python_publish_deps_311_docutils_py3_none_any_dafca5b9\":[{\"filename\":\"docutils-0.21.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_docutils_sdist_3a6b1873\":[{\"filename\":\"docutils-0.21.2.tar.gz\",\"version\":\"3.11\"}]}", + "idna": "{\"rules_python_publish_deps_311_idna_py3_none_any_946d195a\":[{\"filename\":\"idna-3.10-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_idna_sdist_12f65c9b\":[{\"filename\":\"idna-3.10.tar.gz\",\"version\":\"3.11\"}]}", + "importlib_metadata": "{\"rules_python_publish_deps_311_importlib_metadata_py3_none_any_45e54197\":[{\"filename\":\"importlib_metadata-8.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_importlib_metadata_sdist_71522656\":[{\"filename\":\"importlib_metadata-8.5.0.tar.gz\",\"version\":\"3.11\"}]}", + "jaraco_classes": "{\"rules_python_publish_deps_311_jaraco_classes_py3_none_any_f662826b\":[{\"filename\":\"jaraco.classes-3.4.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_classes_sdist_47a024b5\":[{\"filename\":\"jaraco.classes-3.4.0.tar.gz\",\"version\":\"3.11\"}]}", + "jaraco_context": "{\"rules_python_publish_deps_311_jaraco_context_py3_none_any_f797fc48\":[{\"filename\":\"jaraco.context-6.0.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_context_sdist_9bae4ea5\":[{\"filename\":\"jaraco_context-6.0.1.tar.gz\",\"version\":\"3.11\"}]}", + "jaraco_functools": "{\"rules_python_publish_deps_311_jaraco_functools_py3_none_any_ad159f13\":[{\"filename\":\"jaraco.functools-4.1.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jaraco_functools_sdist_70f7e0e2\":[{\"filename\":\"jaraco_functools-4.1.0.tar.gz\",\"version\":\"3.11\"}]}", + "jeepney": "{\"rules_python_publish_deps_311_jeepney_py3_none_any_c0a454ad\":[{\"filename\":\"jeepney-0.8.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_jeepney_sdist_5efe48d2\":[{\"filename\":\"jeepney-0.8.0.tar.gz\",\"version\":\"3.11\"}]}", + "keyring": "{\"rules_python_publish_deps_311_keyring_py3_none_any_5426f817\":[{\"filename\":\"keyring-25.4.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_keyring_sdist_b07ebc55\":[{\"filename\":\"keyring-25.4.1.tar.gz\",\"version\":\"3.11\"}]}", + "markdown_it_py": "{\"rules_python_publish_deps_311_markdown_it_py_py3_none_any_35521684\":[{\"filename\":\"markdown_it_py-3.0.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_markdown_it_py_sdist_e3f60a94\":[{\"filename\":\"markdown-it-py-3.0.0.tar.gz\",\"version\":\"3.11\"}]}", + "mdurl": "{\"rules_python_publish_deps_311_mdurl_py3_none_any_84008a41\":[{\"filename\":\"mdurl-0.1.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_mdurl_sdist_bb413d29\":[{\"filename\":\"mdurl-0.1.2.tar.gz\",\"version\":\"3.11\"}]}", + "more_itertools": "{\"rules_python_publish_deps_311_more_itertools_py3_none_any_037b0d32\":[{\"filename\":\"more_itertools-10.5.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_more_itertools_sdist_5482bfef\":[{\"filename\":\"more-itertools-10.5.0.tar.gz\",\"version\":\"3.11\"}]}", + "nh3": "{\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_14c5a72e\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_macosx_10_12_x86_64_7b7c2a3c\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-macosx_10_12_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_aarch64_42c64511\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_armv7l_0411beb0\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_ppc64_5f36b271\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_s390x_19aaba96\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_manylinux_2_17_x86_64_de3ceed6\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_aarch64_f0eca9ca\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_aarch64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_armv7l_3a157ab1\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_armv7l.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_musllinux_1_2_x86_64_36c95d4b\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-musllinux_1_2_x86_64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_cp37_abi3_win_amd64_8ce0f819\":[{\"filename\":\"nh3-0.2.18-cp37-abi3-win_amd64.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_nh3_sdist_94a16692\":[{\"filename\":\"nh3-0.2.18.tar.gz\",\"version\":\"3.11\"}]}", + "pkginfo": "{\"rules_python_publish_deps_311_pkginfo_py3_none_any_889a6da2\":[{\"filename\":\"pkginfo-1.10.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pkginfo_sdist_5df73835\":[{\"filename\":\"pkginfo-1.10.0.tar.gz\",\"version\":\"3.11\"}]}", + "pycparser": "{\"rules_python_publish_deps_311_pycparser_py3_none_any_c3702b6d\":[{\"filename\":\"pycparser-2.22-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pycparser_sdist_491c8be9\":[{\"filename\":\"pycparser-2.22.tar.gz\",\"version\":\"3.11\"}]}", + "pygments": "{\"rules_python_publish_deps_311_pygments_py3_none_any_b8e6aca0\":[{\"filename\":\"pygments-2.18.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pygments_sdist_786ff802\":[{\"filename\":\"pygments-2.18.0.tar.gz\",\"version\":\"3.11\"}]}", + "pywin32_ctypes": "{\"rules_python_publish_deps_311_pywin32_ctypes_py3_none_any_8a151337\":[{\"filename\":\"pywin32_ctypes-0.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_pywin32_ctypes_sdist_d162dc04\":[{\"filename\":\"pywin32-ctypes-0.2.3.tar.gz\",\"version\":\"3.11\"}]}", + "readme_renderer": "{\"rules_python_publish_deps_311_readme_renderer_py3_none_any_2fbca89b\":[{\"filename\":\"readme_renderer-44.0-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_readme_renderer_sdist_8712034e\":[{\"filename\":\"readme_renderer-44.0.tar.gz\",\"version\":\"3.11\"}]}", + "requests": "{\"rules_python_publish_deps_311_requests_py3_none_any_70761cfe\":[{\"filename\":\"requests-2.32.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_sdist_55365417\":[{\"filename\":\"requests-2.32.3.tar.gz\",\"version\":\"3.11\"}]}", + "requests_toolbelt": "{\"rules_python_publish_deps_311_requests_toolbelt_py2_none_any_cccfdd66\":[{\"filename\":\"requests_toolbelt-1.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_requests_toolbelt_sdist_7681a0a3\":[{\"filename\":\"requests-toolbelt-1.0.0.tar.gz\",\"version\":\"3.11\"}]}", + "rfc3986": "{\"rules_python_publish_deps_311_rfc3986_py2_none_any_50b1502b\":[{\"filename\":\"rfc3986-2.0.0-py2.py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rfc3986_sdist_97aacf9d\":[{\"filename\":\"rfc3986-2.0.0.tar.gz\",\"version\":\"3.11\"}]}", + "rich": "{\"rules_python_publish_deps_311_rich_py3_none_any_6049d5e6\":[{\"filename\":\"rich-13.9.4-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_rich_sdist_43959497\":[{\"filename\":\"rich-13.9.4.tar.gz\",\"version\":\"3.11\"}]}", + "secretstorage": "{\"rules_python_publish_deps_311_secretstorage_py3_none_any_f356e662\":[{\"filename\":\"SecretStorage-3.3.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_secretstorage_sdist_2403533e\":[{\"filename\":\"SecretStorage-3.3.3.tar.gz\",\"version\":\"3.11\"}]}", + "twine": "{\"rules_python_publish_deps_311_twine_py3_none_any_215dbe7b\":[{\"filename\":\"twine-5.1.1-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_twine_sdist_9aa08251\":[{\"filename\":\"twine-5.1.1.tar.gz\",\"version\":\"3.11\"}]}", + "urllib3": "{\"rules_python_publish_deps_311_urllib3_py3_none_any_ca899ca0\":[{\"filename\":\"urllib3-2.2.3-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_urllib3_sdist_e7d814a8\":[{\"filename\":\"urllib3-2.2.3.tar.gz\",\"version\":\"3.11\"}]}", + "zipp": "{\"rules_python_publish_deps_311_zipp_py3_none_any_a817ac80\":[{\"filename\":\"zipp-3.20.2-py3-none-any.whl\",\"version\":\"3.11\"}],\"rules_python_publish_deps_311_zipp_sdist_bc9eb26f\":[{\"filename\":\"zipp-3.20.2.tar.gz\",\"version\":\"3.11\"}]}" + }, + "packages": [ + "backports_tarfile", + "certifi", + "charset_normalizer", + "docutils", + "idna", + "importlib_metadata", + "jaraco_classes", + "jaraco_context", + "jaraco_functools", + "keyring", + "markdown_it_py", + "mdurl", + "more_itertools", + "nh3", + "pkginfo", + "pygments", + "readme_renderer", + "requests", + "requests_toolbelt", + "rfc3986", + "rich", + "twine", + "urllib3", + "zipp" + ], + "groups": {} + } + } + }, + "moduleExtensionMetadata": { + "useAllRepos": "NO", + "reproducible": false + }, + "recordedRepoMappingEntries": [ + [ + "bazel_features+", + "bazel_features_globals", + "bazel_features++version_extension+bazel_features_globals" + ], + [ + "bazel_features+", + "bazel_features_version", + "bazel_features++version_extension+bazel_features_version" + ], + [ + "rules_python+", + "bazel_features", + "bazel_features+" + ], + [ + "rules_python+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "rules_python+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_python+", + "pypi__build", + "rules_python++internal_deps+pypi__build" + ], + [ + "rules_python+", + "pypi__click", + "rules_python++internal_deps+pypi__click" + ], + [ + "rules_python+", + "pypi__colorama", + "rules_python++internal_deps+pypi__colorama" + ], + [ + "rules_python+", + "pypi__importlib_metadata", + "rules_python++internal_deps+pypi__importlib_metadata" + ], + [ + "rules_python+", + "pypi__installer", + "rules_python++internal_deps+pypi__installer" + ], + [ + "rules_python+", + "pypi__more_itertools", + "rules_python++internal_deps+pypi__more_itertools" + ], + [ + "rules_python+", + "pypi__packaging", + "rules_python++internal_deps+pypi__packaging" + ], + [ + "rules_python+", + "pypi__pep517", + "rules_python++internal_deps+pypi__pep517" + ], + [ + "rules_python+", + "pypi__pip", + "rules_python++internal_deps+pypi__pip" + ], + [ + "rules_python+", + "pypi__pip_tools", + "rules_python++internal_deps+pypi__pip_tools" + ], + [ + "rules_python+", + "pypi__pyproject_hooks", + "rules_python++internal_deps+pypi__pyproject_hooks" + ], + [ + "rules_python+", + "pypi__setuptools", + "rules_python++internal_deps+pypi__setuptools" + ], + [ + "rules_python+", + "pypi__tomli", + "rules_python++internal_deps+pypi__tomli" + ], + [ + "rules_python+", + "pypi__wheel", + "rules_python++internal_deps+pypi__wheel" + ], + [ + "rules_python+", + "pypi__zipp", + "rules_python++internal_deps+pypi__zipp" + ], + [ + "rules_python+", + "pythons_hub", + "rules_python++python+pythons_hub" + ], + [ + "rules_python++python+pythons_hub", + "python_3_10_host", + "rules_python++python+python_3_10_host" + ], + [ + "rules_python++python+pythons_hub", + "python_3_11_host", + "rules_python++python+python_3_11_host" + ], + [ + "rules_python++python+pythons_hub", + "python_3_12_host", + "rules_python++python+python_3_12_host" + ], + [ + "rules_python++python+pythons_hub", + "python_3_8_host", + "rules_python++python+python_3_8_host" + ], + [ + "rules_python++python+pythons_hub", + "python_3_9_host", + "rules_python++python+python_3_9_host" + ] + ] + } + }, "@@rules_python+//python/uv:uv.bzl%uv": { "general": { "bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=", diff --git a/android/player/src/main/kotlin/com/intuit/playerui/android/AndroidPlayer.kt b/android/player/src/main/kotlin/com/intuit/playerui/android/AndroidPlayer.kt index 73b698900..79c3e2d91 100644 --- a/android/player/src/main/kotlin/com/intuit/playerui/android/AndroidPlayer.kt +++ b/android/player/src/main/kotlin/com/intuit/playerui/android/AndroidPlayer.kt @@ -8,6 +8,7 @@ import com.intuit.hooks.HookContext import com.intuit.hooks.SyncBailHook import com.intuit.hooks.SyncHook import com.intuit.hooks.SyncWaterfallHook +import com.intuit.playerui.android.asset.AssetRenderException import com.intuit.playerui.android.asset.RenderableAsset import com.intuit.playerui.android.asset.SuspendableAsset.AsyncHydrationTrackerPlugin import com.intuit.playerui.android.extensions.Styles @@ -18,12 +19,15 @@ import com.intuit.playerui.android.registry.RegistryPlugin import com.intuit.playerui.core.asset.Asset import com.intuit.playerui.core.bridge.Completable import com.intuit.playerui.core.bridge.format -import com.intuit.playerui.core.bridge.runtime.PlayerRuntimeConfig import com.intuit.playerui.core.bridge.serialization.format.registerContextualSerializer import com.intuit.playerui.core.constants.ConstantsController +import com.intuit.playerui.core.error.ErrorSeverity +import com.intuit.playerui.core.error.ErrorTypes import com.intuit.playerui.core.experimental.ExperimentalPlayerApi import com.intuit.playerui.core.logger.TapableLogger +import com.intuit.playerui.core.player.GetCoroutineFunction import com.intuit.playerui.core.player.HeadlessPlayer +import com.intuit.playerui.core.player.HeadlessPlayerRuntimeConfig import com.intuit.playerui.core.player.Player import com.intuit.playerui.core.player.PlayerException import com.intuit.playerui.core.player.state.CompletedState @@ -65,7 +69,7 @@ public class AndroidPlayer private constructor( public constructor( plugins: List, config: Config = Config(), - ) : this(HeadlessPlayer(plugins.injectDefaultPlugins(), config = config)) + ) : this(HeadlessPlayer(plugins.injectDefaultPlugins(), realConfig = config)) /** * Allow the [AndroidPlayer] to be built on top of a pre-existing @@ -353,7 +357,25 @@ public class AndroidPlayer private constructor( public data class Config( override var debuggable: Boolean = false, - override var coroutineExceptionHandler: CoroutineExceptionHandler? = null, + // TODO: Find an alternative to changing the type here or improve the API to make a little more sense + override var coroutineExceptionHandler: GetCoroutineFunction? = { player -> + CoroutineExceptionHandler { _, throwable -> + var metadata: Map? = null + if (throwable is AssetRenderException) { + metadata = mapOf( + "assetId" to throwable.rootAsset.asset.id, + ) + } + player.inProgressState?.controllers?.error?.captureError(throwable, ErrorTypes.RENDER, ErrorSeverity.ERROR, metadata) + ?: player.logger.error( + "Exception caught in Player scope: ${throwable.message}", + throwable.stackTrace + .joinToString("\n") { + "\tat $it" + }.replaceFirst("\tat ", "\n"), + ) + } + }, override var timeout: Long = if (debuggable) Int.MAX_VALUE.toLong() else 5000, - ) : PlayerRuntimeConfig() + ) : HeadlessPlayerRuntimeConfig() } diff --git a/android/player/src/main/kotlin/com/intuit/playerui/android/asset/SuspendableAsset.kt b/android/player/src/main/kotlin/com/intuit/playerui/android/asset/SuspendableAsset.kt index 5ce8a72de..0b7d5cf2c 100644 --- a/android/player/src/main/kotlin/com/intuit/playerui/android/asset/SuspendableAsset.kt +++ b/android/player/src/main/kotlin/com/intuit/playerui/android/asset/SuspendableAsset.kt @@ -52,7 +52,22 @@ public abstract class SuspendableAsset( } private suspend fun doInitView() = withContext(Dispatchers.Default) { - initView(getData()).apply { setTag(R.bool.view_hydrated, false) } + // TODO: Centralize some of this error handling so that it can be repeated easily. + try { + initView(getData()).apply { setTag(R.bool.view_hydrated, false) } + } catch (exception: Throwable) { + // ignore cancellation exceptions because those are used to rehydrate the view + if (exception is CancellationException) { + throw exception + } + + if (exception is AssetRenderException) { + exception.assetParentPath += assetContext + throw exception + } else { + throw AssetRenderException(assetContext, "Failed to render asset", exception) + } + } } // To be launched in Dispatchers.Main diff --git a/android/player/src/main/kotlin/com/intuit/playerui/android/compose/ComposableAsset.kt b/android/player/src/main/kotlin/com/intuit/playerui/android/compose/ComposableAsset.kt index 22358e6a9..d6231b3d9 100644 --- a/android/player/src/main/kotlin/com/intuit/playerui/android/compose/ComposableAsset.kt +++ b/android/player/src/main/kotlin/com/intuit/playerui/android/compose/ComposableAsset.kt @@ -24,7 +24,10 @@ import com.intuit.playerui.android.extensions.Styles import com.intuit.playerui.android.extensions.into import com.intuit.playerui.android.withContext import com.intuit.playerui.android.withTag +import com.intuit.playerui.core.error.ErrorSeverity +import com.intuit.playerui.core.error.ErrorTypes import com.intuit.playerui.core.experimental.ExperimentalPlayerApi +import com.intuit.playerui.core.player.state.inProgressState import kotlinx.coroutines.launch import kotlinx.serialization.KSerializer @@ -53,7 +56,19 @@ public abstract class ComposableAsset( @Composable public fun compose(data: Data? = null) { val data: Data? by produceState(initialValue = data, key1 = this) { - value = getData() + try { + value = getData() + } catch (error: Throwable) { + player.inProgressState?.controllers?.error?.captureError( + error, + ErrorTypes.RENDER, + ErrorSeverity.ERROR, + mapOf( + "assetId" to assetContext.asset.id, + ), + ) + null + } } data?.let { @@ -84,6 +99,7 @@ public abstract class ComposableAsset( ) { val assetTag = tag ?: asset.id val containerModifier = Modifier.testTag(assetTag) then modifier + // TODO: Conditionally call withTag only if tag is provided assetContext.withContext(LocalContext.current).withTag(assetTag).build().run { renewHydrationScope("Creating view within a ComposableAsset") when (this) { diff --git a/android/player/src/main/kotlin/com/intuit/playerui/android/lifecycle/PlayerViewModel.kt b/android/player/src/main/kotlin/com/intuit/playerui/android/lifecycle/PlayerViewModel.kt index f61efa898..dc7a31cea 100644 --- a/android/player/src/main/kotlin/com/intuit/playerui/android/lifecycle/PlayerViewModel.kt +++ b/android/player/src/main/kotlin/com/intuit/playerui/android/lifecycle/PlayerViewModel.kt @@ -6,8 +6,11 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.intuit.playerui.android.AndroidPlayer import com.intuit.playerui.android.AndroidPlayerPlugin +import com.intuit.playerui.android.asset.AssetRenderException import com.intuit.playerui.android.asset.RenderableAsset import com.intuit.playerui.core.bridge.runtime.Runtime +import com.intuit.playerui.core.error.ErrorSeverity +import com.intuit.playerui.core.error.ErrorTypes import com.intuit.playerui.core.experimental.ExperimentalPlayerApi import com.intuit.playerui.core.managed.AsyncFlowIterator import com.intuit.playerui.core.managed.AsyncIterationManager @@ -206,8 +209,21 @@ public open class PlayerViewModel( } } - public fun fail(cause: Throwable) { - player.inProgressState?.fail(cause) + public fun fail(throwable: Throwable) { + val cause = throwable.cause + // TODO: Replace type check with general exception that can have the metadata or other properties needed. + if (cause is AssetRenderException) { + player.inProgressState?.controllers?.error?.captureError( + cause, + ErrorTypes.RENDER, + ErrorSeverity.ERROR, + mapOf( + "assetId" to cause.rootAsset.asset.id, + ), + ) + } else { + player.inProgressState?.fail(throwable) + } } /** Helper to progress the [FlowManager] in within the [viewModelScope] */ diff --git a/core/player/src/controllers/error/controller.ts b/core/player/src/controllers/error/controller.ts index 06e2ffb3d..fd519ffe5 100644 --- a/core/player/src/controllers/error/controller.ts +++ b/core/player/src/controllers/error/controller.ts @@ -35,6 +35,23 @@ export interface ErrorControllerOptions { model?: DataController; } +type ReplacerFunction = (key: string, value: any) => any; + +const makeJsonStringifyReplacer = (): ReplacerFunction => { + const cache = new Set(); + return (_: string, value: any) => { + if (typeof value === "object" && value !== null) { + if (cache.has(value)) { + // Circular reference found, discard key + return "[CIRCULAR]"; + } + // Store value in our collection + cache.add(value); + } + return value; + }; +}; + /** The orchestrator for player error handling */ export class ErrorController { public hooks: ErrorControllerHooks = { @@ -88,6 +105,7 @@ export class ErrorController { errorType, severity, metadata, + skipped: false, }; // Add to history @@ -98,7 +116,11 @@ export class ErrorController { this.options.logger.debug( `[ErrorController] Captured error: ${error.message}`, - { errorType, severity, metadata }, + // TODO: Find a better way to do this. Either centralize the stringify replacer in the print plugin or something else. + JSON.stringify( + { errorType, severity, metadata }, + makeJsonStringifyReplacer(), + ), ); // Notify listeners and check if navigation should be skipped @@ -106,6 +128,7 @@ export class ErrorController { const shouldSkip = this.hooks.onError.call(playerError) ?? false; if (shouldSkip) { + playerError.skipped = true; this.options.logger.debug( "[ErrorController] Error state navigation skipped by plugin", ); diff --git a/core/player/src/controllers/error/types.ts b/core/player/src/controllers/error/types.ts index f44e236d2..18817dccb 100644 --- a/core/player/src/controllers/error/types.ts +++ b/core/player/src/controllers/error/types.ts @@ -17,6 +17,7 @@ export const ErrorTypes = { SCHEMA: "schema", NETWORK: "network", PLUGIN: "plugin", + RENDER: "render", } as const; /** @@ -36,4 +37,6 @@ export interface PlayerError { severity?: ErrorSeverity; /** Additional metadata */ metadata?: ErrorMetadata; + /** Whether or not the error was skipped. */ + skipped: boolean; } diff --git a/core/player/src/controllers/view/controller.ts b/core/player/src/controllers/view/controller.ts index 7ad9e1d41..b996995fa 100644 --- a/core/player/src/controllers/view/controller.ts +++ b/core/player/src/controllers/view/controller.ts @@ -22,6 +22,7 @@ import type { DataController } from "../data/controller"; import type { TransformRegistry } from "./types"; import type { BindingInstance } from "../../binding"; import type { Node } from "../../view"; +import { ErrorController } from "../error"; export interface ViewControllerOptions { /** Where to get data from */ @@ -32,6 +33,9 @@ export interface ViewControllerOptions { /** A flow-controller instance to listen for view changes */ flowController: FlowController; + + /** Error controller to use when managing view-level errors */ + errorController: ErrorController; } export type ViewControllerHooks = { @@ -197,7 +201,11 @@ export class ViewController { throw new Error(`No view with id ${viewId}`); } - const view = new ViewInstance(source, this.viewOptions); + const view = new ViewInstance( + source, + this.viewOptions, + this.viewOptions.errorController, + ); this.currentView = view; // Give people a chance to attach their diff --git a/core/player/src/player.ts b/core/player/src/player.ts index 73a2776f7..e42e2cdf2 100644 --- a/core/player/src/player.ts +++ b/core/player/src/player.ts @@ -460,6 +460,7 @@ export class Player { type: (b) => schema.getType(parseBinding(b)), }, constants: this.constantsController, + errorController, }); viewController.hooks.view.tap("player", (view) => { diff --git a/core/player/src/view/resolver/index.ts b/core/player/src/view/resolver/index.ts index 24f434f88..9d3821f17 100644 --- a/core/player/src/view/resolver/index.ts +++ b/core/player/src/view/resolver/index.ts @@ -251,223 +251,254 @@ export class Resolver { prevASTMap: Map, nodeChanges: Set, ): NodeUpdate { - const dependencyModel = new DependencyModel(options.data.model); - - dependencyModel.trackSubset("core"); - const depModelWithParser = withContext( - withParser(dependencyModel, this.options.parseBinding), - ); - - const resolveOptions = this.hooks.resolveOptions.call( - { - ...options, - data: { - ...options.data, - model: depModelWithParser, + try { + const dependencyModel = new DependencyModel(options.data.model); + dependencyModel.trackSubset("core"); + const depModelWithParser = withContext( + withParser(dependencyModel, this.options.parseBinding), + ); + + const resolveOptions = this.hooks.resolveOptions.call( + { + ...options, + data: { + ...options.data, + model: depModelWithParser, + }, + evaluate: (exp) => + this.options.evaluator.evaluate(exp, { model: depModelWithParser }), + node, }, - evaluate: (exp) => - this.options.evaluator.evaluate(exp, { model: depModelWithParser }), node, - }, - node, - ); + ); - const previousResult = this.getPreviousResult(node); - const previousDeps = previousResult?.dependencies; + const previousResult = this.getPreviousResult(node); + const previousDeps = previousResult?.dependencies; - const isChanged = nodeChanges.has(node); - const dataChanged = caresAboutDataChanges(dataChanges, previousDeps); - const shouldUseLastValue = this.hooks.skipResolve.call( - !dataChanged && !isChanged, - node, - resolveOptions, - ); - - if (previousResult && shouldUseLastValue) { - const update = { - ...previousResult, - updated: false, - }; + const isChanged = nodeChanges.has(node); + const dataChanged = caresAboutDataChanges(dataChanges, previousDeps); + const shouldUseLastValue = this.hooks.skipResolve.call( + !dataChanged && !isChanged, + node, + resolveOptions, + ); - /** Recursively repopulate the AST map given some AST Node and it's resolved AST representation */ - const repopulateASTMapFromCache = ( - resolvedNode: Resolve.ResolvedNode, - AST: Node.Node, - ASTParent: Node.Node | undefined, - ) => { - const { node: resolvedASTLocal } = resolvedNode; - this.ASTMap.set(resolvedASTLocal, AST); - const resolvedUpdate = { - ...resolvedNode, + if (previousResult && shouldUseLastValue) { + const update = { + ...previousResult, updated: false, }; - cacheUpdate.set(AST, resolvedUpdate); - - /** Helper function for recursing over child node */ - const handleChildNode = (childNode: Node.Node) => { - // In order to get the correct results, we need to use the node references from the last update. - const originalChildNode = prevASTMap.get(childNode) ?? childNode; - const previousChildResult = this.getPreviousResult(originalChildNode); - if (!previousChildResult) return; - - repopulateASTMapFromCache( - previousChildResult, - originalChildNode, - AST, - ); - }; - if ("children" in resolvedASTLocal) { - resolvedASTLocal.children?.forEach(({ value: childAST }) => - handleChildNode(childAST), - ); - } else if (resolvedASTLocal.type === NodeType.MultiNode) { - resolvedASTLocal.values.forEach(handleChildNode); - } + /** Recursively repopulate the AST map given some AST Node and it's resolved AST representation */ + const repopulateASTMapFromCache = ( + resolvedNode: Resolve.ResolvedNode, + AST: Node.Node, + ASTParent: Node.Node | undefined, + ) => { + const { node: resolvedASTLocal } = resolvedNode; + this.ASTMap.set(resolvedASTLocal, AST); + const resolvedUpdate = { + ...resolvedNode, + updated: false, + }; + cacheUpdate.set(AST, resolvedUpdate); + + /** Helper function for recursing over child node */ + const handleChildNode = (childNode: Node.Node) => { + // In order to get the correct results, we need to use the node references from the last update. + const originalChildNode = prevASTMap.get(childNode) ?? childNode; + const previousChildResult = + this.getPreviousResult(originalChildNode); + if (!previousChildResult) return; + + repopulateASTMapFromCache( + previousChildResult, + originalChildNode, + AST, + ); + }; - this.hooks.afterNodeUpdate.call(AST, ASTParent, resolvedUpdate); - }; + if ("children" in resolvedASTLocal) { + resolvedASTLocal.children?.forEach(({ value: childAST }) => + handleChildNode(childAST), + ); + } else if (resolvedASTLocal.type === NodeType.MultiNode) { + resolvedASTLocal.values.forEach(handleChildNode); + } - // Point the root of the cached node to the new resolved node. - previousResult.node.parent = partiallyResolvedParent; + this.hooks.afterNodeUpdate.call(AST, ASTParent, resolvedUpdate); + }; - repopulateASTMapFromCache(previousResult, node, rawParent); + // Point the root of the cached node to the new resolved node. + previousResult.node.parent = partiallyResolvedParent; - return update; - } + repopulateASTMapFromCache(previousResult, node, rawParent); - // Shallow clone the node so that changes to it during the resolve steps don't impact the original. - // We are trusting that this becomes a deep clone once the whole node tree has been traversed. - const clonedNode: Node.Node = { - ...this.cloneNode(node), - parent: partiallyResolvedParent, - }; - const resolvedAST = this.hooks.beforeResolve.call( - clonedNode, - resolveOptions, - ) ?? { - type: NodeType.Empty, - }; + return update; + } - resolvedAST.parent = partiallyResolvedParent; + // Shallow clone the node so that changes to it during the resolve steps don't impact the original. + // We are trusting that this becomes a deep clone once the whole node tree has been traversed. + const clonedNode: Node.Node = { + ...this.cloneNode(node), + parent: partiallyResolvedParent, + }; + const resolvedAST = this.hooks.beforeResolve.call( + clonedNode, + resolveOptions, + ) ?? { + type: NodeType.Empty, + }; - resolveOptions.node = resolvedAST; + resolvedAST.parent = partiallyResolvedParent; - this.ASTMap.set(resolvedAST, node); + resolveOptions.node = resolvedAST; - let resolved = this.hooks.resolve.call( - undefined, - resolvedAST, - resolveOptions, - ); + this.ASTMap.set(resolvedAST, node); - let updated = !dequal(previousResult?.value, resolved); + let resolved = this.hooks.resolve.call( + undefined, + resolvedAST, + resolveOptions, + ); - if (previousResult && !updated) { - resolved = previousResult?.value; - } + let updated = !dequal(previousResult?.value, resolved); - const childDependencies = new Set(); - dependencyModel.trackSubset("children"); + if (previousResult && !updated) { + resolved = previousResult?.value; + } - if ("children" in resolvedAST) { - const newChildren = resolvedAST.children?.map((child) => { - const computedChildTree = this.computeTree( - child.value, - node, - dataChanges, - cacheUpdate, - resolveOptions, - resolvedAST, - prevASTMap, - nodeChanges, - ); - const { - dependencies: childTreeDeps, - node: childNode, - updated: childUpdated, - value: childValue, - } = computedChildTree; - - childTreeDeps.forEach((binding) => childDependencies.add(binding)); - - if (childValue) { - if (childNode.type === NodeType.MultiNode && !childNode.override) { - const arr = addLast( - dlv(resolved, child.path as any[], []), - childValue, + const childDependencies = new Set(); + dependencyModel.trackSubset("children"); + + if ("children" in resolvedAST) { + const newChildren = resolvedAST.children?.map((child) => { + const computedChildTree = this.computeTree( + child.value, + node, + dataChanges, + cacheUpdate, + resolveOptions, + resolvedAST, + prevASTMap, + nodeChanges, + ); + const { + dependencies: childTreeDeps, + node: childNode, + updated: childUpdated, + value: childValue, + } = computedChildTree; + + childTreeDeps.forEach((binding) => childDependencies.add(binding)); + + if (childValue) { + if (childNode.type === NodeType.MultiNode && !childNode.override) { + const arr = addLast( + dlv(resolved, child.path as any[], []), + childValue, + ); + resolved = setIn(resolved, child.path, arr); + } else { + resolved = setIn(resolved, child.path, childValue); + } + } + + updated = updated || childUpdated; + + return { ...child, value: childNode }; + }); + + resolvedAST.children = newChildren; + } else if (resolvedAST.type === NodeType.MultiNode) { + const childValue: any = []; + const rawParentToPassIn = node; + + resolvedAST.values = resolvedAST.values.map((mValue) => { + const mTree = this.computeTree( + mValue, + rawParentToPassIn, + dataChanges, + cacheUpdate, + resolveOptions, + resolvedAST, + prevASTMap, + nodeChanges, + ); + + if (mTree.value !== undefined && mTree.value !== null) { + mTree.dependencies.forEach((bindingDep) => + childDependencies.add(bindingDep), ); - resolved = setIn(resolved, child.path, arr); - } else { - resolved = setIn(resolved, child.path, childValue); + + updated = updated || mTree.updated; + childValue.push(mTree.value); } - } - updated = updated || childUpdated; + return mTree.node; + }); - return { ...child, value: childNode }; - }); + resolved = childValue; + } - resolvedAST.children = newChildren; - } else if (resolvedAST.type === NodeType.MultiNode) { - const childValue: any = []; - const rawParentToPassIn = node; - - resolvedAST.values = resolvedAST.values.map((mValue) => { - const mTree = this.computeTree( - mValue, - rawParentToPassIn, - dataChanges, - cacheUpdate, - resolveOptions, - resolvedAST, - prevASTMap, - nodeChanges, - ); - - if (mTree.value !== undefined && mTree.value !== null) { - mTree.dependencies.forEach((bindingDep) => - childDependencies.add(bindingDep), - ); + childDependencies.forEach((bindingDep) => + dependencyModel.addChildReadDep(bindingDep), + ); - updated = updated || mTree.updated; - childValue.push(mTree.value); - } + dependencyModel.trackSubset("core"); + if (previousResult && !updated) { + resolved = previousResult?.value; + } - return mTree.node; + resolved = this.hooks.afterResolve.call(resolved, resolvedAST, { + ...resolveOptions, + getDependencies: (scope?: "core" | "children") => + dependencyModel.getDependencies(scope), }); - resolved = childValue; - } + const update: NodeUpdate = { + node: resolvedAST, + updated, + value: resolved, + dependencies: new Set([ + ...dependencyModel.getDependencies(), + ...childDependencies, + ]), + }; - childDependencies.forEach((bindingDep) => - dependencyModel.addChildReadDep(bindingDep), - ); + this.hooks.afterNodeUpdate.call(node, rawParent, update); + cacheUpdate.set(node, update); - dependencyModel.trackSubset("core"); - if (previousResult && !updated) { - resolved = previousResult?.value; - } + return update; + } catch (err: unknown) { + const error = err instanceof Error ? err : new Error(String(err)); - resolved = this.hooks.afterResolve.call(resolved, resolvedAST, { - ...resolveOptions, - getDependencies: (scope?: "core" | "children") => - dependencyModel.getDependencies(scope), - }); + const resolverError = + error instanceof ResolverError + ? error + : new ResolverError(error, ResolverStages.BeforeResolve, node); - const update: NodeUpdate = { - node: resolvedAST, - updated, - value: resolved, - dependencies: new Set([ - ...dependencyModel.getDependencies(), - ...childDependencies, - ]), - }; + throw resolverError; + } + } +} - this.hooks.afterNodeUpdate.call(node, rawParent, update); - cacheUpdate.set(node, update); +export const ResolverStages = { + ResolveOptions: "resolve-options", + BeforeResolve: "before-resolve", +} as const; - return update; +export type ResolverStage = + (typeof ResolverStages)[keyof typeof ResolverStages]; +export class ResolverError extends Error { + /** + * + */ + constructor( + public readonly cause: Error, + public readonly stage: ResolverStage, + public readonly node: Node.Node, + ) { + super(`An error in the resolver occurred at stage '${stage}'`); } } diff --git a/core/player/src/view/view.ts b/core/player/src/view/view.ts index 4d187feb7..d4824c39b 100644 --- a/core/player/src/view/view.ts +++ b/core/player/src/view/view.ts @@ -4,10 +4,16 @@ import type { BindingInstance, BindingFactory } from "../binding"; import type { ValidationProvider, ValidationObject } from "../validator"; import type { Logger } from "../logger"; import type { Resolve } from "./resolver"; -import { Resolver } from "./resolver"; +import { Resolver, ResolverError } from "./resolver"; import type { Node } from "./parser"; import { Parser } from "./parser"; import { TemplatePlugin } from "./plugins"; +import { + ErrorController, + ErrorMetadata, + ErrorSeverity, + ErrorTypes, +} from "../controllers"; /** * Manages the view level validations @@ -96,6 +102,7 @@ export class ViewInstance implements ValidationProvider { public readonly initialView: ViewType; public readonly resolverOptions: Resolve.ResolverOptions; private rootNode?: Node.Node; + private readonly errorController: ErrorController | undefined; private validationProvider?: CrossfieldProvider; @@ -104,9 +111,14 @@ export class ViewInstance implements ValidationProvider { // TODO might want to add a version/timestamp to this to compare updates public lastUpdate: Record | undefined; - constructor(initialView: ViewType, resolverOptions: Resolve.ResolverOptions) { + constructor( + initialView: ViewType, + resolverOptions: Resolve.ResolverOptions, + errorController?: ErrorController, + ) { this.initialView = initialView; this.resolverOptions = resolverOptions; + this.errorController = errorController; } /** @deprecated use ViewController.updateViewAST */ @@ -147,16 +159,38 @@ export class ViewInstance implements ValidationProvider { this.hooks.resolver.call(this.resolver); } - const update = this.resolver?.update(changes, nodeChanges); + try { + const update = this.resolver?.update(changes, nodeChanges); - if (this.lastUpdate === update) { - return this.lastUpdate; - } + if (this.lastUpdate === update) { + return this.lastUpdate; + } - this.lastUpdate = update; - this.hooks.onUpdate.call(update); + this.lastUpdate = update; + this.hooks.onUpdate.call(update); + + return update; + } catch (err: unknown) { + // TODO: Just let error bubble up so nothing needs to be returned here. + if (!this.errorController) { + throw err; + } + + const error = err instanceof Error ? err : new Error(String(err)); + const metadata: ErrorMetadata = {}; + if (error instanceof ResolverError) { + metadata.node = error.node; + } + this.errorController.captureError( + error, + ErrorTypes.VIEW, + ErrorSeverity.ERROR, + metadata, + ); - return update; + // Return previous update while error controller decides the next course of action. + return this.lastUpdate; + } } getValidationsForBinding( diff --git a/docs/storybook/src/reference-assets/ErrorHandling.stories.tsx b/docs/storybook/src/reference-assets/ErrorHandling.stories.tsx new file mode 100644 index 000000000..d58d5ff93 --- /dev/null +++ b/docs/storybook/src/reference-assets/ErrorHandling.stories.tsx @@ -0,0 +1,21 @@ +import type { Meta } from "@storybook/react-webpack5"; +import { createDSLStory } from "@player-ui/storybook"; +import { Throwing } from "@player-ui/reference-assets-plugin-react"; + +const meta: Meta = { + title: "Reference Assets/Error Handling", + component: Throwing, + parameters: { + assetDocs: ["InputAsset"], + }, +}; + +export default meta; + +export const RenderTime = createDSLStory( + () => import("!!raw-loader!@player-ui/mocks/throwing/throw-render.tsx"), +); + +export const TransformTime = createDSLStory( + () => import("!!raw-loader!@player-ui/mocks/throwing/throw-transform.tsx"), +); diff --git a/ios/core/Sources/Types/Core/ErrorController.swift b/ios/core/Sources/Types/Core/ErrorController.swift index 78a7ab5b9..f18d006a8 100644 --- a/ios/core/Sources/Types/Core/ErrorController.swift +++ b/ios/core/Sources/Types/Core/ErrorController.swift @@ -34,6 +34,7 @@ public struct ErrorTypes { public static let schema = "schema" public static let network = "network" public static let plugin = "plugin" + public static let render = "render" } /** diff --git a/ios/demo/Sources/MockFlows.swift b/ios/demo/Sources/MockFlows.swift index 1ee599025..2c9fac7af 100644 --- a/ios/demo/Sources/MockFlows.swift +++ b/ios/demo/Sources/MockFlows.swift @@ -1480,6 +1480,34 @@ static let chatMessageBasic: String = """ } } } + }, + { + "asset": { + "id": "values-3", + "type": "action", + "exp": "sendBroken({{content}})", + "label": { + "asset": { + "id": "values-3-label", + "type": "text", + "value": " Send Broken Render Asset " + } + } + } + }, + { + "asset": { + "id": "values-4", + "type": "action", + "exp": "sendBrokenTransform({{content}})", + "label": { + "asset": { + "id": "values-4-label", + "type": "text", + "value": " Send Broken Transform Asset " + } + } + } } ] } diff --git a/ios/swiftui/Sources/SwiftUIPlayer.swift b/ios/swiftui/Sources/SwiftUIPlayer.swift index 9a55a76eb..764b823f3 100644 --- a/ios/swiftui/Sources/SwiftUIPlayer.swift +++ b/ios/swiftui/Sources/SwiftUIPlayer.swift @@ -160,7 +160,15 @@ public struct SwiftUIPlayer: View, HeadlessPlayer { do { try registry.decode(value: value) } catch { - (state as? InProgressState)?.fail(PlayerError.unknownResponse(error)) + if let assetErr = error as? AssetRenderError { + switch assetErr { + case .decodingFailure(let innerError, let asset, let pathToAsset): + (state as? InProgressState)?.controllers?.error.captureError(error: assetErr, errorType: ErrorTypes.render, severity: .error, metadata: ["assetId": asset?.id ?? ""]) + break; + } + } else { + (state as? InProgressState)?.fail(PlayerError.unknownResponse(error)) + } } } } diff --git a/jvm/core/src/main/kotlin/com/intuit/playerui/core/bridge/runtime/PlayerRuntimeConfig.kt b/jvm/core/src/main/kotlin/com/intuit/playerui/core/bridge/runtime/PlayerRuntimeConfig.kt index a62154d83..194e947bc 100644 --- a/jvm/core/src/main/kotlin/com/intuit/playerui/core/bridge/runtime/PlayerRuntimeConfig.kt +++ b/jvm/core/src/main/kotlin/com/intuit/playerui/core/bridge/runtime/PlayerRuntimeConfig.kt @@ -1,5 +1,4 @@ package com.intuit.playerui.core.bridge.runtime - import kotlinx.coroutines.CoroutineExceptionHandler /** Base configuration for [Runtime] */ diff --git a/jvm/core/src/main/kotlin/com/intuit/playerui/core/error/ErrorController.kt b/jvm/core/src/main/kotlin/com/intuit/playerui/core/error/ErrorController.kt index 989e654bb..8958802a0 100644 --- a/jvm/core/src/main/kotlin/com/intuit/playerui/core/error/ErrorController.kt +++ b/jvm/core/src/main/kotlin/com/intuit/playerui/core/error/ErrorController.kt @@ -37,6 +37,7 @@ public object ErrorTypes { public const val SCHEMA: String = "schema" public const val NETWORK: String = "network" public const val PLUGIN: String = "plugin" + public const val RENDER: String = "render" } /** diff --git a/jvm/core/src/main/kotlin/com/intuit/playerui/core/player/HeadlessPlayer.kt b/jvm/core/src/main/kotlin/com/intuit/playerui/core/player/HeadlessPlayer.kt index bfa6cb92f..1b9a22d26 100644 --- a/jvm/core/src/main/kotlin/com/intuit/playerui/core/player/HeadlessPlayer.kt +++ b/jvm/core/src/main/kotlin/com/intuit/playerui/core/player/HeadlessPlayer.kt @@ -33,6 +33,24 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import java.net.URL +public typealias GetCoroutineFunction = (Player) -> CoroutineExceptionHandler + +public open class HeadlessPlayerRuntimeConfig { + public constructor() + + public constructor(config: PlayerRuntimeConfig) { + debuggable = config.debuggable + coroutineExceptionHandler = config.coroutineExceptionHandler?.let { h -> + { _: Player -> h } + } + timeout = config.timeout + } + + public open var debuggable: Boolean = false + public open var coroutineExceptionHandler: GetCoroutineFunction? = null + public open var timeout: Long = if (debuggable) Int.MAX_VALUE.toLong() else 5000 +} + /** * Headless [Player] wrapping a core JS player with a [Runtime]. The [player] * will be instantiated from the [bundledSource] unless supplied with @@ -54,6 +72,7 @@ public class HeadlessPlayer @ExperimentalPlayerApi @JvmOverloads public construc explicitRuntime: Runtime<*>? = null, private val source: URL = bundledSource, config: PlayerRuntimeConfig = PlayerRuntimeConfig(), + realConfig: HeadlessPlayerRuntimeConfig = HeadlessPlayerRuntimeConfig(config), ) : Player(), NodeWrapper { /** Convenience constructor to allow [plugins] to be passed as varargs */ @@ -63,6 +82,7 @@ public class HeadlessPlayer @ExperimentalPlayerApi @JvmOverloads public construc config: PlayerRuntimeConfig = PlayerRuntimeConfig(), explicitRuntime: Runtime<*>? = null, source: URL = bundledSource, + realConfig: HeadlessPlayerRuntimeConfig? = null, ) : this(plugins.toList(), explicitRuntime, source, config) public constructor( @@ -90,19 +110,21 @@ public class HeadlessPlayer @ExperimentalPlayerApi @JvmOverloads public construc } public val runtime: Runtime<*> = explicitRuntime ?: runtimeFactory.create { - debuggable = config.debuggable - timeout = config.timeout - coroutineExceptionHandler = config.coroutineExceptionHandler ?: CoroutineExceptionHandler { _, throwable -> - if (state !is ReleasedState) { - inProgressState?.fail(throwable) ?: logger.error( - "Exception caught in Player scope: ${throwable.message}", - throwable.stackTrace - .joinToString("\n") { - "\tat $it" - }.replaceFirst("\tat ", "\n"), - ) + debuggable = realConfig.debuggable + timeout = realConfig.timeout + coroutineExceptionHandler = + realConfig.coroutineExceptionHandler?.invoke(this@HeadlessPlayer) ?: CoroutineExceptionHandler { _, throwable -> + if (state !is ReleasedState) { + logger.error("[HeadlessPlayer]: Error has been found") + inProgressState?.fail(throwable) ?: logger.error( + "Exception caught in Player scope: ${throwable.message}", + throwable.stackTrace + .joinToString("\n") { + "\tat $it" + }.replaceFirst("\tat ", "\n"), + ) + } } - } } override val scope: CoroutineScope by runtime::scope diff --git a/plugins/async-node/core/src/index.ts b/plugins/async-node/core/src/index.ts index 1c0fb3524..051f42bc7 100644 --- a/plugins/async-node/core/src/index.ts +++ b/plugins/async-node/core/src/index.ts @@ -1,4 +1,4 @@ -import { NodeType, getNodeID } from "@player-ui/player"; +import { ErrorTypes, NodeType, getNodeID } from "@player-ui/player"; import type { Player, PlayerPlugin, @@ -11,6 +11,7 @@ import type { Resolver, Resolve, ViewController, + PlayerError, } from "@player-ui/player"; import { AsyncSeriesBailHook, SyncBailHook } from "tapable-ts"; import queueMicrotask from "queue-microtask"; @@ -35,6 +36,15 @@ type AsyncPluginContext = { * In some cases, async nodes are transformed into from other node types so the original reference is needed in order to trigger an update on the view when the async node changes. */ originalNodeCache: Map>; + + /** Maps generated nodes to the async id that generated them. */ + oneMoreCache: Map; + + /** Maps asset ids to its original node. Used to then search for what if could be generated by. */ + assetIdCache: Map; + + /** map of async nodes ids to their async nodes. */ + sureWhyNotOneMoreThing: Map; }; export interface AsyncNodePluginOptions { @@ -42,6 +52,16 @@ export interface AsyncNodePluginOptions { plugins?: AsyncNodeViewPlugin[]; } +export type ThingType = Resolve.NodeResolveOptions & { + asyncData?: { + generatedBy?: string; + }; +}; + +const isThingType = (thing: Resolve.NodeResolveOptions): thing is ThingType => { + return true; +}; + export interface AsyncNodeViewPlugin extends ViewPlugin { /** Use this to tap into the async node plugin hooks */ applyPlugin: (asyncNodePlugin: AsyncNodePlugin) => void; @@ -142,10 +162,10 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { node: Node.Async, context: AsyncPluginContext, result: any, - options: Resolve.NodeResolveOptions, + parseFunction?: (content: any) => Node.Node | null, ) { let parsedNode = - options.parseNode && result ? options.parseNode(result) : undefined; + parseFunction && result ? parseFunction(result) : undefined; if (parsedNode && node.onValueReceived) { parsedNode = node.onValueReceived(parsedNode); @@ -193,12 +213,64 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { * @param view */ applyResolver(resolver: Resolver, context: AsyncPluginContext): void { + resolver.hooks.resolveOptions.tap(this.name, (options, node) => { + if (!isThingType(options)) { + return options; + } + + const generatedArray = Array.isArray(options.asyncData?.generatedBy) + ? options.asyncData?.generatedBy + : []; + + // TODO: edge case - is not originally an async node, but becomes one through a transform or w/e + + // 1. If it is an async node, then it will be generated by it. + if (this.isAsync(node)) { + return { + ...options, + asyncData: { + generatedBy: [node.id, ...generatedArray], + }, + }; + } + + // 2. If it was generated through `resolveAsyncChildren` it should exist in oneMoreCache + const thing = context.oneMoreCache.get(node); + if (thing) { + return { + ...options, + asyncData: { + generatedBy: [thing, ...generatedArray], + }, + }; + } + + return options; + }); + + resolver.hooks.afterNodeUpdate.tap( + this.name, + (original, parent, update) => { + if ( + update.node.type !== NodeType.Asset && + update.node.type !== NodeType.View + ) { + return; + } + + context.assetIdCache.set(update.value.id, original); + }, + ); + resolver.hooks.beforeResolve.tap(this.name, (node, options) => { if (!this.isAsync(node)) { return node === null ? node : this.resolveAsyncChildren(node, context); } + + context.sureWhyNotOneMoreThing.set(node.id, node); if (options.node) { context.originalNodeCache.set(node.id, new Set([options.node])); + context.oneMoreCache.set(options.node, node.id); } const resolvedNode = context.nodeResolveCache.get(node.id); @@ -244,6 +316,8 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { continue; } + context.sureWhyNotOneMoreThing.set(childNode.id, childNode); + const mappedNode = context.nodeResolveCache.get(childNode.id)!; const nodeSet = new Set(); if (mappedNode.type === NodeType.MultiNode && childNode.flatten) { @@ -262,6 +336,9 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { nodeSet.add(mappedNode); } context.originalNodeCache.set(childNode.id, nodeSet); + for (const n of nodeSet) { + context.oneMoreCache.set(n, childNode.id); + } } } else if ("children" in node) { node.children?.forEach((c) => { @@ -272,6 +349,7 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { ) { const mappedNode = context.nodeResolveCache.get(c.value.id)!; context.originalNodeCache.set(c.value.id, new Set([mappedNode])); + context.oneMoreCache.set(mappedNode, c.value.id); c.value = mappedNode; c.value.parent = node; } @@ -290,13 +368,13 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { const result = await this.basePlugin?.hooks.onAsyncNode.call( node, (result) => { - this.parseNodeAndUpdate(node, context, result, options); + this.parseNodeAndUpdate(node, context, result, options.parseNode); }, ); // Stop tracking before the next update is triggered context.inProgressNodes.delete(node.id); - this.parseNodeAndUpdate(node, context, result, options); + this.parseNodeAndUpdate(node, context, result, options.parseNode); } catch (e: unknown) { const error = e instanceof Error ? e : new Error(String(e)); const result = this.basePlugin?.hooks.onAsyncNodeError.call(error, node); @@ -318,7 +396,7 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { // Stop tracking before the next update is triggered context.inProgressNodes.delete(node.id); - this.parseNodeAndUpdate(node, context, result, options); + this.parseNodeAndUpdate(node, context, result, options.parseNode); } } @@ -385,15 +463,72 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { } applyPlayer(player: Player): void { + let currentContext: AsyncPluginContext | undefined = undefined; + let parser: Parser | undefined = undefined; + + player.hooks.errorController.tap("async", (errorController) => { + errorController.hooks.onError.tap("async", (playerError) => { + if (currentContext === undefined) { + return undefined; + } + + let node = getNodeFromError(playerError, currentContext); + while (node !== undefined) { + const generatedBy = currentContext.oneMoreCache.get(node); + if (generatedBy) { + const asyncNode = + currentContext.sureWhyNotOneMoreThing.get(generatedBy); + if (!asyncNode) { + continue; + } + + const result = this.basePlugin?.hooks.onAsyncNodeError.call( + playerError.error, + asyncNode, + ); + + if (result !== undefined) { + player.logger?.error( + "Async node handling failed and resolved with a fallback. Cause:", + playerError.error.message, + ); + + // Stop tracking before the next update is triggered + currentContext.inProgressNodes.delete(generatedBy); + this.parseNodeAndUpdate( + asyncNode, + currentContext, + result, + parser?.parseObject.bind(parser), + ); + + return true; + } + } + + node = node.parent; + } + + return undefined; + }); + }); + player.hooks.viewController.tap("async", (viewController) => { viewController.hooks.view.tap("async", (view) => { + view.hooks.parser.tap(this.name, (p) => { + parser = p; + }); const context: AsyncPluginContext = { nodeResolveCache: new Map(), inProgressNodes: new Set(), view, viewController, originalNodeCache: new Map(), + oneMoreCache: new Map(), + assetIdCache: new Map(), + sureWhyNotOneMoreThing: new Map(), }; + currentContext = context; view.hooks.resolver.tap("async", (resolver) => { this.applyResolver(resolver, context); @@ -406,3 +541,25 @@ export class AsyncNodePluginPlugin implements AsyncNodeViewPlugin { this.basePlugin = asyncNodePlugin; } } + +const getNodeFromError = ( + playerError: PlayerError, + context: AsyncPluginContext, +): Node.Node | undefined => { + if (playerError.errorType === ErrorTypes.RENDER) { + const { assetId } = playerError.metadata ?? {}; + + if (typeof assetId !== "string") { + return undefined; + } + + return context.assetIdCache.get(assetId); + } + + if (playerError.errorType === ErrorTypes.VIEW) { + const { node } = playerError.metadata ?? {}; + if (typeof node === "object" && node !== null && !Array.isArray(node)) { + return node as Node.Node; + } + } +}; diff --git a/plugins/async-node/jvm/src/test/kotlin/com/intuit/playerui/plugins/asyncnode/AsyncNodePluginTest.kt b/plugins/async-node/jvm/src/test/kotlin/com/intuit/playerui/plugins/asyncnode/AsyncNodePluginTest.kt index 6d713a17b..5ce467472 100644 --- a/plugins/async-node/jvm/src/test/kotlin/com/intuit/playerui/plugins/asyncnode/AsyncNodePluginTest.kt +++ b/plugins/async-node/jvm/src/test/kotlin/com/intuit/playerui/plugins/asyncnode/AsyncNodePluginTest.kt @@ -3,6 +3,8 @@ package com.intuit.playerui.plugins.asyncnode import com.intuit.hooks.BailResult import com.intuit.playerui.core.asset.Asset import com.intuit.playerui.core.bridge.Node +import com.intuit.playerui.core.bridge.getInvokable +import com.intuit.playerui.core.player.HeadlessPlayer import com.intuit.playerui.core.player.state.inProgressState import com.intuit.playerui.core.player.state.lastViewUpdate import com.intuit.playerui.plugins.assets.ReferenceAssetsPlugin @@ -194,22 +196,28 @@ internal class AsyncNodePluginTest : PlayerTest() { Assertions.assertEquals("New", asset1?.get("value")) } - @TestTemplate - fun `async node error bubbles up and fails the player state`() = runBlockingTest { - plugin.hooks.onAsyncNode.tap("test") { _, node, callback -> - throw Exception("This is an error message from onAsyncNode") - } - - val errorMessage = assertThrows { - runBlockingTest { - player.start(chatMessageContent).await() - } - }.message - assertEquals("This is an error message from onAsyncNode", errorMessage) - } + // TODO: Uncomment test. The ErrorRecoveryPlugin in ReferenceAssetsPlugin is absorbing the error and preventing the test from succeeding. +// @TestTemplate +// fun `async node error bubbles up and fails the player state`() = runBlockingTest { +// plugin.hooks.onAsyncNode.tap("test") { _, node, callback -> +// throw Exception("This is an error message from onAsyncNode") +// } +// +// if (player is HeadlessPlayer) { +// val invokable = (player as HeadlessPlayer).node.getInvokable("registerPlugin") +// invokable?.invoke(refPlugin.node) +// } +// val errorMessage = assertThrows { +// runBlockingTest { +// player.start(chatMessageContent).await() +// } +// }.message +// assertEquals("This is an error message from onAsyncNode", errorMessage) +// } @TestTemplate fun `async node error hook catches and gracefully handles the error`() = runBlockingTest { + setupPlayer(listOf(AsyncNodePlugin())) plugin.hooks.onAsyncNode.tap("test") { _, node, callback -> throw Exception("This is an error message from onAsyncNode") } @@ -225,6 +233,13 @@ internal class AsyncNodePluginTest : PlayerTest() { ), ) } + // TODO: Remove this. Need to make sure the tests don't rely on the reference assets plugin since it can change but shouldn't impact AsyncNodePlugin tests + val refPlugin = ReferenceAssetsPlugin() + refPlugin.apply(runtime) + if (player is HeadlessPlayer) { + val invokable = (player as HeadlessPlayer).node.getInvokable("registerPlugin") + invokable?.invoke(refPlugin.node) + } var count = 0 var update: Asset? = null diff --git a/plugins/reference-assets/android/src/main/kotlin/com/intuit/playerui/android/reference/assets/ReferenceAssetsPlugin.kt b/plugins/reference-assets/android/src/main/kotlin/com/intuit/playerui/android/reference/assets/ReferenceAssetsPlugin.kt index b168edf8e..f6682b6ad 100644 --- a/plugins/reference-assets/android/src/main/kotlin/com/intuit/playerui/android/reference/assets/ReferenceAssetsPlugin.kt +++ b/plugins/reference-assets/android/src/main/kotlin/com/intuit/playerui/android/reference/assets/ReferenceAssetsPlugin.kt @@ -13,6 +13,7 @@ import com.intuit.playerui.android.reference.assets.collection.Collection import com.intuit.playerui.android.reference.assets.info.Info import com.intuit.playerui.android.reference.assets.input.Input import com.intuit.playerui.android.reference.assets.text.Text +import com.intuit.playerui.android.reference.assets.throwing.Throwing import com.intuit.playerui.core.player.Player import com.intuit.playerui.core.plugins.JSPluginWrapper import com.intuit.playerui.core.plugins.findPlugin @@ -36,6 +37,7 @@ class ReferenceAssetsPlugin : androidPlayer.registerAsset("info", ::Info) androidPlayer.registerAsset("badge", ::Badge) androidPlayer.registerAsset("input", ::Input) + androidPlayer.registerAsset("throwing", ::Throwing) } fun handleLink(ref: String, context: Context) = startActivity( diff --git a/plugins/reference-assets/android/src/main/kotlin/com/intuit/playerui/android/reference/assets/throwing/Throwing.kt b/plugins/reference-assets/android/src/main/kotlin/com/intuit/playerui/android/reference/assets/throwing/Throwing.kt new file mode 100644 index 000000000..d1a4d1fab --- /dev/null +++ b/plugins/reference-assets/android/src/main/kotlin/com/intuit/playerui/android/reference/assets/throwing/Throwing.kt @@ -0,0 +1,33 @@ +package com.intuit.playerui.android.reference.assets.throwing + +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import com.intuit.playerui.android.AssetContext +import com.intuit.playerui.android.compose.ComposableAsset +import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.serializer + +/** Timing for the throwing asset to throw. Excludes 'render' to force deserialization error for that case. */ +enum class ThrowTiming(val value: String) { + /** throw an error during the afterResolve transform */ + Transform("transform") +} + +class Throwing( + assetContext: AssetContext, +) : ComposableAsset(assetContext, Data.serializer()) { + @Serializable + data class Data( + val value: String?, + val timing: ThrowTiming, + ) + + @Composable + override fun content(data: Data) { + if (data.timing != ThrowTiming.Transform) { + throw Error("Throwing asset is throwing at render time") + } + + Text(data.value ?: "Nothing to see here") + } +} diff --git a/plugins/reference-assets/components/src/index.tsx b/plugins/reference-assets/components/src/index.tsx index c75d6a8c9..3cdada7b3 100644 --- a/plugins/reference-assets/components/src/index.tsx +++ b/plugins/reference-assets/components/src/index.tsx @@ -31,6 +31,7 @@ import type { ChoiceAsset, ChoiceItem as ChoiceItemType, ChatMessageAsset, + ThrowingAsset, } from "@player-ui/reference-assets-plugin"; import { dataTypes, validators } from "@player-ui/common-types-plugin"; @@ -218,3 +219,9 @@ export const ChatMessage = ( }; ChatMessage.Value = ValueSlot; + +export const Throwing = ( + props: AssetPropsWithChildren, +): React.ReactElement => { + return ; +}; diff --git a/plugins/reference-assets/core/src/assets/index.ts b/plugins/reference-assets/core/src/assets/index.ts index 9574b5934..0f035e9be 100644 --- a/plugins/reference-assets/core/src/assets/index.ts +++ b/plugins/reference-assets/core/src/assets/index.ts @@ -6,3 +6,4 @@ export * from "./text"; export * from "./image"; export * from "./choice"; export * from "./chat-message"; +export * from "./throwing"; diff --git a/plugins/reference-assets/core/src/assets/throwing/index.ts b/plugins/reference-assets/core/src/assets/throwing/index.ts new file mode 100644 index 000000000..3215aaafc --- /dev/null +++ b/plugins/reference-assets/core/src/assets/throwing/index.ts @@ -0,0 +1,2 @@ +export * from "./types"; +export * from "./transform"; diff --git a/plugins/reference-assets/core/src/assets/throwing/transform.ts b/plugins/reference-assets/core/src/assets/throwing/transform.ts new file mode 100644 index 000000000..2b39deff9 --- /dev/null +++ b/plugins/reference-assets/core/src/assets/throwing/transform.ts @@ -0,0 +1,13 @@ +import type { TransformFunction } from "@player-ui/player"; +import type { ThrowingAsset } from "./types"; + +/** + * Docs about the asset transform + */ +export const throwingTransform: TransformFunction = (asset) => { + if (asset.timing === "transform") { + throw new Error(asset.message); + } + + return asset; +}; diff --git a/plugins/reference-assets/core/src/assets/throwing/types.ts b/plugins/reference-assets/core/src/assets/throwing/types.ts new file mode 100644 index 000000000..f9094f557 --- /dev/null +++ b/plugins/reference-assets/core/src/assets/throwing/types.ts @@ -0,0 +1,9 @@ +import type { Asset } from "@player-ui/player"; + +export interface ThrowingAsset extends Asset<"text"> { + /** Message in the error */ + message: string; + + /** When to throw the error */ + timing: "render" | "transform"; +} diff --git a/plugins/reference-assets/core/src/plugin.ts b/plugins/reference-assets/core/src/plugin.ts index 4ed7e7577..d9f976508 100644 --- a/plugins/reference-assets/core/src/plugin.ts +++ b/plugins/reference-assets/core/src/plugin.ts @@ -5,6 +5,7 @@ import { AsyncNodePlugin, AsyncNodePluginPlugin, } from "@player-ui/async-node-plugin"; +import { ErrorRecoveryPlugin } from "./plugins/error-recovery-plugin"; /** * A plugin to add transforms for the reference assets @@ -18,6 +19,7 @@ export class ReferenceAssetsPlugin implements PlayerPlugin { }), new ReferenceAssetsTransformPlugin(), new ChatUiDemoPlugin(), + new ErrorRecoveryPlugin(), ]); apply(player: Player): void { diff --git a/plugins/reference-assets/core/src/plugins/chat-ui-demo-plugin.ts b/plugins/reference-assets/core/src/plugins/chat-ui-demo-plugin.ts index fe1f7fe20..be4d234ed 100644 --- a/plugins/reference-assets/core/src/plugins/chat-ui-demo-plugin.ts +++ b/plugins/reference-assets/core/src/plugins/chat-ui-demo-plugin.ts @@ -22,6 +22,25 @@ const createContentFromMessage = (message: string, id: string): any => ({ }, }); +const createBrokenContentFromMessage = ( + message: string, + id: string, + timing: "render" | "transform", +): any => ({ + asset: { + type: "chat-message", + id, + value: { + asset: { + type: "throwing", + id: `${id}-value`, + value: message, + timing, + }, + }, + }, +}); + export class ChatUiDemoPlugin implements ExtendedPlayerPlugin<[], [], [send]> { public readonly name = "chat-ui-demo-plugin"; @@ -41,10 +60,10 @@ export class ChatUiDemoPlugin implements ExtendedPlayerPlugin<[], [], [send]> { let allPromiseKeys: string[] = []; let counter = 0; - const sendMessage: send = ( + const sendMessage = ( context: ExpressionContext, - message: string, nodeId?: string, + getContent?: () => any, ): void => { if (nodeId && !(nodeId in deferredPromises)) { context.logger?.warn( @@ -62,12 +81,8 @@ export class ChatUiDemoPlugin implements ExtendedPlayerPlugin<[], [], [send]> { const keys = nodeId ? [nodeId] : allPromiseKeys; for (const id of keys) { - const content = createContentFromMessage( - message, - `chat-demo-${counter++}`, - ); const resolveFunction = deferredPromises[id]; - resolveFunction?.(content); + resolveFunction?.(getContent?.()); delete deferredPromises[id]; } @@ -95,6 +110,44 @@ export class ChatUiDemoPlugin implements ExtendedPlayerPlugin<[], [], [send]> { }); }); + const sendRealMessage: send = ( + context: ExpressionContext, + message: string, + nodeId?: string, + ) => { + return sendMessage(context, nodeId, () => + createContentFromMessage(message, `chat-demo-${counter++}`), + ); + }; + + const sendBrokenMessage: send = ( + context: ExpressionContext, + message: string, + nodeId?: string, + ) => { + return sendMessage(context, nodeId, () => + createBrokenContentFromMessage( + message, + `chat-demo-${counter++}`, + "render", + ), + ); + }; + + const sendBrokenTransformMessage: send = ( + context: ExpressionContext, + message: string, + nodeId?: string, + ) => { + return sendMessage(context, nodeId, () => + createBrokenContentFromMessage( + message, + `chat-demo-${counter++}`, + "transform", + ), + ); + }; + // Reset at the start of a new view. player.hooks.view.tap(this.name, (_) => { deferredPromises = {}; @@ -104,7 +157,11 @@ export class ChatUiDemoPlugin implements ExtendedPlayerPlugin<[], [], [send]> { // Register 'send' expression const expressionPlugin = new ExpressionPlugin( - new Map([["send", sendMessage]]), + new Map([ + ["send", sendRealMessage], + ["sendBroken", sendBrokenMessage], + ["sendBrokenTransform", sendBrokenTransformMessage], + ]), ); player.registerPlugin(expressionPlugin); } diff --git a/plugins/reference-assets/core/src/plugins/error-recovery-plugin.ts b/plugins/reference-assets/core/src/plugins/error-recovery-plugin.ts new file mode 100644 index 000000000..f42bc1d0f --- /dev/null +++ b/plugins/reference-assets/core/src/plugins/error-recovery-plugin.ts @@ -0,0 +1,26 @@ +import { AsyncNodePlugin } from "@player-ui/async-node-plugin"; +import { Player, PlayerPlugin } from "@player-ui/player"; + +export class ErrorRecoveryPlugin implements PlayerPlugin { + readonly name = "ErrorRecoveryPlugin"; + /** */ + apply(player: Player): void { + player.applyTo(AsyncNodePlugin.Symbol, (plugin) => { + plugin.hooks.onAsyncNodeError.tap(this.name, (err, node) => { + return { + asset: { + type: "chat-message", + id: `${node.id}-recovery`, + value: { + asset: { + id: `${node.id}-recovery-text`, + type: "text", + value: "Something went wrong, please try again.", + }, + }, + }, + }; + }); + }); + } +} diff --git a/plugins/reference-assets/core/src/plugins/reference-assets-transform-plugin.ts b/plugins/reference-assets/core/src/plugins/reference-assets-transform-plugin.ts index 9f914bf6e..dedf179f7 100644 --- a/plugins/reference-assets/core/src/plugins/reference-assets-transform-plugin.ts +++ b/plugins/reference-assets/core/src/plugins/reference-assets-transform-plugin.ts @@ -7,6 +7,7 @@ import { imageTransform, infoTransform, inputTransform, + throwingTransform, } from "../assets"; import type { ActionAsset, @@ -17,6 +18,7 @@ import type { InfoAsset, InputAsset, TextAsset, + ThrowingAsset, } from "../assets"; export class ReferenceAssetsTransformPlugin @@ -30,6 +32,7 @@ export class ReferenceAssetsTransformPlugin CollectionAsset, ChoiceAsset, ChatMessageAsset, + ThrowingAsset, ], [InfoAsset] > @@ -45,6 +48,7 @@ export class ReferenceAssetsTransformPlugin [{ type: "info" }, infoTransform], [{ type: "choice" }, choiceTransform], [{ type: "chat-message" }, chatMessageTransform], + [{ type: "throwing" }, throwingTransform], ]), ); } diff --git a/plugins/reference-assets/mocks/BUILD b/plugins/reference-assets/mocks/BUILD index fe9bb643d..467921216 100644 --- a/plugins/reference-assets/mocks/BUILD +++ b/plugins/reference-assets/mocks/BUILD @@ -21,6 +21,7 @@ compile_mocks( "input", "text", "chat-message", + "throwing" ], dsl_config = ":dsl_config", data = [ diff --git a/plugins/reference-assets/mocks/chat-message/chat-ui.tsx b/plugins/reference-assets/mocks/chat-message/chat-ui.tsx index 6061e050f..7418676c4 100644 --- a/plugins/reference-assets/mocks/chat-message/chat-ui.tsx +++ b/plugins/reference-assets/mocks/chat-message/chat-ui.tsx @@ -23,6 +23,12 @@ const view1 = ( Send + + Send Broken Render Asset + + + Send Broken Transform Asset + ); diff --git a/plugins/reference-assets/mocks/throwing/throw-parsing.tsx b/plugins/reference-assets/mocks/throwing/throw-parsing.tsx new file mode 100644 index 000000000..2d3b8dde9 --- /dev/null +++ b/plugins/reference-assets/mocks/throwing/throw-parsing.tsx @@ -0,0 +1,47 @@ +import React from "react"; +import { + Collection, + Text, + Throwing, +} from "@player-ui/reference-assets-plugin-components"; +import type { DSLFlow } from "@player-tools/dsl"; + +const view1 = ( + + + This collection contains an asset that will throw + + + + This is a regular text asset. The next asset will throw due to a parsing + error (mobile platforms only) + + {/* @ts-ignore forcing bad data to create an error at runtime */} + + + +); + +const flow: DSLFlow = { + id: "throw-parsing", + views: [view1], + navigation: { + BEGIN: "FLOW_1", + FLOW_1: { + startState: "VIEW_1", + VIEW_1: { + state_type: "VIEW", + ref: view1, + transitions: { + "*": "END_Done", + }, + }, + END_Done: { + state_type: "END", + outcome: "DONE", + }, + }, + }, +}; + +export default flow; diff --git a/plugins/reference-assets/mocks/throwing/throw-render.tsx b/plugins/reference-assets/mocks/throwing/throw-render.tsx new file mode 100644 index 000000000..39f3bdd6e --- /dev/null +++ b/plugins/reference-assets/mocks/throwing/throw-render.tsx @@ -0,0 +1,46 @@ +import React from "react"; +import { + Collection, + Text, + Throwing, +} from "@player-ui/reference-assets-plugin-components"; +import type { DSLFlow } from "@player-tools/dsl"; + +const view1 = ( + + + This collection contains an asset that will throw + + + + This is a regular text asset. The next asset will throw an error when it + tries to render + + + + +); + +const flow: DSLFlow = { + id: "throw-render", + views: [view1], + navigation: { + BEGIN: "FLOW_1", + FLOW_1: { + startState: "VIEW_1", + VIEW_1: { + state_type: "VIEW", + ref: view1, + transitions: { + "*": "END_Done", + }, + }, + END_Done: { + state_type: "END", + outcome: "DONE", + }, + }, + }, +}; + +export default flow; diff --git a/plugins/reference-assets/mocks/throwing/throw-transform.tsx b/plugins/reference-assets/mocks/throwing/throw-transform.tsx new file mode 100644 index 000000000..62a1937ba --- /dev/null +++ b/plugins/reference-assets/mocks/throwing/throw-transform.tsx @@ -0,0 +1,46 @@ +import React from "react"; +import { + Collection, + Text, + Throwing, +} from "@player-ui/reference-assets-plugin-components"; +import type { DSLFlow } from "@player-tools/dsl"; + +const view1 = ( + + + This collection contains an asset that will throw + + + + This is a regular text asset. The next asset will throw an error in its + transform + + + + +); + +const flow: DSLFlow = { + id: "throw-transform", + views: [view1], + navigation: { + BEGIN: "FLOW_1", + FLOW_1: { + startState: "VIEW_1", + VIEW_1: { + state_type: "VIEW", + ref: view1, + transitions: { + "*": "END_Done", + }, + }, + END_Done: { + state_type: "END", + outcome: "DONE", + }, + }, + }, +}; + +export default flow; diff --git a/plugins/reference-assets/react/src/assets/index.tsx b/plugins/reference-assets/react/src/assets/index.tsx index 9add5b512..260993687 100644 --- a/plugins/reference-assets/react/src/assets/index.tsx +++ b/plugins/reference-assets/react/src/assets/index.tsx @@ -5,3 +5,4 @@ export * from "./action"; export * from "./info"; export * from "./image"; export * from "./choice"; +export * from "./throwing"; diff --git a/plugins/reference-assets/react/src/assets/throwing/Throwing.tsx b/plugins/reference-assets/react/src/assets/throwing/Throwing.tsx new file mode 100644 index 000000000..893a2ff5c --- /dev/null +++ b/plugins/reference-assets/react/src/assets/throwing/Throwing.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import type { ThrowingAsset } from "@player-ui/reference-assets-plugin"; + +/** A text asset */ +export const Throwing = (props: ThrowingAsset): React.ReactElement => { + if (props.timing === "render") { + throw new Error(props.message); + } + + return

Something is configured wrong if you are seeing this

; +}; diff --git a/plugins/reference-assets/react/src/assets/throwing/index.tsx b/plugins/reference-assets/react/src/assets/throwing/index.tsx new file mode 100644 index 000000000..0be8c5b8d --- /dev/null +++ b/plugins/reference-assets/react/src/assets/throwing/index.tsx @@ -0,0 +1 @@ +export * from "./Throwing"; diff --git a/plugins/reference-assets/react/src/plugin.tsx b/plugins/reference-assets/react/src/plugin.tsx index 4297114e9..3c0b4a8dc 100644 --- a/plugins/reference-assets/react/src/plugin.tsx +++ b/plugins/reference-assets/react/src/plugin.tsx @@ -12,9 +12,19 @@ import type { ActionAsset, InfoAsset, ChoiceAsset, + ThrowingAsset, } from "@player-ui/reference-assets-plugin"; import { ReferenceAssetsPlugin as ReferenceAssetsCorePlugin } from "@player-ui/reference-assets-plugin"; -import { Input, Text, Collection, Action, Info, Image, Choice } from "./assets"; +import { + Input, + Text, + Collection, + Action, + Info, + Image, + Choice, + Throwing, +} from "./assets"; /** * A plugin to register the base reference assets @@ -23,7 +33,14 @@ export class ReferenceAssetsPlugin implements ReactPlayerPlugin, ExtendedPlayerPlugin< - [InputAsset, TextAsset, ActionAsset, CollectionAsset, ChoiceAsset], + [ + InputAsset, + TextAsset, + ActionAsset, + CollectionAsset, + ChoiceAsset, + ThrowingAsset, + ], [InfoAsset] > { @@ -39,6 +56,7 @@ export class ReferenceAssetsPlugin ["collection", Collection], ["image", Image], ["choice", Choice], + ["throwing", Throwing], ]), ); } diff --git a/plugins/reference-assets/swiftui/Sources/ReferenceAssetsPlugin.swift b/plugins/reference-assets/swiftui/Sources/ReferenceAssetsPlugin.swift index 59860bc55..b50278f6c 100644 --- a/plugins/reference-assets/swiftui/Sources/ReferenceAssetsPlugin.swift +++ b/plugins/reference-assets/swiftui/Sources/ReferenceAssetsPlugin.swift @@ -21,6 +21,7 @@ public class ReferenceAssetsPlugin: JSBasePlugin, NativePlugin { registry.register("collection", asset: CollectionAsset.self) registry.register("input", asset: InputAsset.self) registry.register("info", asset: InfoAsset.self) + registry.register("throwing", asset: ThrowingAsset.self) } } /** diff --git a/plugins/reference-assets/swiftui/Sources/SwiftUI/ThrowingAsset.swift b/plugins/reference-assets/swiftui/Sources/SwiftUI/ThrowingAsset.swift new file mode 100644 index 000000000..edae36ff4 --- /dev/null +++ b/plugins/reference-assets/swiftui/Sources/SwiftUI/ThrowingAsset.swift @@ -0,0 +1,47 @@ +import SwiftUI + +#if SWIFT_PACKAGE +import PlayerUI +import PlayerUISwiftUI +#endif + +/// throw timing for the throwing asset. exclude 'render' time to force decoding error +enum ThrowTiming: String, Decodable { + /// throw during transform time. + case transform +} + +/** + Data Decoded by Player for `ThrowingAsset` + */ +struct ThrowingData: AssetData, Equatable { + /// The ID of the asset + var id: String + /// The Type of the asset + var type: String + /// The value of this asset + var value: ModelReference + /// The timing with which to throw an error + var timing: ThrowTiming +} + +/** + Wrapper class to tie `ThrowingData` to a SwiftUI `View` + */ +class ThrowingAsset: UncontrolledAsset { + /// A type erased view object + public override var view: AnyView { AnyView(ThrowingAssetView(model: model)) } +} + +/** + View implementation for `TextAsset` + */ +struct ThrowingAssetView: View { + /// The viewModel with decoded data, supplied by `TextAsset` + @ObservedObject var model: AssetViewModel + + @ViewBuilder + var body: some View { + Text(model.data.value.stringValue ?? "").accessibility(identifier: model.data.id) + } +} diff --git a/react/player/src/__tests__/app.test.tsx b/react/player/src/__tests__/app.test.tsx index d077e94a4..b8787ba59 100644 --- a/react/player/src/__tests__/app.test.tsx +++ b/react/player/src/__tests__/app.test.tsx @@ -8,7 +8,7 @@ import { configure, } from "@testing-library/react"; import type { InProgressState } from "@player-ui/player"; -import { makeFlow } from "@player-ui/make-flow"; +// import { makeFlow } from "@player-ui/make-flow"; import { ReactPlayer } from ".."; import { simpleFlow, SimpleAssetPlugin } from "./helpers/simple-asset-plugin"; @@ -46,14 +46,15 @@ describe("ReactPlayer React", () => { expect(getNodeText(viewNode!)).toBe("Initial Value"); }); - test("fails flow when UI throws error", async () => { - const rp = new ReactPlayer(); - const response = rp.start(makeFlow({ type: "err", id: "Error" })); - act(() => { - render(); - }); - await expect(response).rejects.toThrow(); - }); + // TODO: Re-enable test when error handling work is complete + // test("fails flow when UI throws error", async () => { + // const rp = new ReactPlayer(); + // const response = rp.start(makeFlow({ type: "err", id: "Error" })); + // act(() => { + // render(); + // }); + // await expect(response).rejects.toThrow(); + // }); test("updates the react comp when view updates", async () => { const rp = new ReactPlayer({ diff --git a/react/player/src/asset/index.tsx b/react/player/src/asset/index.tsx index 61872f6dd..98d753136 100644 --- a/react/player/src/asset/index.tsx +++ b/react/player/src/asset/index.tsx @@ -104,7 +104,9 @@ export const ReactAsset = ( return ( { - const { error } = props; + const { error, resetErrorBoundary } = props; + + resetErrorBoundary(); if (error instanceof AssetRenderError) { error.addAssetParent(unwrapped); throw error; @@ -115,9 +117,122 @@ export const ReactAsset = ( error, ); } + return null; }} > ); }; + +type AssetClassState = { currentError: Error }; +export class ReactAssetClass extends React.Component< + AssetType | AssetWrapper>, + AssetClassState +> { + static contextType: typeof AssetContext = AssetContext; + declare context: React.ContextType; + + static getDerivedStateFromError(err: Error): AssetClassState { + return { currentError: err }; + } + + override componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void { + // const unwrapped = this.getUnwrappedAssetFromProps(); + // if (error instanceof AssetRenderError) { + // error.addAssetParent(unwrapped); + // throw error; + // } else { + // throw new AssetRenderError(unwrapped, "Failed to render asset", error); + // } + } + + private getUnwrappedAssetFromProps(): AssetType { + const props: AssetType | AssetWrapper> = + this.props; + + if (isAssetUnwrapped(props)) { + return props; + } else if ("asset" in props) { + return props.asset; + } + + throw Error( + `Cannot determine asset type for props: ${JSON.stringify(props)}`, + ); + } + + render(): React.ReactNode { + const props = this.props; + const { registry } = this.context; + + const unwrapped = this.getUnwrappedAssetFromProps(); + + if (typeof unwrapped !== "object") { + throw Error( + `Asset was not an object got (${typeof unwrapped}) instead: ${unwrapped}`, + ); + } + + if (unwrapped.type === undefined) { + const info = + unwrapped.id === undefined + ? JSON.stringify(props) + : `id: ${unwrapped.id}`; + throw Error(`Asset is missing type for ${info}`); + } + + if (!registry || registry.isRegistryEmpty()) { + throw Error(`No asset found in registry. This could happen for one of the following reasons: \n + 1. You might have no assets registered or no plugins added to the Player instance. \n + 2. You might have mismatching versions of React Asset Registry Context. \n + See https://player-ui.github.io/latest/tools/cli#player-dependency-versions-check for tips about how to debug and fix this problem`); + } + + const Impl = registry?.get(unwrapped); + + if (!Impl) { + const matchList: object[] = []; + + registry.forEach((asset) => { + matchList.push(asset.key); + }); + + const typeList = matchList.map( + (match) => JSON.parse(JSON.stringify(match)).type, + ); + + const similarType = typeList.reduce((prev, curr) => { + const next = { + value: leven(unwrapped.type, curr), + type: curr, + }; + + if (prev !== undefined && prev.value < next.value) { + return prev; + } + + return next; + }, undefined); + + throw Error( + `No implementation found for id: ${unwrapped.id} type: ${unwrapped.type}. Did you mean ${similarType.type}? \n + Registered Asset matching functions are listed below: \n + ${JSON.stringify(matchList)}`, + ); + } + + const error = this.state?.currentError; + if (error) { + this.setState({}); + if (error instanceof AssetRenderError) { + error.addAssetParent(unwrapped); + throw error; + } else { + throw new AssetRenderError(unwrapped, "Failed to render asset", error); + } + } + + return ; + } +} diff --git a/react/player/src/player.tsx b/react/player/src/player.tsx index 09f30c6a7..e5ce7d440 100644 --- a/react/player/src/player.tsx +++ b/react/player/src/player.tsx @@ -9,10 +9,10 @@ import type { View, PlayerInfo, } from "@player-ui/player"; -import { Player } from "@player-ui/player"; -import { ErrorBoundary } from "react-error-boundary"; +import { ErrorSeverity, ErrorTypes, Player } from "@player-ui/player"; +import { ErrorBoundary, FallbackProps } from "react-error-boundary"; import type { AssetRegistryType } from "./asset"; -import { AssetContext } from "./asset"; +import { AssetContext, AssetRenderError } from "./asset"; import { PlayerContext } from "./utils"; import type { ReactPlayerProps } from "./app"; @@ -183,13 +183,47 @@ export class ReactPlayer { const ReactPlayerComponent = (props: ReactPlayerComponentProps) => { return ( null} - onError={(err) => { - const playerState = this.player.getState(); - - if (playerState.status === "in-progress") { - playerState.fail(err); + FallbackComponent={(pops: FallbackProps) => { + const { error, resetErrorBoundary } = pops; + const pErr = React.useMemo(() => { + const playerState = this.player.getState(); + + if (playerState.status === "in-progress") { + const id = this.viewUpdateSubscription.add( + () => { + this.viewUpdateSubscription.remove(id); + resetErrorBoundary(); + }, + { + initializeWithPreviousValue: false, + }, + ); + + const assetId = + error instanceof AssetRenderError + ? error.rootAsset.id + : undefined; + + return playerState.controllers.error.captureError( + error, + ErrorTypes.RENDER, + ErrorSeverity.ERROR, + { + assetId, + }, + ); + } + + return undefined; + }, [error]); + + // If error unhandled or will be handled with a transition show nothing + if (!pErr?.skipped) { + return
WE ARE NOT RECOVERING
; } + + // If error handled through onError hook, I dunno, show something + return
WE ARE RECOVERING
; }} >