|
50 | 50 | _process_brief, |
51 | 51 | _process_connection_string, |
52 | 52 | _process_csv_input, |
| 53 | + _process_data, |
53 | 54 | _process_parquet_input, |
54 | 55 | connect_to_table, |
55 | 56 | _process_title_text, |
@@ -7801,6 +7802,265 @@ def test_process_action_str(): |
7801 | 7802 | ) |
7802 | 7803 |
|
7803 | 7804 |
|
| 7805 | +def test_process_data_dataframe_passthrough_polars(): |
| 7806 | + pl = pytest.importorskip("polars") |
| 7807 | + |
| 7808 | + # Create test DataFrame |
| 7809 | + df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]}) |
| 7810 | + |
| 7811 | + # Process through the function |
| 7812 | + result = _process_data(df) |
| 7813 | + |
| 7814 | + # Should be the same object |
| 7815 | + assert result is df |
| 7816 | + |
| 7817 | + |
| 7818 | +def test_process_data_dataframe_passthrough_pandas(): |
| 7819 | + pd = pytest.importorskip("pandas") |
| 7820 | + |
| 7821 | + # Create test DataFrame |
| 7822 | + df = pd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]}) |
| 7823 | + |
| 7824 | + # Process through the function |
| 7825 | + result = _process_data(df) |
| 7826 | + |
| 7827 | + # Should be the same object |
| 7828 | + assert result is df |
| 7829 | + |
| 7830 | + |
| 7831 | +def test_process_data_non_data_passthrough(): |
| 7832 | + test_cases = [ |
| 7833 | + 42, # Integer |
| 7834 | + 3.14, # Float |
| 7835 | + "not_a_file.txt", # Random string |
| 7836 | + ["list", "of", "items"], # List |
| 7837 | + {"key": "value"}, # Dict |
| 7838 | + None, # None |
| 7839 | + ] |
| 7840 | + |
| 7841 | + for test_input in test_cases: |
| 7842 | + result = _process_data(test_input) |
| 7843 | + assert result is test_input |
| 7844 | + |
| 7845 | + |
| 7846 | +def test_process_data_csv_file_processing(): |
| 7847 | + pl = pytest.importorskip("polars") |
| 7848 | + |
| 7849 | + # Create test DataFrame and temporary CSV file |
| 7850 | + df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [1.1, 2.2, 3.3]}) |
| 7851 | + |
| 7852 | + with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f: |
| 7853 | + df.write_csv(f.name) |
| 7854 | + csv_path = f.name |
| 7855 | + |
| 7856 | + try: |
| 7857 | + # Process the CSV file |
| 7858 | + result = _process_data(csv_path) |
| 7859 | + |
| 7860 | + # Should return a DataFrame |
| 7861 | + assert hasattr(result, "columns") or hasattr(result, "shape") |
| 7862 | + assert len(result) == 3 # Should have 3 rows |
| 7863 | + |
| 7864 | + finally: |
| 7865 | + # Clean up |
| 7866 | + Path(csv_path).unlink() |
| 7867 | + |
| 7868 | + |
| 7869 | +def test_process_data_csv_path_object_processing(): |
| 7870 | + pl = pytest.importorskip("polars") |
| 7871 | + |
| 7872 | + # Create test DataFrame and temporary CSV file |
| 7873 | + df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [1.1, 2.2, 3.3]}) |
| 7874 | + |
| 7875 | + with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f: |
| 7876 | + df.write_csv(f.name) |
| 7877 | + path_obj = Path(f.name) |
| 7878 | + |
| 7879 | + try: |
| 7880 | + # Process the Path object |
| 7881 | + result = _process_data(path_obj) |
| 7882 | + |
| 7883 | + # Should return a DataFrame |
| 7884 | + assert hasattr(result, "columns") or hasattr(result, "shape") |
| 7885 | + assert len(result) == 3 # Should have 3 rows |
| 7886 | + |
| 7887 | + finally: |
| 7888 | + # Clean up |
| 7889 | + path_obj.unlink() |
| 7890 | + |
| 7891 | + |
| 7892 | +def test_process_data_parquet_file_processing(): |
| 7893 | + pl = pytest.importorskip("polars") |
| 7894 | + |
| 7895 | + # Create test DataFrame and temporary Parquet file |
| 7896 | + df = pl.DataFrame({"x": [10, 20, 30], "y": ["a", "b", "c"], "z": [10.5, 20.5, 30.5]}) |
| 7897 | + |
| 7898 | + with tempfile.NamedTemporaryFile(mode="w", suffix=".parquet", delete=False) as f: |
| 7899 | + df.write_parquet(f.name) |
| 7900 | + parquet_path = f.name |
| 7901 | + |
| 7902 | + try: |
| 7903 | + # Process the Parquet file |
| 7904 | + result = _process_data(parquet_path) |
| 7905 | + |
| 7906 | + # Should return a DataFrame |
| 7907 | + assert hasattr(result, "columns") or hasattr(result, "shape") |
| 7908 | + assert len(result) == 3 # Should have 3 rows |
| 7909 | + |
| 7910 | + finally: |
| 7911 | + # Clean up |
| 7912 | + Path(parquet_path).unlink() |
| 7913 | + |
| 7914 | + |
| 7915 | +def test_process_data_nonexistent_file(): |
| 7916 | + # Test CSV |
| 7917 | + with pytest.raises(FileNotFoundError): |
| 7918 | + _process_data("nonexistent_file.csv") |
| 7919 | + |
| 7920 | + # Test Parquet |
| 7921 | + with pytest.raises(FileNotFoundError): |
| 7922 | + _process_data("nonexistent_file.parquet") |
| 7923 | + |
| 7924 | + |
| 7925 | +def test_process_data_processing_order(): |
| 7926 | + # This test ensures GitHub URLs are processed before connection strings |
| 7927 | + # by mocking the individual processing functions |
| 7928 | + |
| 7929 | + test_input = "test_string" |
| 7930 | + |
| 7931 | + with ( |
| 7932 | + patch("pointblank.validate._process_github_url") as mock_github, |
| 7933 | + patch("pointblank.validate._process_connection_string") as mock_conn, |
| 7934 | + patch("pointblank.validate._process_csv_input") as mock_csv, |
| 7935 | + patch("pointblank.validate._process_parquet_input") as mock_parquet, |
| 7936 | + ): |
| 7937 | + # Set up the mocks to pass through the input |
| 7938 | + mock_github.return_value = test_input |
| 7939 | + mock_conn.return_value = test_input |
| 7940 | + mock_csv.return_value = test_input |
| 7941 | + mock_parquet.return_value = test_input |
| 7942 | + |
| 7943 | + # Call the function |
| 7944 | + result = _process_data(test_input) |
| 7945 | + |
| 7946 | + # Verify the order of calls |
| 7947 | + mock_github.assert_called_once_with(test_input) |
| 7948 | + mock_conn.assert_called_once_with(test_input) |
| 7949 | + mock_csv.assert_called_once_with(test_input) |
| 7950 | + mock_parquet.assert_called_once_with(test_input) |
| 7951 | + |
| 7952 | + # Verify result |
| 7953 | + assert result == test_input |
| 7954 | + |
| 7955 | + |
| 7956 | +@patch("pointblank.validate._process_github_url") |
| 7957 | +def test_process_data_github_url_processing(mock_github): |
| 7958 | + pl = pytest.importorskip("polars") |
| 7959 | + |
| 7960 | + # Mock the GitHub processing to return a DataFrame |
| 7961 | + mock_df = pl.DataFrame({"test": [1, 2, 3]}) |
| 7962 | + mock_github.return_value = mock_df |
| 7963 | + |
| 7964 | + # Test with a GitHub URL |
| 7965 | + github_url = "https://github.com/user/repo/blob/main/data.csv" |
| 7966 | + result = _process_data(github_url) |
| 7967 | + |
| 7968 | + # Verify GitHub processing was called |
| 7969 | + mock_github.assert_called_once_with(github_url) |
| 7970 | + assert result is mock_df |
| 7971 | + |
| 7972 | + |
| 7973 | +def test_process_data_case_insensitive_extensions(): |
| 7974 | + pl = pytest.importorskip("polars") |
| 7975 | + |
| 7976 | + # Create test DataFrame |
| 7977 | + df = pl.DataFrame({"test": [1, 2, 3]}) |
| 7978 | + |
| 7979 | + # Test CSV with uppercase extension |
| 7980 | + with tempfile.NamedTemporaryFile(mode="w", suffix=".CSV", delete=False) as f: |
| 7981 | + df.write_csv(f.name) |
| 7982 | + csv_path = f.name |
| 7983 | + |
| 7984 | + try: |
| 7985 | + result = _process_data(csv_path) |
| 7986 | + assert hasattr(result, "columns") or hasattr(result, "shape") |
| 7987 | + finally: |
| 7988 | + Path(csv_path).unlink() |
| 7989 | + |
| 7990 | + |
| 7991 | +def test_process_data_integration_with_validate_class(): |
| 7992 | + pl = pytest.importorskip("polars") |
| 7993 | + |
| 7994 | + # Create test DataFrame and temporary CSV file |
| 7995 | + df = pl.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"], "c": [1.1, 2.2, 3.3]}) |
| 7996 | + |
| 7997 | + with tempfile.NamedTemporaryFile(mode="w", suffix=".csv", delete=False) as f: |
| 7998 | + df.write_csv(f.name) |
| 7999 | + csv_path = f.name |
| 8000 | + |
| 8001 | + try: |
| 8002 | + # Create a Validate instance with CSV path |
| 8003 | + validation = Validate(data=csv_path) |
| 8004 | + |
| 8005 | + # The data should have been processed into a DataFrame |
| 8006 | + assert hasattr(validation.data, "columns") or hasattr(validation.data, "shape") |
| 8007 | + assert len(validation.data) == 3 |
| 8008 | + |
| 8009 | + finally: |
| 8010 | + # Clean up |
| 8011 | + Path(csv_path).unlink() |
| 8012 | + |
| 8013 | + |
| 8014 | +def test_process_data_error_handling(): |
| 8015 | + # Test with invalid file paths |
| 8016 | + with pytest.raises((FileNotFoundError, OSError)): |
| 8017 | + _process_data("/invalid/path/file.csv") |
| 8018 | + |
| 8019 | + |
| 8020 | +def test_process_data_with_connection_string(): |
| 8021 | + with patch("pointblank.validate._process_connection_string") as mock_conn: |
| 8022 | + mock_table = Mock() |
| 8023 | + mock_conn.return_value = mock_table |
| 8024 | + |
| 8025 | + # Test that the function delegates to connection string processing |
| 8026 | + result = _process_data("duckdb://test.db::table") |
| 8027 | + |
| 8028 | + # Should call _process_connection_string and return the result |
| 8029 | + mock_conn.assert_called_once_with("duckdb://test.db::table") |
| 8030 | + assert result == mock_table |
| 8031 | + |
| 8032 | + |
| 8033 | +def test_process_data_dataframe_goes_through_pipeline(): |
| 8034 | + pl = pytest.importorskip("polars") |
| 8035 | + |
| 8036 | + # Create test DataFrame |
| 8037 | + df = pl.DataFrame({"test": [1, 2, 3]}) |
| 8038 | + |
| 8039 | + with ( |
| 8040 | + patch("pointblank.validate._process_github_url") as mock_github, |
| 8041 | + patch("pointblank.validate._process_connection_string") as mock_conn, |
| 8042 | + patch("pointblank.validate._process_csv_input") as mock_csv, |
| 8043 | + patch("pointblank.validate._process_parquet_input") as mock_parquet, |
| 8044 | + ): |
| 8045 | + # Set up the mocks to pass through the input (as they would for DataFrames) |
| 8046 | + mock_github.return_value = df |
| 8047 | + mock_conn.return_value = df |
| 8048 | + mock_csv.return_value = df |
| 8049 | + mock_parquet.return_value = df |
| 8050 | + |
| 8051 | + # Call the function with a DataFrame |
| 8052 | + result = _process_data(df) |
| 8053 | + |
| 8054 | + # Should return the DataFrame after going through all processing functions |
| 8055 | + assert result is df |
| 8056 | + |
| 8057 | + # All processing functions should have been called |
| 8058 | + mock_github.assert_called_once_with(df) |
| 8059 | + mock_conn.assert_called_once_with(df) |
| 8060 | + mock_csv.assert_called_once_with(df) |
| 8061 | + mock_parquet.assert_called_once_with(df) |
| 8062 | + |
| 8063 | + |
7804 | 8064 | def test_process_title_text(): |
7805 | 8065 | assert _process_title_text(title=None, tbl_name=None, lang="en") == "" |
7806 | 8066 | assert ( |
|
0 commit comments