This is an automated email from the ASF dual-hosted git repository.

lzljs3620320 pushed a commit to branch release-1.3
in repository https://gitbox.apache.org/repos/asf/paimon.git

commit 1390842f9b0ebcc4f48b52c41135f918b5839dce
Author: umi <[email protected]>
AuthorDate: Tue Nov 11 10:53:37 2025 +0800

    [Python] Add Mixed read and write test between Java and Python. (#6579)
---
 .github/workflows/paimon-python-checks.yml         |  24 +++
 .../test/java/org/apache/paimon/JavaPyE2ETest.java | 159 +++++++++++++++
 paimon-python/dev/lint-python.sh                   |  49 ++++-
 paimon-python/dev/run_mixed_tests.sh               | 217 +++++++++++++++++++++
 paimon-python/pypaimon/tests/e2e/__init__.py       |  16 ++
 .../pypaimon/tests/e2e/java_py_read_write_test.py  |  89 +++++++++
 6 files changed, 548 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/paimon-python-checks.yml 
b/.github/workflows/paimon-python-checks.yml
index c4c7e32a84..80277e701c 100755
--- a/.github/workflows/paimon-python-checks.yml
+++ b/.github/workflows/paimon-python-checks.yml
@@ -32,6 +32,9 @@ on:
 
 env:
   PYTHON_VERSIONS: "['3.6.15', '3.10']"
+  JDK_VERSION: 8
+  MAVEN_OPTS: -Dmaven.wagon.httpconnectionManager.ttlSeconds=30 
-Dmaven.wagon.http.retryHandler.requestSentEnabled=true
+
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.event_name }}-${{ 
github.event.number || github.run_id }}
@@ -49,6 +52,17 @@ jobs:
       - name: Checkout code
         uses: actions/checkout@v2
 
+      - name: Set up JDK ${{ env.JDK_VERSION }}
+        uses: actions/setup-java@v4
+        with:
+          java-version: ${{ env.JDK_VERSION }}
+          distribution: 'temurin'
+
+      - name: Set up Maven
+        uses: stCarolas/[email protected]
+        with:
+          maven-version: 3.8.8
+
       - name: Install system dependencies
         shell: bash
         run: |
@@ -58,9 +72,19 @@ jobs:
             curl \
             && rm -rf /var/lib/apt/lists/*
 
+      - name: Verify Java and Maven installation
+        run: |
+          java -version
+          mvn -version
+
       - name: Verify Python version
         run: python --version
 
+      - name: Build Java
+        run: |
+          echo "Start compiling modules"
+          mvn -T 2C -B clean install -DskipTests
+
       - name: Install Python dependencies
         shell: bash
         run: |
diff --git a/paimon-core/src/test/java/org/apache/paimon/JavaPyE2ETest.java 
b/paimon-core/src/test/java/org/apache/paimon/JavaPyE2ETest.java
new file mode 100644
index 0000000000..3759bc8757
--- /dev/null
+++ b/paimon-core/src/test/java/org/apache/paimon/JavaPyE2ETest.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon;
+
+import org.apache.paimon.catalog.Catalog;
+import org.apache.paimon.catalog.CatalogContext;
+import org.apache.paimon.catalog.CatalogFactory;
+import org.apache.paimon.catalog.Identifier;
+import org.apache.paimon.data.BinaryString;
+import org.apache.paimon.data.DataFormatTestUtil;
+import org.apache.paimon.data.GenericRow;
+import org.apache.paimon.data.InternalRow;
+import org.apache.paimon.fs.Path;
+import org.apache.paimon.schema.Schema;
+import org.apache.paimon.table.FileStoreTable;
+import org.apache.paimon.table.Table;
+import org.apache.paimon.table.sink.InnerTableCommit;
+import org.apache.paimon.table.sink.StreamTableWrite;
+import org.apache.paimon.table.source.Split;
+import org.apache.paimon.table.source.TableRead;
+import org.apache.paimon.types.DataTypes;
+import org.apache.paimon.utils.TraceableFileIO;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.apache.paimon.table.SimpleTableTestBase.getResult;
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** Mixed language overwrite test for Java and Python interoperability. */
+public class JavaPyE2ETest {
+
+    java.nio.file.Path tempDir = 
Paths.get("../paimon-python/pypaimon/tests/e2e").toAbsolutePath();
+
+    // Fields from TableTestBase that we need
+    protected final String commitUser = UUID.randomUUID().toString();
+    protected Path warehouse;
+    protected Catalog catalog;
+    protected String database;
+
+    @BeforeEach
+    public void before() throws Exception {
+        database = "default";
+
+        // Create warehouse directory if it doesn't exist
+        if (!Files.exists(tempDir.resolve("warehouse"))) {
+            Files.createDirectories(tempDir.resolve("warehouse"));
+        }
+
+        warehouse = new Path(TraceableFileIO.SCHEME + "://" + 
tempDir.resolve("warehouse"));
+        catalog = 
CatalogFactory.createCatalog(CatalogContext.create(warehouse));
+
+        // Create database if it doesn't exist
+        try {
+            catalog.createDatabase(database, false);
+        } catch (Catalog.DatabaseAlreadyExistException e) {
+            // Database already exists, ignore
+        }
+    }
+
+    @Test
+    @EnabledIfSystemProperty(named = "run.e2e.tests", matches = "true")
+    public void testJavaWriteRead() throws Exception {
+        Identifier identifier = identifier("mixed_test_tablej");
+        Schema schema =
+                Schema.newBuilder()
+                        .column("id", DataTypes.INT())
+                        .column("name", DataTypes.STRING())
+                        .column("category", DataTypes.STRING())
+                        .column("value", DataTypes.DOUBLE())
+                        .partitionKeys("category")
+                        .option("dynamic-partition-overwrite", "false")
+                        .build();
+
+        catalog.createTable(identifier, schema, true);
+        Table table = catalog.getTable(identifier);
+        FileStoreTable fileStoreTable = (FileStoreTable) table;
+
+        try (StreamTableWrite write = fileStoreTable.newWrite(commitUser);
+                InnerTableCommit commit = 
fileStoreTable.newCommit(commitUser)) {
+
+            write.write(createRow(1, "Apple", "Fruit", 1.5));
+            write.write(createRow(2, "Banana", "Fruit", 0.8));
+            write.write(createRow(3, "Carrot", "Vegetable", 0.6));
+            write.write(createRow(4, "Broccoli", "Vegetable", 1.2));
+            write.write(createRow(5, "Chicken", "Meat", 5.0));
+            write.write(createRow(6, "Beef", "Meat", 8.0));
+
+            commit.commit(0, write.prepareCommit(true, 0));
+        }
+
+        List<Split> splits =
+                new 
ArrayList<>(fileStoreTable.newSnapshotReader().read().dataSplits());
+        TableRead read = fileStoreTable.newRead();
+        List<String> res =
+                getResult(
+                        read,
+                        splits,
+                        row -> DataFormatTestUtil.toStringNoRowKind(row, 
table.rowType()));
+        assertThat(res)
+                .containsExactlyInAnyOrder(
+                        "1, Apple, Fruit, 1.5",
+                        "2, Banana, Fruit, 0.8",
+                        "3, Carrot, Vegetable, 0.6",
+                        "4, Broccoli, Vegetable, 1.2",
+                        "5, Chicken, Meat, 5.0",
+                        "6, Beef, Meat, 8.0");
+    }
+
+    @Test
+    @EnabledIfSystemProperty(named = "run.e2e.tests", matches = "true")
+    public void testRead() throws Exception {
+        Identifier identifier = identifier("mixed_test_tablep");
+        Table table = catalog.getTable(identifier);
+        FileStoreTable fileStoreTable = (FileStoreTable) table;
+        List<Split> splits =
+                new 
ArrayList<>(fileStoreTable.newSnapshotReader().read().dataSplits());
+        TableRead read = fileStoreTable.newRead();
+        List<String> res =
+                getResult(
+                        read,
+                        splits,
+                        row -> DataFormatTestUtil.toStringNoRowKind(row, 
table.rowType()));
+        System.out.println(res);
+    }
+
+    // Helper method from TableTestBase
+    protected Identifier identifier(String tableName) {
+        return new Identifier(database, tableName);
+    }
+
+    private static InternalRow createRow(int id, String name, String category, 
double value) {
+        return GenericRow.of(
+                id, BinaryString.fromString(name), 
BinaryString.fromString(category), value);
+    }
+}
diff --git a/paimon-python/dev/lint-python.sh b/paimon-python/dev/lint-python.sh
index 9cbb612137..fb57bfdd41 100755
--- a/paimon-python/dev/lint-python.sh
+++ b/paimon-python/dev/lint-python.sh
@@ -119,13 +119,12 @@ function get_all_supported_checks() {
 # exec all selected check stages
 function check_stage() {
     print_function "STAGE" "checks starting"
-    for fun in ${SUPPORT_CHECKS[@]}; do
+    for fun in "${SUPPORT_CHECKS[@]}"; do
         $fun
     done
     echo "All the checks are finished, the detailed information can be found 
in: $LOG_FILE"
 }
 
-
 ###############################################################All Checks 
Definitions###############################################################
 #########################
 # This part defines all check functions such as tox_check and flake8_check
@@ -176,7 +175,7 @@ function pytest_check() {
         TEST_DIR="pypaimon/tests/py36"
         echo "Running tests for Python 3.6: $TEST_DIR"
     else
-        TEST_DIR="pypaimon/tests --ignore=pypaimon/tests/py36"
+        TEST_DIR="pypaimon/tests --ignore=pypaimon/tests/py36 
--ignore=pypaimon/tests/e2e"
         echo "Running tests for Python $PYTHON_VERSION (excluding py36): 
pypaimon/tests --ignore=pypaimon/tests/py36"
     fi
 
@@ -194,6 +193,43 @@ function pytest_check() {
         print_function "STAGE" "pytest checks... [SUCCESS]"
     fi
 }
+
+# Mixed tests check - runs Java-Python interoperability tests
+function mixed_check() {
+    # Get Python version
+    PYTHON_VERSION=$(python -c "import sys; 
print(f'{sys.version_info.major}.{sys.version_info.minor}')")
+    echo "Detected Python version: $PYTHON_VERSION"
+    if [ "$PYTHON_VERSION" = "3.6" ]; then
+        print_function "STAGE" "mixed tests checks... [SKIPPED]"
+        return
+    fi
+    print_function "STAGE" "mixed tests checks"
+
+    # Path to the mixed tests script
+    MIXED_TESTS_SCRIPT="$CURRENT_DIR/dev/run_mixed_tests.sh"
+
+    if [ ! -f "$MIXED_TESTS_SCRIPT" ]; then
+        echo "Mixed tests script not found at: $MIXED_TESTS_SCRIPT"
+        print_function "STAGE" "mixed tests checks... [FAILED]"
+        exit 1
+    fi
+
+    # Make sure the script is executable
+    chmod +x "$MIXED_TESTS_SCRIPT"
+
+    # Run the mixed tests script
+    set -o pipefail
+    ($MIXED_TESTS_SCRIPT) 2>&1 | tee -a $LOG_FILE
+
+    MIXED_TESTS_STATUS=$?
+    if [ $MIXED_TESTS_STATUS -ne 0 ]; then
+        print_function "STAGE" "mixed tests checks... [FAILED]"
+        # Stop the running script.
+        exit 1;
+    else
+        print_function "STAGE" "mixed tests checks... [SUCCESS]"
+    fi
+}
 ###############################################################All Checks 
Definitions###############################################################
 # CURRENT_DIR is "paimon-python/"
 SCRIPT_PATH="$(readlink -f "$0")"
@@ -236,15 +272,16 @@ INCLUDE_CHECKS=""
 USAGE="
 usage: $0 [options]
 -h          print this help message and exit
--e [tox,flake8,sphinx,mypy]
+-e [tox,flake8,sphinx,mypy,mixed]
             exclude checks which split by comma(,)
--i [tox,flake8,sphinx,mypy]
+-i [tox,flake8,sphinx,mypy,mixed]
             include checks which split by comma(,)
 -l          list all checks supported.
 Examples:
   ./lint-python.sh                 =>  exec all checks.
   ./lint-python.sh -e tox,flake8   =>  exclude checks tox,flake8.
   ./lint-python.sh -i flake8       =>  include checks flake8.
+  ./lint-python.sh -i mixed        =>  include checks mixed.
   ./lint-python.sh -l              =>  list all checks supported.
 "
 while getopts "hfs:i:e:lr" arg; do
@@ -261,7 +298,7 @@ while getopts "hfs:i:e:lr" arg; do
             ;;
         l)
             printf "current supported checks includes:\n"
-            for fun in ${SUPPORT_CHECKS[@]}; do
+            for fun in "${SUPPORT_CHECKS[@]}"; do
                 echo ${fun%%_check*}
             done
             exit 2
diff --git a/paimon-python/dev/run_mixed_tests.sh 
b/paimon-python/dev/run_mixed_tests.sh
new file mode 100755
index 0000000000..8387e79eb9
--- /dev/null
+++ b/paimon-python/dev/run_mixed_tests.sh
@@ -0,0 +1,217 @@
+#!/bin/bash
+
+################################################################################
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+# limitations under the License.
+################################################################################
+
+# Mixed Java and Python test runner
+# This script runs Java test first, then Python test to verify interoperability
+
+set -e  # Exit on any error
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+# Get script directory
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
+PAIMON_PYTHON_DIR="$PROJECT_ROOT/paimon-python/pypaimon/tests/e2e"
+PAIMON_CORE_DIR="$PROJECT_ROOT/paimon-core"
+
+echo -e "${YELLOW}=== Mixed Java-Python Read Write Test Runner ===${NC}"
+echo "Project root: $PROJECT_ROOT"
+echo "Paimon Python dir: $PAIMON_PYTHON_DIR"
+echo "Paimon Core dir: $PAIMON_CORE_DIR"
+echo ""
+
+# Function to clean up warehouse directory
+cleanup_warehouse() {
+    echo -e "${YELLOW}=== Cleaning up warehouse directory ===${NC}"
+
+    local warehouse_dir="$PAIMON_PYTHON_DIR/warehouse"
+
+    if [[ -d "$warehouse_dir" ]]; then
+        echo "Removing warehouse directory: $warehouse_dir"
+        rm -rf "$warehouse_dir"
+        echo -e "${GREEN}✓ Warehouse directory cleaned up successfully${NC}"
+    else
+        echo "Warehouse directory does not exist, no cleanup needed"
+    fi
+
+    echo ""
+}
+
+# Function to run Java test
+run_java_write_test() {
+    echo -e "${YELLOW}=== Step 1: Running Java Test 
(JavaPyE2ETest.testJavaWriteRead) ===${NC}"
+
+    cd "$PROJECT_ROOT"
+
+    # Run the specific Java test method
+    echo "Running Maven test for JavaPyE2ETest.testJavaWriteRead..."
+    if mvn test -Dtest=org.apache.paimon.JavaPyE2ETest#testJavaWriteRead -pl 
paimon-core -q -Drun.e2e.tests=true; then
+        echo -e "${GREEN}✓ Java test completed successfully${NC}"
+        return 0
+    else
+        echo -e "${RED}✗ Java test failed${NC}"
+        return 1
+    fi
+}
+
+# Function to run Python test
+run_python_read_test() {
+    echo -e "${YELLOW}=== Step 2: Running Python Test 
(JavaPyReadWriteTest.testRead) ===${NC}"
+
+    cd "$PAIMON_PYTHON_DIR"
+
+    # Run the specific Python test method
+    echo "Running Python test for JavaPyReadWriteTest.testRead..."
+    if python -m pytest 
java_py_read_write_test.py::JavaPyReadWriteTest::test_read -v; then
+        echo -e "${GREEN}✓ Python test completed successfully${NC}"
+#        source deactivate
+        return 0
+    else
+        echo -e "${RED}✗ Python test failed${NC}"
+#        source deactivate
+        return 1
+    fi
+}
+
+# Function to run Python Write test for Python-Write-Java-Read scenario
+run_python_write_test() {
+    echo -e "${YELLOW}=== Step 3: Running Python Write Test 
(JavaPyReadWriteTest.test_py_write_read) ===${NC}"
+
+    cd "$PAIMON_PYTHON_DIR"
+
+    # Run the specific Python test method for writing data
+    echo "Running Python test for JavaPyReadWriteTest.test_py_write_read 
(Python Write)..."
+    if python -m pytest 
java_py_read_write_test.py::JavaPyReadWriteTest::test_py_write_read -v; then
+        echo -e "${GREEN}✓ Python write test completed successfully${NC}"
+        return 0
+    else
+        echo -e "${RED}✗ Python write test failed${NC}"
+        return 1
+    fi
+}
+
+# Function to run Java Read test for Python-Write-Java-Read scenario
+run_java_read_test() {
+    echo -e "${YELLOW}=== Step 4: Running Java Read Test 
(JavaPyE2ETest.testRead) ===${NC}"
+
+    cd "$PROJECT_ROOT"
+
+    # Run the specific Java test method for reading Python-written data
+    echo "Running Maven test for JavaPyE2ETest.testRead (Java Read)..."
+    if mvn test -Dtest=org.apache.paimon.JavaPyE2ETest#testRead -pl 
paimon-core -q -Drun.e2e.tests=true; then
+        echo -e "${GREEN}✓ Java read test completed successfully${NC}"
+        return 0
+    else
+        echo -e "${RED}✗ Java read test failed${NC}"
+        return 1
+    fi
+}
+
+# Main execution
+main() {
+    local java_write_result=0
+    local python_read_result=0
+    local python_write_result=0
+    local java_read_result=0
+
+    echo -e "${YELLOW}Starting mixed language test execution...${NC}"
+    echo ""
+
+    # Run Java write test
+    if ! run_java_write_test; then
+        java_write_result=1
+        echo -e "${RED}Java test failed, but continuing with Python 
test...${NC}"
+        echo ""
+    else
+        echo ""
+    fi
+
+    # Run Python read test
+    if ! run_python_read_test; then
+        python_read_result=1
+    fi
+
+    echo ""
+
+    # Run Python Write - Java Read test sequence
+    echo -e "${YELLOW}Starting Python Write - Java Read test sequence...${NC}"
+    echo ""
+
+    # Run Python write test
+    if ! run_python_write_test; then
+        python_write_result=1
+        echo -e "${RED}Python write test failed, but continuing with Java read 
test...${NC}"
+        echo ""
+    else
+        echo ""
+    fi
+
+    # Run Java read test
+    if ! run_java_read_test; then
+        java_read_result=1
+    fi
+
+    echo ""
+    echo -e "${YELLOW}=== Test Results Summary ===${NC}"
+
+    if [[ $java_write_result -eq 0 ]]; then
+        echo -e "${GREEN}✓ Java Write Test (JavaPyE2ETest.testJavaWriteRead): 
PASSED${NC}"
+    else
+        echo -e "${RED}✗ Java Write Test (JavaPyE2ETest.testJavaWriteRead): 
FAILED${NC}"
+    fi
+
+    if [[ $python_read_result -eq 0 ]]; then
+        echo -e "${GREEN}✓ Python Read Test (JavaPyReadWriteTest.testRead): 
PASSED${NC}"
+    else
+        echo -e "${RED}✗ Python Read Test (JavaPyReadWriteTest.testRead): 
FAILED${NC}"
+    fi
+
+    if [[ $python_write_result -eq 0 ]]; then
+        echo -e "${GREEN}✓ Python Write Test 
(JavaPyReadWriteTest.test_py_write_read): PASSED${NC}"
+    else
+        echo -e "${RED}✗ Python Write Test 
(JavaPyReadWriteTest.test_py_write_read): FAILED${NC}"
+    fi
+
+    if [[ $java_read_result -eq 0 ]]; then
+        echo -e "${GREEN}✓ Java Read Test (JavaPyE2ETest.testRead): 
PASSED${NC}"
+    else
+        echo -e "${RED}✗ Java Read Test (JavaPyE2ETest.testRead): FAILED${NC}"
+    fi
+
+    echo ""
+
+    # Clean up warehouse directory after all tests
+    cleanup_warehouse
+
+    if [[ $java_write_result -eq 0 && $python_read_result -eq 0 && 
$python_write_result -eq 0 && $java_read_result -eq 0 ]]; then
+        echo -e "${GREEN}🎉 All tests passed! Java-Python interoperability 
verified.${NC}"
+        return 0
+    else
+        echo -e "${RED}❌ Some tests failed. Please check the output 
above.${NC}"
+        return 1
+    fi
+}
+
+# Run main function
+main "$@"
\ No newline at end of file
diff --git a/paimon-python/pypaimon/tests/e2e/__init__.py 
b/paimon-python/pypaimon/tests/e2e/__init__.py
new file mode 100644
index 0000000000..a67d5ea255
--- /dev/null
+++ b/paimon-python/pypaimon/tests/e2e/__init__.py
@@ -0,0 +1,16 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
diff --git a/paimon-python/pypaimon/tests/e2e/java_py_read_write_test.py 
b/paimon-python/pypaimon/tests/e2e/java_py_read_write_test.py
new file mode 100644
index 0000000000..405484d505
--- /dev/null
+++ b/paimon-python/pypaimon/tests/e2e/java_py_read_write_test.py
@@ -0,0 +1,89 @@
+################################################################################
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+# limitations under the License.
+################################################################################
+
+import os
+import unittest
+
+import pandas as pd
+import pyarrow as pa
+from pypaimon.catalog.catalog_factory import CatalogFactory
+from pypaimon.schema.schema import Schema
+
+
+class JavaPyReadWriteTest(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.tempdir = os.path.abspath(".")
+        cls.warehouse = os.path.join(cls.tempdir, 'warehouse')
+        cls.catalog = CatalogFactory.create({
+            'warehouse': cls.warehouse
+        })
+        cls.catalog.create_database('default', True)
+
+    def test_py_write_read(self):
+        pa_schema = pa.schema([
+            ('id', pa.int32()),
+            ('name', pa.string()),
+            ('category', pa.string()),
+            ('value', pa.float64())
+        ])
+
+        schema = Schema.from_pyarrow_schema(
+            pa_schema,
+            partition_keys=['category'],
+            options={'dynamic-partition-overwrite': 'false'}
+        )
+
+        self.catalog.create_table('default.mixed_test_tablep', schema, False)
+        table = self.catalog.get_table('default.mixed_test_tablep')
+
+        initial_data = pd.DataFrame({
+            'id': [1, 2, 3, 4, 5, 6],
+            'name': ['Apple', 'Banana', 'Carrot', 'Broccoli', 'Chicken', 
'Beef'],
+            'category': ['Fruit', 'Fruit', 'Vegetable', 'Vegetable', 'Meat', 
'Meat'],
+            'value': [1.5, 0.8, 0.6, 1.2, 5.0, 8.0]
+        })
+        # Write initial data
+        write_builder = table.new_batch_write_builder()
+        table_write = write_builder.new_write()
+        table_commit = write_builder.new_commit()
+
+        table_write.write_pandas(initial_data)
+        table_commit.commit(table_write.prepare_commit())
+        table_write.close()
+        table_commit.close()
+
+        # Verify initial data
+        read_builder = table.new_read_builder()
+        table_scan = read_builder.new_scan()
+        table_read = read_builder.new_read()
+        initial_result = table_read.to_pandas(table_scan.plan().splits())
+        print(initial_result)
+        self.assertEqual(len(initial_result), 6)
+        self.assertListEqual(
+            initial_result['name'].tolist(),
+            ['Apple', 'Banana', 'Carrot', 'Broccoli', 'Chicken', 'Beef']
+        )
+
+    def test_read(self):
+        table = self.catalog.get_table('default.mixed_test_tablej')
+        read_builder = table.new_read_builder()
+        table_scan = read_builder.new_scan()
+        table_read = read_builder.new_read()
+        res = table_read.to_pandas(table_scan.plan().splits())
+        print(res)

Reply via email to