Skip to content

Commit 921482f

Browse files
committed
fix: updates json array registration
1 parent 158243b commit 921482f

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

db_dtypes/json.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -277,5 +277,10 @@ def to_pandas_dtype(self):
277277

278278

279279
# Register the type to be included in RecordBatches, sent over IPC and received in
280-
# another Python process.
281-
pa.register_extension_type(JSONArrowType())
280+
# another Python process. Also handle potential pre-registration
281+
try:
282+
pa.register_extension_type(JSONArrowType())
283+
except pa.ArrowKeyError:
284+
# Type 'dbjson' might already be registered if the module is reloaded,
285+
# which is okay.
286+
pass

tests/unit/test_json.py

+68
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
import json
16+
import sys
1617

1718
import numpy as np
1819
import pandas as pd
@@ -224,3 +225,70 @@ def test_json_arrow_record_batch():
224225
== '{"null_field":null,"order":{"address":{"city":"Anytown","street":"123 Main St"},"items":["book","pen","computer"],"total":15}}'
225226
)
226227
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

Comments
 (0)