From 3a926ea1d167ec69dd49768546e9532daddcdd10 Mon Sep 17 00:00:00 2001 From: Taewoon Kim Date: Sun, 25 Oct 2026 17:51:46 +0900 Subject: [PATCH] Native tests: skips come from explicit collection-time entries and NotOnNativeYet, never from failure text The report hook turned a failed native test into a skip when its exception text contained one of ~15 generic markers ("assert (None is not None)", "KeyError: 'flush'", "DID NOT RAISE KeyboardInterrupt", "cause is ", "getClass", ...) or when its name was on a list. Those texts are also what genuine bugs look like, and the hook hid three real regressions in PR #522. Now only an explicit signal skips a test: NotOnNativeYet raised by the native code (NOTYET), or an entry in NATIVE_NA_JVM_TESTS keyed by file::[Class::]function with a reason (NA-JVM, skipped at collection). Of the 154 items the text and name matching hid, 73 now run and pass on native (60 resultset read errors, 7 graph batch, 6 sparse vector), 81 are listed as NA-JVM with a reason, and one real bug is pinned as xfail(strict): BACKLOG-bindings.md P-04. Also found and fixed: to_java_int_array and to_java_byte_array had no native branch and raised JVMNotRunning on the native wheel (to_java_float_array has one); six tests that were listed as NA-JVM by name now run on native. Co-Authored-By: Claude Sonnet 5.5 --- .../python/src/arcadedb_embedded/vector.py | 41 +++- bindings/python/tests/conftest.py | 184 ++++++++++-------- bindings/python/tests/test_graph_batch.py | 32 ++- .../tests/test_resultset_read_errors.py | 5 + .../tests/test_sparse_quantization_compact.py | 7 +- bindings/python/tests/test_vector_sql.py | 5 +- 6 files changed, 188 insertions(+), 86 deletions(-) diff --git a/bindings/python/src/arcadedb_embedded/vector.py b/bindings/python/src/arcadedb_embedded/vector.py index 4cb980479f9..f60a112eb8c 100644 --- a/bindings/python/src/arcadedb_embedded/vector.py +++ b/bindings/python/src/arcadedb_embedded/vector.py @@ -92,8 +92,24 @@ def to_java_int_array(vector): vector: Array-like object containing integer values Returns: - Java int array + Java int array (a NumPy int32 array on the native backend, which has no JVM to build one in: like + :func:`to_java_float_array`, it binds as a SQL parameter in place of the Java array) """ + if _native_enabled(): + values = ( + vector if isinstance(vector, _np.ndarray) else _np.asarray(list(vector)) + ) + if values.size == 0: + return values.astype(_np.int32) + if values.dtype.kind not in "iu": + raise TypeError("to_java_int_array takes integer values") + bounds = _np.iinfo(_np.int32) + if values.min() < bounds.min or values.max() > bounds.max: + raise OverflowError( + "Cannot convert value to Java int: an element does not fit in 32 bits" + ) + return values.astype(_np.int32) + if _np is not None and isinstance(vector, _np.ndarray): if vector.dtype.kind in "iu" and vector.size: bounds = _np.iinfo(_np.int32) @@ -125,8 +141,29 @@ def to_java_byte_array(vector): vector: Array-like object containing byte values Returns: - Java byte array compatible with INT8-encoded ArcadeDB vector indexes + Java byte array compatible with INT8-encoded ArcadeDB vector indexes (a NumPy int8 array on the native + backend, which has no JVM to build one in) """ + if _native_enabled(): + if isinstance(vector, (bytes, bytearray, memoryview)): + return _np.frombuffer(bytes(vector), dtype=_np.int8).copy() + if ( + isinstance(vector, _np.ndarray) + and vector.dtype.kind in "iu" + and vector.dtype.itemsize == 1 + ): + return _np.ascontiguousarray(vector).view(_np.int8).copy() + native_bytes = [] + for value in vector.tolist() if isinstance(vector, _np.ndarray) else vector: + byte_value = int(value) + if byte_value < -128 or byte_value > 255: + raise ArcadeDBError( + "Byte vectors must contain values in the signed byte range " + "[-128, 127] or unsigned byte range [0, 255]" + ) + native_bytes.append(byte_value - 256 if byte_value > 127 else byte_value) + return _np.asarray(native_bytes, dtype=_np.int8) + try: import numpy as np diff --git a/bindings/python/tests/conftest.py b/bindings/python/tests/conftest.py index 77820a36136..778b16ed36c 100644 --- a/bindings/python/tests/conftest.py +++ b/bindings/python/tests/conftest.py @@ -54,85 +54,135 @@ collect_ignore.extend(NATIVE_NOT_APPLICABLE) -# Failure texts that mean the test is about the JPype bridge, not about database behaviour. -NATIVE_JVM_MARKERS = ( - "JVMNotRunning", - "without JVM", - "Java Virtual Machine is not running", - "'_java_db'", - "'_java_result'", - "bridge jar", - "'nextRows'", - "getClass", - "DID NOT RAISE KeyboardInterrupt", - "Cannot drop the database in transaction", # teardown after an injected KeyboardInterrupt - "assert (None is not None)", # fixtures that need a bridge class - "KeyError: 'flush'", - "KeyError: 'max_connections'", - "cause is ", # the Java exception as __cause__ - "findNeighborsFromVector", # the test calls the Java vector index directly - "to_java_rid", +# Tests that exercise the JVM itself, so the native backend (no JVM, no jars) has nothing to run. Skipped before they start, at +# collection time, with the reason (reported as "NA-JVM: "). The key is "::[::]": every parameter +# of the function, or one parameter id as in "test_x.py::test_y[java]". A test is listed only when it reaches into the JVM on purpose: +# it builds or reads a Java object (jpype.JClass, a Java array, db._java_db, _java_index, the bridge classes), counts JPype bridge +# crossings, or patches a hook of the JPype path. A failure text never puts a test on this list, and a failing test is never turned +# into a skip: a test whose behaviour native shares has to pass on native, and one that fails there is a bug to file (an +# xfail(strict=True) naming the BACKLOG-bindings.md row, so it turns red when fixed), not an entry here. +# A feature the native wheel lacks on purpose raises NotOnNativeYet from the native code, which pytest_runtest_makereport reports as NOTYET. +JAVA_CLASS = "builds a java.* object through JPype" +JAVA_ARRAY = "builds a Java array through JPype (jpype.JArray)" +JAVA_DB = "reads the Java database behind the wrapper (db._java_db)" +JAVA_INDEX = "reads the Java index behind the wrapper (_java_index: getClass, metadata)" +BRIDGE_COUNT = ( + "counts or intercepts the JPype bridge crossings (an internal of the JPype path)" ) - - -# Failure texts that mean the test needs a Java-object wrapper (Document, Vertex, Edge) or the exporter's Java path. -NATIVE_NOTYET_MARKERS = ( - "'NativeResult' object is not iterable", - "assert 'NativeResult' ==", -) - - -# Tests that count the JPype parameter conversions (an internal of the JPype path). -NATIVE_NA_TESTS = { - "test_non_scalars_keep_the_general_path", - "test_a_subclass_of_a_scalar_is_not_assumed_to_be_one", - "test_lsm_vector_search_looks_up_all_hits_in_one_bridge_call", # counts GraphCalls bridge crossings +NATIVE_NA_JVM_TESTS = { + # JVM start-up, signals and settings + "test_sigint.py::test_ctrl_c_raises_keyboard_interrupt_and_runs_cleanup[java]": "a Java call blocked in JPype's SIGINT handler (#179)", + "test_sigint.py::test_interrupt_true_keeps_the_jvm_handling_sigint": "start_jvm(interrupt=True): the JVM handles SIGINT", + "test_docs_examples.py::test_docs_installation_jvm_examples": "documents start_jvm() and jvm_kwargs", + "test_server_wire_protocols.py::test_the_host_reaches_exactly_the_listener_bind_settings": "reads the engine's GlobalConfiguration through the JVM", + "test_server_wire_protocols.py::test_wire_listeners_stay_on_loopback_by_default": "reads the server's GlobalConfiguration through the JVM", + "test_server_wire_protocols.py::test_host_applies_to_every_wire_listener": "reads the server's GlobalConfiguration through the JVM", + "test_server_wire_protocols.py::test_a_protocol_host_overrides_the_server_host_for_that_protocol_only": "reads the server's GlobalConfiguration through the JVM", + "test_sql_constraints_and_maintenance.py::test_backup_check_and_rebuild_index_statements": "sets GlobalConfiguration.SERVER_BACKUP_DIRECTORY through the JVM", + "test_vector_params_verification.py::TestVectorParams::test_jvm_heap_check": "reads java.lang.Runtime through JPype", + "test_vector_params_verification.py::TestVectorParams::test_wrapper_default_matches_engine_default": "reads the engine default through java.lang.String and GlobalConfiguration", + "test_vector_params_verification.py::TestVectorParams::test_omitted_max_connections_reaches_the_index": "reads the engine default through java.lang.String and GlobalConfiguration", + "test_vector_sql.py::TestVectorSearchOptionsSql::test_where_map_and_condition": "picks the expected behaviour by com.arcadedb.Constants.getRawVersion() through JPype", + "test_vector_sql.py::TestVectorSearchOptionsSql::test_where_combines_with_filter": "picks the expected behaviour by com.arcadedb.Constants.getRawVersion() through JPype", + # Java objects built or read by the test + "test_conversion_fixes.py::test_java_instants_convert_without_losing_microseconds": JAVA_CLASS, + "test_type_conversion.py::test_offset_datetime_conversion": JAVA_CLASS, + "test_type_conversion.py::test_scalar_list_crosses_as_one_array_with_the_same_types": "asserts the converted value is a java.util.ArrayList", + "test_type_conversion.py::TestPrimitiveArrayFormats::test_int_array": JAVA_ARRAY, + "test_type_conversion.py::TestPrimitiveArrayFormats::test_long_array": JAVA_ARRAY, + "test_percall_calls.py::test_float_array_conversion_gives_a_float_array": 'asserts the converted value is a Java float[] (getClass() == "[F")', + "test_typed_rows.py::test_java_values_sql_cannot_produce": JAVA_CLASS, + "test_typed_rows.py::test_value_python_cannot_hold_raises_as_before": JAVA_CLASS, + "test_typed_rows.py::test_object_array_raises_as_before": JAVA_ARRAY, + "test_typed_rows.py::test_iter_dicts_reads_one_row_at_a_time": "builds a Java InternalResultSet", + "test_typed_rows.py::test_vertex_edges_match_the_engine_iteration": "the oracle is the Java Vertex.getEdges iteration", + "test_typed_rows.py::test_vector_search_hits_match_the_per_hit_path": "the oracle is the Java vector index (findNeighborsFromVector)", + "test_typed_rows.py::test_a_batch_of_wide_rows_ends_at_a_few_megabytes": "calls the bridge's typed_rows.nextRows on the Java result set", + "test_typed_rows.py::test_the_batch_says_whether_the_result_set_is_drained": "calls the bridge's typed_rows.nextRows on the Java result set", + "test_graph_api.py::test_document_wrap_static_method": "wraps the Java object behind a result (_java_result)", + "test_legacy_temporal_implementations.py::test_the_engine_hands_back_the_configured_class_holding_the_utc_instant": JAVA_DB, + "test_graph_batch.py::test_graph_batch_leaves_the_callers_wal_setting_alone": JAVA_DB, + "test_transaction_config.py::test_set_wal_flush_is_database_wide": JAVA_DB, + "test_run_in_transaction_retry.py::test_contended_commits_spend_their_budget_before_failing": JAVA_DB, + # Java exceptions thrown and engine hooks set from the test + "test_run_in_transaction_retry.py::test_every_need_retry_exception_is_retried": "throws Java exceptions (com.arcadedb.exception.*) from the test", + "test_run_in_transaction_retry.py::test_the_budget_is_spent_before_the_conflict_reaches_the_caller": "throws Java exceptions (com.arcadedb.exception.*) from the test", + "test_run_in_transaction_retry.py::test_the_wait_the_refusing_side_asked_for_is_honored": "throws Java exceptions (com.arcadedb.exception.*) from the test", + "test_run_in_transaction_retry.py::test_the_wait_is_capped_by_retry_after_max_wait": "throws Java exceptions (com.arcadedb.exception.*) from the test", + "test_run_in_transaction_retry.py::test_a_block_that_committed_part_of_its_work_is_not_replayed": "throws a Java ConcurrentModificationException from the test (native: test_run_in_transaction_partial_commit.py)", + "test_graph_batch.py::test_graph_batch_outside_the_callers_transactions": "sets GraphBatch.TEST_BEFORE_VERTEX_COMMIT_HOOK, a Java static, through JPype", + "test_graph_batch.py::test_graph_batch_create_vertices_refuses_before_any_commit_attempt": "sets GraphBatch.TEST_BEFORE_VERTEX_COMMIT_HOOK, a Java static, through JPype", + "test_graph_batch.py::test_graph_batch_create_vertices_keyboard_interrupt_rolls_back": "patches GraphBatch._create_vertices_json_bulk, the JPype path's bulk call", + # parameter conversion and bridge crossings of the JPype path + "test_parameter_binding.py::test_each_parameter_shape_reaches_one_java_overload": "inspects the Java Database overloads through JPype", + "test_parameter_binding.py::test_async_parameters_reach_one_java_overload": "inspects the Java DatabaseAsyncExecutor overloads through JPype", + "test_parameter_binding.py::TestScalarParametersTakeTheShortPath::test_a_java_array_value_is_not_converted_and_binds_as_before": JAVA_ARRAY, + "test_parameter_binding.py::TestScalarParametersTakeTheShortPath::test_non_scalars_keep_the_general_path": "counts JPype parameter conversions", + "test_parameter_binding.py::TestScalarParametersTakeTheShortPath::test_a_subclass_of_a_scalar_is_not_assumed_to_be_one": "counts JPype parameter conversions", + "test_resultset.py::test_to_dict_one_crossing_matches_the_per_property_path": "needs the bridge jar's RowAccess class", + "test_resultset.py::TestSmallResultsCostOneBridgeCall::test_to_list_makes_one_call_for_a_short_result": BRIDGE_COUNT, + "test_resultset.py::TestSmallResultsCostOneBridgeCall::test_to_list_of_an_empty_result_makes_one_call": BRIDGE_COUNT, + "test_resultset.py::TestSmallResultsCostOneBridgeCall::test_to_json_list_makes_one_call_for_a_short_result": BRIDGE_COUNT, + "test_resultset.py::TestSmallResultsCostOneBridgeCall::test_a_full_batch_still_ends_on_the_next_call": BRIDGE_COUNT, + "test_resultset.py::TestSmallResultsCostOneBridgeCall::test_a_drained_set_reads_as_empty_and_is_not_an_error": BRIDGE_COUNT, + "test_resultset.py::TestSmallResultsCostOneBridgeCall::test_python_does_not_cross_the_bridge_to_close_a_drained_set": BRIDGE_COUNT, + "test_resultset.py::TestSmallResultsCostOneBridgeCall::test_the_bridge_closes_what_it_drains_and_only_that": BRIDGE_COUNT, + "test_vector.py::TestLSMVectorIndex::test_lsm_vector_search_looks_up_all_hits_in_one_bridge_call": BRIDGE_COUNT, + "test_vector.py::TestLSMVectorIndex::test_lsm_vector_search_uses_database_rid_conversion": "intercepts Database.to_java_rid, the JPype path's RID conversion", + # the Java index behind the wrapper + "test_vector.py::TestLSMVectorIndex::test_create_vector_index_with_pq_params": JAVA_INDEX, + "test_vector.py::TestLSMVectorIndex::test_create_vector_index_with_custom_id_property": JAVA_INDEX, + "test_vector.py::TestLSMVectorIndex::test_lsm_vector_search_approximate_product": JAVA_INDEX, + "test_vector.py::TestLSMVectorIndex::test_lsm_vector_search_approximate_typeindex": JAVA_INDEX, + **{ + f"test_vector_params_verification.py::TestVectorParams::{name}": JAVA_INDEX + for name in ( + "test_quantization_param", + "test_store_vectors_in_graph_param", + "test_encoding_param", + "test_add_hierarchy_param", + "test_per_index_cache_params", + "test_quantization_none", + "test_quantization_binary", + "test_quantization_product", + ) + }, } -# Tests that exercise the JVM itself, so the native backend (no JVM, no jars) has nothing to run. Skipped before they start, -# with the reason; a test whose behaviour native shares (Ctrl-C in a Python loop, the zone of to_json_list) is not listed. -NATIVE_NA_JVM_TESTS = { - "test_ctrl_c_raises_keyboard_interrupt_and_runs_cleanup[java]": "a Java call blocked in JPype's SIGINT handler (#179)", - "test_interrupt_true_keeps_the_jvm_handling_sigint": "start_jvm(interrupt=True): the JVM handles SIGINT", - "test_docs_installation_jvm_examples": "documents start_jvm() and jvm_kwargs", - "test_to_java_int_array_keeps_values_that_fit": "to_java_int_array builds a Java int[] (JPype)", - "test_to_java_int_array_refuses_values_beyond_32_bits_in_an_array": "to_java_int_array builds a Java int[] (JPype)", - "test_to_java_byte_array_accepts_bytes_like_fast_paths": "to_java_byte_array builds a Java byte[] (JPype)", - "test_to_java_int_array": "to_java_int_array builds a Java int[] (JPype)", - "test_to_java_int_array_accepts_numpy_directly": "to_java_int_array builds a Java int[] (JPype)", - "test_to_java_int_array_round_trips_through_a_sparse_vector": "to_java_int_array builds a Java int[] (JPype)", - "test_the_host_reaches_exactly_the_listener_bind_settings": "reads the engine's GlobalConfiguration through the JVM", -} +def _native(): + return os.environ.get("ARCADEDB_BACKEND", "jpype").lower() == "native" def pytest_collection_modifyitems(config, items): - if os.environ.get("ARCADEDB_BACKEND", "jpype").lower() != "native": + if not _native(): return for item in items: - reason = NATIVE_NA_JVM_TESTS.get(item.name) + # "::[::][]", the file without its directory + test_id = f"{item.path.name}::{item.nodeid.split('::', 1)[-1]}" + reason = NATIVE_NA_JVM_TESTS.get(test_id) or NATIVE_NA_JVM_TESTS.get( + test_id.split("[", 1)[0] + ) if reason: item.add_marker(pytest.mark.skip(reason=f"NA-JVM: {reason}")) @pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): + """On the native backend, report a test as NOTYET when the native code raised NotOnNativeYet. + + That is the one explicit signal: the native code path names a feature the wheel does not have (yet) by raising a dedicated + exception, the exception itself or an exception raised from it. Nothing else is turned into a skip. In particular no failure text + is matched: a text such as "assert None is not None" or "KeyError: 'flush'" is also what a real bug looks like. + """ outcome = yield - if os.environ.get("ARCADEDB_BACKEND", "jpype").lower() != "native": + if not _native(): return report = outcome.get_result() if call.excinfo is None or report.passed: return from arcadedb_embedded._native import NotOnNativeYet - if item.name in NATIVE_NA_TESTS: - report.outcome = "skipped" - report.longrepr = ( - str(item.fspath), - item.location[1] or 0, - "NA-JVM: counts JPype conversions", - ) - return exc, seen = call.excinfo.value, 0 while exc is not None and seen < 8: if isinstance(exc, NotOnNativeYet): @@ -143,25 +193,7 @@ def pytest_runtest_makereport(item, call): f"NOTYET: {exc}", ) return - text = f"{type(exc).__name__}: {exc}" - if any(marker in text for marker in NATIVE_NOTYET_MARKERS): - report.outcome = "skipped" - report.longrepr = ( - str(item.fspath), - item.location[1] or 0, - "NOTYET: Java-object wrapper or exporter path", - ) - return - if any(marker in text for marker in NATIVE_JVM_MARKERS): - # the test reaches into the JVM directly (jpype.JClass, Java arrays, bridge classes): about the JPype path - report.outcome = "skipped" - report.longrepr = ( - str(item.fspath), - item.location[1] or 0, - "NA-JVM: the test uses the JVM directly", - ) - return - exc, seen = exc.__cause__ or exc.__context__, seen + 1 + exc, seen = exc.__cause__, seen + 1 @pytest.hookimpl(trylast=True) diff --git a/bindings/python/tests/test_graph_batch.py b/bindings/python/tests/test_graph_batch.py index ddee4175dd7..e9b030b99f6 100644 --- a/bindings/python/tests/test_graph_batch.py +++ b/bindings/python/tests/test_graph_batch.py @@ -1,10 +1,13 @@ import contextlib +import os from datetime import datetime import arcadedb_embedded as arcadedb import pytest from arcadedb_embedded.exceptions import ArcadeDBError +_NATIVE = os.environ.get("ARCADEDB_BACKEND", "jpype").lower() == "native" + def test_graph_batch_creates_vertices_and_edges(temp_db_path): with arcadedb.create_database(temp_db_path) as db: @@ -524,6 +527,11 @@ def interrupt(*_args, **_kwargs): # untouched transaction, so a change that commits quietly again, or one that stops refusing # without leaving the transaction alone, fails them. def _is_the_engines_refusal(error): + if _NATIVE: + # no Java exception object to chain: the engine's class is named in the message + return isinstance(error, ArcadeDBError) and "IllegalStateException" in str( + error + ) import jpype return isinstance(error, ArcadeDBError) and isinstance( @@ -717,11 +725,33 @@ def test_graph_batch_close_refused_in_the_callers_transaction_can_be_retried( + batch.get_deferred_incoming_edge_count() > 0 ) + if ( + not _NATIVE + ): # native: BACKLOG-bindings.md P-04, pinned by the test below + with pytest.raises(ArcadeDBError, match="already in progress"): + db.graph_batch(parallel_flush=False) + finally: + batch.close() + assert db.count_type("E") == 2 + db.graph_batch(parallel_flush=False).close() + + +@pytest.mark.xfail( + _NATIVE, + strict=True, + reason="BACKLOG-bindings.md P-04: the native glue builds its batch with GraphBatch.builder(db), which takes no part in the engine's " + "single-batch guard (LocalDatabase.batchStarted); the JPype path goes through db.batch(). Two batches on one database lose edges.", +) +def test_a_second_graph_batch_is_refused_while_one_is_open(temp_db_path): + """#5666: two concurrent GraphBatch instances on one database silently lose edges, so the engine refuses the second.""" + with arcadedb.create_database(temp_db_path) as db: + _vertex_edge_note_types(db) + batch = db.graph_batch(parallel_flush=False) + try: with pytest.raises(ArcadeDBError, match="already in progress"): db.graph_batch(parallel_flush=False) finally: batch.close() - assert db.count_type("E") == 2 db.graph_batch(parallel_flush=False).close() diff --git a/bindings/python/tests/test_resultset_read_errors.py b/bindings/python/tests/test_resultset_read_errors.py index 9b070922dbc..9db41a262b3 100644 --- a/bindings/python/tests/test_resultset_read_errors.py +++ b/bindings/python/tests/test_resultset_read_errors.py @@ -75,6 +75,11 @@ def db(): def _assert_wraps_the_java_error(error): + if os.environ.get("ARCADEDB_BACKEND", "jpype").lower() == "native": + # no Java exception object to chain: the engine's error is named in the message, which is what the other backend's cause adds + assert str(error).startswith("Reading the result set failed: ") + assert "Exception: " in str(error), str(error) + return cause = error.__cause__ assert isinstance(cause, jpype.JException), f"cause is {type(cause)!r}" assert isinstance(cause, jpype.JClass("java.lang.RuntimeException")) diff --git a/bindings/python/tests/test_sparse_quantization_compact.py b/bindings/python/tests/test_sparse_quantization_compact.py index 784851f5c64..77dbb3a43a7 100644 --- a/bindings/python/tests/test_sparse_quantization_compact.py +++ b/bindings/python/tests/test_sparse_quantization_compact.py @@ -3,7 +3,6 @@ benchmark harness depends on (guide/vectors.md, 2026-09-07).""" import arcadedb_embedded as arcadedb -import jpype.types as jtypes import pytest DIMS = 512 @@ -37,7 +36,7 @@ def _neighbours(db, toks, wts, k=5): rows = db.query( "sql", "SELECT id FROM (SELECT expand(`vector.sparseNeighbors`('SDoc[tokens,weights]', ?, ?, ?)))", - jtypes.JArray(jtypes.JInt)(toks), + arcadedb.to_java_int_array(toks), arcadedb.to_java_float_array(wts), k, ).to_list() @@ -119,7 +118,7 @@ def _scores_against_exact(db, type_name, meta): "sql", f"INSERT INTO {type_name} SET id = ?, tokens = ?, weights = ?", i, - jtypes.JArray(jtypes.JInt)(toks), + arcadedb.to_java_int_array(toks), arcadedb.to_java_float_array(wts), ) db.command("sql", f"COMPACT INDEX `{type_name}[tokens,weights]`") @@ -128,7 +127,7 @@ def _scores_against_exact(db, type_name, meta): "sql", "SELECT id, score FROM (SELECT expand(`vector.sparseNeighbors`(" f"'{type_name}[tokens,weights]', ?, ?, ?)))", # nosec B608 - test type name - jtypes.JArray(jtypes.JInt)(list(query)), + arcadedb.to_java_int_array(list(query)), arcadedb.to_java_float_array(list(query.values())), 5, ).to_list() diff --git a/bindings/python/tests/test_vector_sql.py b/bindings/python/tests/test_vector_sql.py index 2026e00ac85..402631887dd 100644 --- a/bindings/python/tests/test_vector_sql.py +++ b/bindings/python/tests/test_vector_sql.py @@ -8,7 +8,6 @@ import math import arcadedb_embedded as arcadedb -import jpype.types as jtypes import pytest from arcadedb_embedded import create_database @@ -564,7 +563,7 @@ def test_sparse_vector_neighbors_sql(self, test_db): "(SELECT expand(`vector.sparseNeighbors`('SparseDoc[tokens,weights]', ?, ?, ?))) " "ORDER BY score DESC" ), - jtypes.JArray(jtypes.JInt)([5]), + arcadedb.to_java_int_array([5]), arcadedb.to_java_float_array([1.0]), 5, ).to_list() @@ -1313,7 +1312,7 @@ def _search(db, options): "SELECT id, score FROM " # nosec B608 - test-owned option literals "(SELECT expand(`vector.sparseNeighbors`('SparseOpt[tokens,weights]', " # nosec B608 f"?, ?, 5, {options}))) ORDER BY score DESC", # nosec B608 - jtypes.JArray(jtypes.JInt)([5]), + arcadedb.to_java_int_array([5]), arcadedb.to_java_float_array([1.0]), ).to_list()