Skip to content

Commit 35c5120

Browse files
committed
Merge branch '42-log-callback' into dev
2 parents 1fda1c8 + a12d57c commit 35c5120

File tree

5 files changed

+56
-2
lines changed

5 files changed

+56
-2
lines changed

.gitlab-ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ test:linux:aarch64:
5858

5959
test:mac:x64:
6060
extends: .test
61+
script:
62+
- python3 -m venv .venv
63+
- source .venv/bin/activate
64+
- python3 -m pip install pytest
65+
- rm -r objectbox # todo this is ugly; let's copy required files in a sub-folder instead?
66+
- pip3 install --force-reinstall dist/*.whl # Artifacts from the previous stage (downloaded by default)
67+
- python -m pytest
6168
tags: [mac, x64, shell, python3]
6269

6370
test:windows:x64:

objectbox/c.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ def shlib_name(library: str) -> str:
8484
OBXValidateOnOpenPagesFlags = ctypes.c_int
8585
OBXValidateOnOpenKvFlags = ctypes.c_int
8686
OBXBackupRestoreFlags = ctypes.c_int
87+
OBXLogLevel = ctypes.c_int
88+
89+
from enum import IntEnum
90+
class LogLevel(IntEnum):
91+
Verbose = 10
92+
Debug = 20
93+
Info = 30
94+
Warn = 40
95+
Error = 50
8796

8897
class DebugFlags(IntEnum):
8998
"""Debug flags"""
@@ -563,8 +572,11 @@ def c_array_pointer(py_list: Union[List[Any], np.ndarray], c_type):
563572
# OBX_C_API void obx_opt_async_object_bytes_max_size_to_cache(OBX_store_options* opt, uint64_t value);
564573
obx_opt_async_object_bytes_max_size_to_cache = c_fn('obx_opt_async_object_bytes_max_size_to_cache', None, [OBX_store_options_p, ctypes.c_uint64])
565574

575+
#typedef void obx_log_callback(OBXLogLevel log_level, const char* message, size_t message_size, void* user_data);
576+
obx_log_callback_fn = ctypes.CFUNCTYPE(None, OBXLogLevel, ctypes.c_char_p, ctypes.c_size_t, ctypes.c_voidp)
577+
566578
# OBX_C_API void obx_opt_log_callback(OBX_store_options* opt, obx_log_callback* callback, void* user_data);
567-
# obx_opt_log_callback = c_fn('obx_opt_log_callback', None, [OBX_store_options_p, ...]) TODO
579+
obx_opt_log_callback = c_fn('obx_opt_log_callback', None, [OBX_store_options_p, obx_log_callback_fn, ctypes.c_voidp])
568580

569581
# OBX_C_API void obx_opt_backup_restore(OBX_store_options* opt, const char* backup_file, uint32_t flags);
570582
obx_opt_backup_restore = c_fn('obx_opt_backup_restore', None, [OBX_store_options_p, ctypes.c_char_p, OBXBackupRestoreFlags])

objectbox/store.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def __init__(self,
5555
async_minor_refill_max_count: Optional[int] = None,
5656
async_object_bytes_max_cache_size: Optional[int] = None,
5757
async_object_bytes_max_size_to_cache: Optional[int] = None,
58+
log_callback: Callable[[c.OBXLogLevel, str],None] = None,
5859
c_store: Optional[c.OBX_store_p] = None):
5960

6061
"""Opens an ObjectBox database Store
@@ -118,6 +119,8 @@ def __init__(self,
118119
Total cache size. Defaults to 0.5 mega bytes.
119120
:param async_object_bytes_max_size_to_cache:
120121
Maximum size for an object to be cached.
122+
:param log_callback:
123+
Callback function for logging with the parameters, OBXLogLevel and message.
121124
:param c_store:
122125
Internal parameter for deprecated ObjectBox interface. Do not use it; other options would be ignored if passed.
123126
"""
@@ -175,6 +178,8 @@ def __init__(self,
175178
options.async_object_bytes_max_cache_size(async_object_bytes_max_cache_size)
176179
if async_object_bytes_max_size_to_cache is not None:
177180
options.async_object_bytes_max_size_to_cache(async_object_bytes_max_size_to_cache)
181+
if log_callback is not None:
182+
options.log_callback(log_callback)
178183

179184
except c.CoreException:
180185
options._free()

objectbox/store_options.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,10 @@ def async_object_bytes_max_cache_size(self, value: int):
112112
def async_object_bytes_max_size_to_cache(self, value: int):
113113
obx_opt_async_object_bytes_max_size_to_cache(self._c_handle, value)
114114

115-
# TODO def log_callback(self):
115+
def log_callback(self, value: Callable[[OBXLogLevel, str],None]):
116+
self._c_log_cb = obx_log_callback_fn(lambda level, message, size, userdata: value(level, message.decode('utf-8')))
117+
obx_opt_log_callback(self._c_handle, self._c_log_cb, None)
118+
return self
116119

117120
def backup_restore(self, backup_file: str, flags: OBXBackupRestoreFlags):
118121
raise NotImplementedError # TODO

tests/test_store_options.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,30 @@ def test_store_with_options():
7878
async_object_bytes_max_size_to_cache=100<<10
7979
)
8080
store.close()
81+
82+
def test_log_callback():
83+
Store.remove_db_files("testdata")
84+
remove_json_model_file()
85+
86+
log_entries = []
87+
88+
def mylog(level: OBXLogLevel, message: str):
89+
levelText = "?"
90+
if level == LogLevel.Debug:
91+
levelText = "DEBUG"
92+
print(f"MYLOG: {levelText} {message}")
93+
log_entries.append( (level, message) )
94+
95+
store = Store(
96+
model=create_default_model(),
97+
directory="testdata",
98+
log_callback=mylog
99+
)
100+
101+
box = store.box(TestEntity)
102+
assert len(log_entries) == 2
103+
assert log_entries[0][0] == LogLevel.Debug
104+
assert log_entries[0][1].startswith("Opening store:")
105+
assert log_entries[1][0] == LogLevel.Debug
106+
assert log_entries[1][1].startswith("Opening store:")
107+

0 commit comments

Comments
 (0)