Skip to content

Commit 5b7948f

Browse files
authored
269 ant 1 (#272)
* #269 - Save point * #269 - Save point * #269 - Save point * #269 - Save point * #269 - Save point * #269 - Save point * #269 - Save point * #269 - Work around not needing typing_extensions * #269 - Type fix * #269 - Type fix * #269 - Type fix
1 parent 589b52a commit 5b7948f

File tree

4 files changed

+35
-25
lines changed

4 files changed

+35
-25
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning].
77

88
## [Unreleased]
99

10+
## [0.3.13] - 2025-06-10
11+
12+
### Changed in 0.3.13
13+
14+
- To be consistent with Sz engine and orjson, if json.dumps() is used (orjson not available) in _helpers.py don't add spaces after : and , separators
15+
16+
### Removed in 0.3.13
17+
18+
- `from typing_extensions import ...` in _helpers.py is removed to simplify product requirements
19+
1020
## [0.3.12] - 2025-05-21
1121

1222
### Added in 0.3.12

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = senzing_core
3-
version = 0.3.12
3+
version = 0.3.13
44
author = senzing
55
author_email = support@senzing.com
66
description = Senzing Python SDK

src/senzing_core/_helpers.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
SDK Helper functions
33
"""
44

5-
# NOTE This is to prevent TypeError: '_ctypes.PyCPointerType' object is not subscriptable
6-
# on _Pointer[c_char]) for FreeCResources
7-
# ctypes._Pointer is generic for type checkers, but at runtime it's not generic, so annotations
8-
# import is necessary - or string annotation ("_Pointer[c_char]") .
5+
# NOTE - This is to prevent TypeError: '_ctypes.PyCPointerType' object is not subscriptable on _Pointer[c_char]) for
6+
# NOTE - FreeCResources ctypes._Pointer is generic for type checkers, but at runtime it's not generic, so annotations
7+
# NOTE - import is necessary - or string annotation ("_Pointer[c_char]") .
98
from __future__ import annotations
109

1110
import platform
12-
import sys
1311
import threading
12+
from collections.abc import Callable
1413
from contextlib import suppress
1514
from ctypes import (
1615
CDLL,
@@ -28,30 +27,30 @@
2827
from ctypes.util import find_library
2928
from functools import wraps
3029
from types import TracebackType
31-
from typing import Any, Callable, Dict, List, Optional, Type, TypeVar, Union
30+
from typing import Any, Dict, List, Optional, Type, TypeVar, Union
31+
from typing import cast as typing_cast
3232

3333
from senzing import ENGINE_EXCEPTION_MAP, SzError, SzSdkError
3434

3535
try:
36-
import orjson
36+
import orjson # type: ignore[import-not-found, unused-ignore]
3737

3838
def _json_dumps(object_: Any) -> str:
39-
return orjson.dumps(object_).decode("utf-8")
39+
return orjson.dumps(object_).decode("utf-8") # type: ignore[no-any-return, unused-ignore]
4040

4141
except ImportError:
4242
import json
4343

44+
# NOTE - separators= is used to be consistent with Sz engine and orjson output
4445
def _json_dumps(object_: Any) -> str:
45-
return json.dumps(object_, ensure_ascii=False)
46+
return json.dumps(object_, ensure_ascii=False, separators=(",", ":"))
4647

4748

48-
if sys.version_info < (3, 11):
49-
from typing_extensions import ParamSpec, Self
50-
else:
51-
from typing import ParamSpec, Self
52-
53-
T = TypeVar("T")
54-
P = ParamSpec("P")
49+
# NOTE - Using earlier Python version typing to support v3.9 still and not rely on typing_extensions.
50+
# NOTE - F can be changed to use ParamSpec when no longer need to support v3.9.
51+
# NOTE - SelfFreeCResources can be changed to use Self at v3.11.
52+
F = TypeVar("F", bound=Callable[..., Any])
53+
SelfFreeCResources = TypeVar("SelfFreeCResources", bound="FreeCResources")
5554

5655
START_DSRC_JSON = '{"DATA_SOURCES": ['
5756
START_ENTITIES_JSON = '{"ENTITIES": ['
@@ -74,7 +73,7 @@ def __init__(self, handle: CDLL, resource: _Pointer[c_char]) -> None:
7473
self.handle = handle
7574
self.resource = resource
7675

77-
def __enter__(self) -> Self:
76+
def __enter__(self: SelfFreeCResources) -> SelfFreeCResources:
7877
return self
7978

8079
def __exit__(
@@ -91,7 +90,8 @@ def __exit__(
9190
# -----------------------------------------------------------------------------
9291

9392

94-
def catch_sdk_exceptions(func_to_decorate: Callable[P, T]) -> Callable[P, T]:
93+
# def catch_sdk_exceptions(func_to_decorate: Callable[P, T]) -> Callable[P, T]:
94+
def catch_sdk_exceptions(func_to_decorate: F) -> F:
9595
"""
9696
The Python SDK methods convert Python types to ctypes and utilize helper functions. If incorrect types/values are
9797
used standard library exceptions are raised not SzError exceptions as the Senzing library hasn't been called
@@ -103,9 +103,9 @@ def catch_sdk_exceptions(func_to_decorate: Callable[P, T]) -> Callable[P, T]:
103103
"""
104104

105105
@wraps(func_to_decorate)
106-
def wrapped_func(*args: P.args, **kwargs: P.kwargs) -> T:
106+
def wrapped_func(*args: Any, **kwargs: Any) -> F:
107107
try:
108-
return func_to_decorate(*args, **kwargs)
108+
return typing_cast(F, func_to_decorate(*args, **kwargs))
109109
except (ArgumentError, TypeError, ValueError) as err:
110110
# Get wrapped function annotation, remove unwanted keys
111111
annotations_dict = func_to_decorate.__annotations__
@@ -132,7 +132,7 @@ def wrapped_func(*args: P.args, **kwargs: P.kwargs) -> T:
132132

133133
raise SzSdkError(err) from err
134134

135-
return wrapped_func
135+
return typing_cast(F, wrapped_func)
136136

137137

138138
# -----------------------------------------------------------------------------
@@ -160,7 +160,7 @@ def load_sz_library(lib: str = "", os: str = "") -> CDLL:
160160

161161
raise SzSdkError(f"{system_name} is an unsupported operating system")
162162
except OSError as err:
163-
# TODO Wording & links for V4
163+
# TODO - Wording & links for V4
164164
print(
165165
f"ERROR: Unable to load the Senzing library: {err}\n"
166166
" Did you remember to setup your environment by sourcing the setupEnv file?\n"

tests/helpers_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ def test_as_str() -> None:
4141
"test2": 5,
4242
"test3": {"test3.1": "Wilma"},
4343
}
44-
# NOTE replace() is needed, dumps() adds spaces but as_str() doesn't
45-
actual = json.dumps(a_dict).replace(" ", "")
44+
# NOTE - separators= is used to be consistent with Sz engine and orjson output as used in _helpers.py
45+
actual = json.dumps(a_dict, separators=(",", ":"))
4646
result1 = as_str(a_dict)
4747
assert isinstance(result1, str)
4848
assert result1 == actual

0 commit comments

Comments
 (0)