|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
15 | 15 | import json
|
| 16 | +import sys |
16 | 17 |
|
17 | 18 | import numpy as np
|
18 | 19 | import pandas as pd
|
@@ -224,3 +225,70 @@ def test_json_arrow_record_batch():
|
224 | 225 | == '{"null_field":null,"order":{"address":{"city":"Anytown","street":"123 Main St"},"items":["book","pen","computer"],"total":15}}'
|
225 | 226 | )
|
226 | 227 | assert s[6] == "null"
|
| 228 | + |
| 229 | + |
| 230 | +@pytest.fixture |
| 231 | +def cleanup_json_module_for_reload(): |
| 232 | + """ |
| 233 | + Fixture to ensure db_dtypes.json is registered and then removed |
| 234 | + from sys.modules to allow testing the registration except block via reload. |
| 235 | + """ |
| 236 | + |
| 237 | + json_module_name = "db_dtypes.json" |
| 238 | + original_module = sys.modules.get(json_module_name) |
| 239 | + |
| 240 | + # Ensure the type is registered initially (usually by the first import) |
| 241 | + try: |
| 242 | + # Make sure the module is loaded so the type exists |
| 243 | + import db_dtypes.json |
| 244 | + |
| 245 | + # Explicitly register just in case it wasn't, or was cleaned up elsewhere. |
| 246 | + # This might raise ArrowKeyError itself if already registered, which is fine here. |
| 247 | + pa.register_extension_type(db_dtypes.json.JSONArrowType()) |
| 248 | + except pa.ArrowKeyError: |
| 249 | + pass # Already registered is the state we want before the test runs |
| 250 | + except ImportError: |
| 251 | + pytest.skip("Could not import db_dtypes.json to set up test.") |
| 252 | + |
| 253 | + # Remove the module from sys.modules so importlib.reload re-executes it |
| 254 | + if json_module_name in sys.modules: |
| 255 | + del sys.modules[json_module_name] |
| 256 | + |
| 257 | + yield # Run the test that uses this fixture |
| 258 | + |
| 259 | + # Cleanup: Put the original module back if it existed |
| 260 | + # This helps isolate from other tests that might import db_dtypes.json |
| 261 | + if original_module: |
| 262 | + sys.modules[json_module_name] = original_module |
| 263 | + elif json_module_name in sys.modules: |
| 264 | + # If the test re-imported it but it wasn't there originally, remove it |
| 265 | + del sys.modules[json_module_name] |
| 266 | + |
| 267 | + # Note: PyArrow doesn't have a public API to unregister types easily, |
| 268 | + # thus we are using the testing pattern of module isolation/reloading. |
| 269 | + |
| 270 | + |
| 271 | +def test_json_arrow_type_reregistration_is_handled(cleanup_json_module_for_reload): |
| 272 | + """ |
| 273 | + Verify that attempting to re-register JSONArrowType via module reload |
| 274 | + is caught by the except block and does not raise an error. |
| 275 | + """ |
| 276 | + |
| 277 | + try: |
| 278 | + # Re-importing the module after the fixture removed it from sys.modules |
| 279 | + # forces Python to execute the module's top-level code again. |
| 280 | + # This includes the pa.register_extension_type call. |
| 281 | + import db_dtypes.json # noqa: F401 |
| 282 | + |
| 283 | + assert ( |
| 284 | + True |
| 285 | + ), "Module re-import completed without error, except block likely worked." |
| 286 | + |
| 287 | + except pa.ArrowKeyError: |
| 288 | + # If this exception escapes, the except block in db_dtypes/json.py failed. |
| 289 | + pytest.fail( |
| 290 | + "pa.ArrowKeyError was raised during module reload, " |
| 291 | + "indicating the except block failed." |
| 292 | + ) |
| 293 | + except Exception as e: |
| 294 | + pytest.fail(f"An unexpected exception occurred during module reload: {e}") |
0 commit comments