diff --git a/CHANGELOG.md b/CHANGELOG.md index a7162423..b68ec37f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning]. ## [Unreleased] +## [0.2.6] - 2025-04-16 + +### Added in 0.2.6 + +- `SzEngine.why_search` + ## [0.2.5] - 2025-03-11 ### Changed in 0.2.5 diff --git a/docs/source/_static/.placeholder.txt b/docs/source/_static/.placeholder.txt new file mode 100644 index 00000000..e69de29b diff --git a/examples/szengine/why_search.py b/examples/szengine/why_search.py new file mode 100755 index 00000000..84b5729f --- /dev/null +++ b/examples/szengine/why_search.py @@ -0,0 +1,15 @@ +import json + +from senzing import SzEngineFlags, SzError + +from . import sz_engine + +try: + attributes = json.dumps({"NAME_FULL": "BOB SMITH", "EMAIL_ADDRESS": "bsmith@work.com"}) + ENTITY_ID = 1 + flags = SzEngineFlags.SZ_SEARCH_BY_ATTRIBUTES_DEFAULT_FLAGS + SEARCH_PROFILE = "SEARCH" + RESULT = sz_engine.why_search(attributes, ENTITY_ID, flags, SEARCH_PROFILE) + print(f"\n{RESULT}\n") +except SzError as err: + print(f"\nERROR: {err}\n") diff --git a/examples/szengine/why_search.txt b/examples/szengine/why_search.txt new file mode 100644 index 00000000..659843a2 --- /dev/null +++ b/examples/szengine/why_search.txt @@ -0,0 +1,20 @@ +// Output has been formatted for easier reading. +{ + "WHY_RESULTS": [ + { + "ENTITY_ID": 1, + "MATCH_INFO": { + "WHY_KEY": "+PNAME+EMAIL", + "WHY_ERRULE_CODE": "SF1", + "MATCH_LEVEL_CODE": "POSSIBLY_RELATED" + } + } + ], + "ENTITIES": [ + { + "RESOLVED_ENTITY": { + "ENTITY_ID": 1 + } + } + ] +} diff --git a/setup.cfg b/setup.cfg index 3ea8b440..3be83597 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = senzing -version = 0.2.5 +version = 0.2.6 author = senzing author_email = support@senzing.com description = Python SDK method definitions diff --git a/src/senzing/szengine.py b/src/senzing/szengine.py index a8de57f4..20f46385 100644 --- a/src/senzing/szengine.py +++ b/src/senzing/szengine.py @@ -932,6 +932,42 @@ def why_records( :language: json """ + @abstractmethod + def why_search( + self, + attributes: str, + entity_id: int, + flags: int = SzEngineFlags.SZ_SEARCH_BY_ATTRIBUTES_DEFAULT_FLAGS, + search_profile: str = "", + ) -> str: + """ + The `why_search` method retrieves entity data based on a specific entity Id and a + user-specified set of entity attributes. + + Args: + attributes (str): A JSON document with the attribute data to search for. + entity_id (int): The identifier of the entity to retrieve. + flags (int, optional): _description_. Defaults to SzEngineFlags.SZ_SEARCH_BY_ATTRIBUTES_DEFAULT_FLAGS. + search_profile (str): The name of a configured search profile. Defaults to SEARCH. + + Returns: + str: A JSON document. + + Raises: + + .. collapse:: Example: + + .. literalinclude:: ../../examples/szengine/why_search.py + :linenos: + :language: python + + **Output:** + + .. literalinclude:: ../../examples/szengine/why_search.txt + :linenos: + :language: json + """ + # ------------------------------------------------------------------------- # Convenience methods # ------------------------------------------------------------------------- diff --git a/src/senzing_mock/senzing_mock.py b/src/senzing_mock/senzing_mock.py index e4171e46..32bd0b09 100755 --- a/src/senzing_mock/senzing_mock.py +++ b/src/senzing_mock/senzing_mock.py @@ -328,6 +328,15 @@ def why_records( ) -> str: return "" + def why_search( + self, + attributes: str, + entity_id: int, + flags: int = SzEngineFlags.SZ_SEARCH_BY_ATTRIBUTES_DEFAULT_FLAGS, + search_profile: str = "", + ) -> str: + return "" + # ----------------------------------------------------------------------------- # SzProductMock class diff --git a/tests/szabstractfactory_test.py b/tests/szabstractfactory_test.py index 9978d97a..ce5be542 100755 --- a/tests/szabstractfactory_test.py +++ b/tests/szabstractfactory_test.py @@ -4,7 +4,6 @@ TODO: szabstractfactory_test.py """ - import pytest from senzing import ( @@ -17,55 +16,55 @@ from senzing_mock import SzAbstractFactoryMock # ----------------------------------------------------------------------------- -# SzAbstractFactory testcases +# Test cases # ----------------------------------------------------------------------------- -def test_create_configmanager(szabstractfactory: SzAbstractFactory) -> None: +def test_create_configmanager(sz_abstractfactory: SzAbstractFactory) -> None: """Test SzAbstractFactory.create_configmanager().""" - actual = szabstractfactory.create_configmanager() + actual = sz_abstractfactory.create_configmanager() assert isinstance(actual, SzConfigManager) -def test_create_diagnostic(szabstractfactory: SzAbstractFactory) -> None: +def test_create_diagnostic(sz_abstractfactory: SzAbstractFactory) -> None: """Test SzAbstractFactory.create_diagnostic().""" - actual = szabstractfactory.create_diagnostic() + actual = sz_abstractfactory.create_diagnostic() assert isinstance(actual, SzDiagnostic) -def test_create_engine(szabstractfactory: SzAbstractFactory) -> None: +def test_create_engine(sz_abstractfactory: SzAbstractFactory) -> None: """Test SzAbstractFactory.create_engine().""" - actual = szabstractfactory.create_engine() + actual = sz_abstractfactory.create_engine() assert isinstance(actual, SzEngine) -def test_create_product(szabstractfactory: SzAbstractFactory) -> None: +def test_create_product(sz_abstractfactory: SzAbstractFactory) -> None: """Test SzAbstractFactory.create_product().""" - actual = szabstractfactory.create_product() + actual = sz_abstractfactory.create_product() assert isinstance(actual, SzProduct) -def test_help_1(szabstractfactory: SzAbstractFactory) -> None: - """Test SzAbstractFactory().help().""" - szabstractfactory.help() +def test_help_1(sz_abstractfactory: SzAbstractFactory) -> None: + """Test SzAbstractFactory.help().""" + sz_abstractfactory.help() -def test_help_2(szabstractfactory: SzAbstractFactory) -> None: - """Test SzAbstractFactory().help(...).""" - szabstractfactory.help("create_configmanager") +def test_help_2(sz_abstractfactory: SzAbstractFactory) -> None: + """Test SzAbstractFactory.help(...).""" + sz_abstractfactory.help("create_configmanager") -def test_reinitialize(szabstractfactory: SzAbstractFactory) -> None: +def test_reinitialize(sz_abstractfactory: SzAbstractFactory) -> None: """Test SzAbstractFactory.reinitialize().""" - szabstractfactory.reinitialize(0) + sz_abstractfactory.reinitialize(0) # ----------------------------------------------------------------------------- -# SzAbstractFactory fixtures +# Fixtures # ----------------------------------------------------------------------------- -@pytest.fixture(name="szabstractfactory", scope="module") +@pytest.fixture(name="sz_abstractfactory", scope="function") def szabstractfactory_fixture() -> SzAbstractFactory: """ Single sz_abstractfactory object to use for all tests. diff --git a/tests/szconfig_test.py b/tests/szconfig_test.py index 0d231695..b177a5dd 100644 --- a/tests/szconfig_test.py +++ b/tests/szconfig_test.py @@ -4,7 +4,6 @@ TODO: szconfig_test.py """ - import pytest from senzing import SzConfig @@ -36,17 +35,17 @@ def test_get_data_sources(sz_config: SzConfig) -> None: def test_help_1(sz_config: SzConfig) -> None: - """Test SzConfig().help().""" + """Test SzConfig.help().""" sz_config.help() def test_help_2(sz_config: SzConfig) -> None: - """Test SzConfig().help(...).""" + """Test SzConfig.help(...).""" sz_config.help("add_data_source") # ----------------------------------------------------------------------------- -# szConfig fixtures +# Fixtures # ----------------------------------------------------------------------------- diff --git a/tests/szconfigmanager_test.py b/tests/szconfigmanager_test.py index 772c9a37..47e5e9bd 100644 --- a/tests/szconfigmanager_test.py +++ b/tests/szconfigmanager_test.py @@ -20,13 +20,13 @@ def test_create_config_from_config_id(sz_configmanager: SzConfigManager) -> None sz_configmanager.create_config_from_config_id(0) -def test_create_config_from_config_string(sz_configmanager: SzConfigManager) -> None: - """Test SzConfigManager.create_config_from_config_string().""" +def test_create_config_from_string(sz_configmanager: SzConfigManager) -> None: + """Test SzConfigManager.create_config_from_string().""" sz_configmanager.create_config_from_string("") -def test_create_config_from_config_template(sz_configmanager: SzConfigManager) -> None: - """Test SzConfigManager.create_config_from_config_string().""" +def test_create_config_from_template(sz_configmanager: SzConfigManager) -> None: + """Test SzConfigManager.create_config_from_template().""" sz_configmanager.create_config_from_template() @@ -41,17 +41,17 @@ def test_get_default_config_id(sz_configmanager: SzConfigManager) -> None: def test_help_1(sz_configmanager: SzConfigManager) -> None: - """Test SzConfigManager().help().""" + """Test SzConfigManager.help().""" sz_configmanager.help() def test_help_2(sz_configmanager: SzConfigManager) -> None: - """Test SzConfigManager().help(...).""" + """Test SzConfigManager.help(...).""" sz_configmanager.help("register_config") def test_register_config(sz_configmanager: SzConfigManager) -> None: - """Test SzConfigManager.add_config().""" + """Test SzConfigManager.register_config().""" sz_configmanager.register_config("", "") @@ -71,7 +71,7 @@ def test_set_default_config_id(sz_configmanager: SzConfigManager) -> None: # ----------------------------------------------------------------------------- -# SzConfigManager fixtures +# Fixtures # ----------------------------------------------------------------------------- diff --git a/tests/szdiagnostic_test.py b/tests/szdiagnostic_test.py index 667644d5..5e9920ad 100644 --- a/tests/szdiagnostic_test.py +++ b/tests/szdiagnostic_test.py @@ -15,47 +15,51 @@ def test_check_datastore_performance(sz_diagnostic: SzDiagnostic) -> None: - """Test SzDiagnosic().check_datastore_performance().""" + """Test SzDiagnostic.check_datastore_performance().""" sz_diagnostic.check_datastore_performance(0) -# def test_destroy(sz_diagnostic: SzDiagnostic) -> None: -# """Test SzDiagnosic().destroy().""" -# sz_diagnostic.destroy() - - def test_get_datastore_info(sz_diagnostic: SzDiagnostic) -> None: - """Test SzDiagnosic().get_datastore_info().""" + """Test SzDiagnostic.get_datastore_info().""" sz_diagnostic.get_datastore_info() def test_get_feature(sz_diagnostic: SzDiagnostic) -> None: - """Test SzDiagnosic().get_datastore_info().""" + """Test SzDiagnostic.get_feature().""" sz_diagnostic.get_feature(0) def test_help_1(sz_diagnostic: SzDiagnostic) -> None: - """Test SzDiagnosic().help().""" + """Test SzDiagnostic.help().""" sz_diagnostic.help() def test_help_2(sz_diagnostic: SzDiagnostic) -> None: - """Test SzDiagnosic().help(...).""" + """Test SzDiagnostic.help(...).""" sz_diagnostic.help("check_datastore_performance") +# ----------------------------------------------------------------------------- +# Unique testcases +# ----------------------------------------------------------------------------- + # def test_initialize(sz_diagnostic: SzDiagnostic) -> None: -# """Test SzDiagnosic().initialize().""" +# """Test SzDiagnostic.initialize().""" # sz_diagnostic.initialize("", "") +# def test_destroy(sz_diagnostic: SzDiagnostic) -> None: +# """Test SzDiagnostic.destroy().""" +# sz_diagnostic.destroy() + + def test_purge_repository(sz_diagnostic: SzDiagnostic) -> None: - """Test SzDiagnosic().purge_repository().""" + """Test SzDiagnostic.purge_repository().""" sz_diagnostic.purge_repository() # ----------------------------------------------------------------------------- -# SzDiagnostic fixtures +# Fixtures # ----------------------------------------------------------------------------- diff --git a/tests/szengine_test.py b/tests/szengine_test.py index fa2ab3e3..a3644bbb 100644 --- a/tests/szengine_test.py +++ b/tests/szengine_test.py @@ -16,177 +16,187 @@ def test_add_record(sz_engine: SzEngine) -> None: - """Test SzEngine().add_record().""" + """Test SzEngine.add_record().""" sz_engine.add_record("", "", "") def test_close_export(sz_engine: SzEngine) -> None: - """Test SzEngine().close_export().""" + """Test SzEngine.close_export().""" sz_engine.close_export(0) def test_count_redo_records(sz_engine: SzEngine) -> None: - """Test SzEngine().count_redo_records().""" + """Test SzEngine.count_redo_records().""" sz_engine.count_redo_records() def test_delete_record(sz_engine: SzEngine) -> None: - """Test SzEngine().delete_record().""" + """Test SzEngine.delete_record().""" sz_engine.delete_record("", "") -# def test_destroy(sz_engine: SzEngine) -> None: -# """Test SzEngine().destroy().""" -# sz_engine.destroy() - - def test_export_csv_entity_report(sz_engine: SzEngine) -> None: - """Test SzEngine().export_csv_entity_report().""" + """Test SzEngine.export_csv_entity_report().""" sz_engine.export_csv_entity_report("") def test_export_json_entity_report(sz_engine: SzEngine) -> None: - """Test SzEngine().export_json_entity_report().""" + """Test SzEngine.export_json_entity_report().""" sz_engine.export_json_entity_report() def test_fetch_next(sz_engine: SzEngine) -> None: - """Test SzEngine().fetch_next().""" + """Test SzEngine.fetch_next().""" sz_engine.fetch_next(0) def test_find_interesting_entities_by_entity_id(sz_engine: SzEngine) -> None: - """Test SzEngine().find_interesting_entities_by_entity_id().""" + """Test SzEngine.find_interesting_entities_by_entity_id().""" sz_engine.find_interesting_entities_by_entity_id(0) def test_find_interesting_entities_by_record_id(sz_engine: SzEngine) -> None: - """Test SzEngine().find_interesting_entities_by_record_id().""" + """Test SzEngine.find_interesting_entities_by_record_id().""" sz_engine.find_interesting_entities_by_record_id("", "") def test_find_network_by_entity_id(sz_engine: SzEngine) -> None: - """Test SzEngine().find_network_by_entity_id().""" + """Test SzEngine.find_network_by_entity_id().""" sz_engine.find_network_by_entity_id([], 0, 0, 0) def test_find_network_by_record_id(sz_engine: SzEngine) -> None: - """Test SzEngine().find_network_by_record_id().""" + """Test SzEngine.find_network_by_record_id().""" sz_engine.find_network_by_record_id([], 0, 0, 0) def test_find_path_by_entity_id(sz_engine: SzEngine) -> None: - """Test SzEngine().find_path_by_entity_id().""" + """Test SzEngine.find_path_by_entity_id().""" sz_engine.find_path_by_entity_id(0, 0, 0) def test_find_path_by_record_id(sz_engine: SzEngine) -> None: - """Test SzEngine().find_path_by_record_id().""" + """Test SzEngine.find_path_by_record_id().""" sz_engine.find_path_by_record_id("", "", "", "", 0) def test_get_active_config_id(sz_engine: SzEngine) -> None: - """Test SzEngine().get_active_config_id().""" + """Test SzEngine.get_active_config_id().""" sz_engine.get_active_config_id() def test_get_entity_by_entity_id(sz_engine: SzEngine) -> None: - """Test SzEngine().get_entity_by_entity_id().""" + """Test SzEngine.get_entity_by_entity_id().""" sz_engine.get_entity_by_entity_id(0) def test_get_entity_by_record_id(sz_engine: SzEngine) -> None: - """Test SzEngine().get_entity_by_record_id().""" + """Test SzEngine.get_entity_by_record_id().""" sz_engine.get_entity_by_record_id("", "") def test_get_record(sz_engine: SzEngine) -> None: - """Test SzEngine().get_record().""" + """Test SzEngine.get_record().""" sz_engine.get_record("", "") def test_get_redo_record(sz_engine: SzEngine) -> None: - """Test SzEngine().get_redo_record().""" + """Test SzEngine.get_redo_record().""" sz_engine.get_redo_record() def test_get_stats(sz_engine: SzEngine) -> None: - """Test SzEngine().stats().""" + """Test SzEngine.get_stats().""" sz_engine.get_stats() def test_get_virtual_entity_by_record_id(sz_engine: SzEngine) -> None: - """Test SzEngine().get_virtual_entity_by_record_id().""" + """Test SzEngine.get_virtual_entity_by_record_id().""" sz_engine.get_virtual_entity_by_record_id([]) def test_help_1(sz_engine: SzEngine) -> None: - """Test SzEngine().help().""" + """Test SzEngine.help().""" sz_engine.help() def test_help_2(sz_engine: SzEngine) -> None: - """Test SzEngine().help(...).""" + """Test SzEngine.help(...).""" sz_engine.help("get_stats") def test_how_entity_by_entity_id(sz_engine: SzEngine) -> None: - """Test SzEngine().how_entity_by_entity_id().""" + """Test SzEngine.how_entity_by_entity_id().""" sz_engine.how_entity_by_entity_id(0) -# def test_initialize(sz_engine: SzEngine) -> None: -# """Test SzEngine().init().""" -# sz_engine.initialize("", "") - - def test_preprocess_record(sz_engine: SzEngine) -> None: - """Test SzEngine().preprocess_record().""" + """Test SzEngine.preprocess_record().""" sz_engine.preprocess_record("") def test_prime_engine(sz_engine: SzEngine) -> None: - """Test SzEngine().prime_engine().""" + """Test SzEngine.prime_engine().""" sz_engine.prime_engine() def test_process_redo_record(sz_engine: SzEngine) -> None: - """Test SzEngine().process_redo_record().""" + """Test SzEngine.process_redo_record().""" sz_engine.process_redo_record("") def test_reevaluate_entity(sz_engine: SzEngine) -> None: - """Test SzEngine().reevaluate_entity().""" + """Test SzEngine.reevaluate_entity().""" sz_engine.reevaluate_entity(0) def test_reevaluate_record(sz_engine: SzEngine) -> None: - """Test SzEngine().reevaluate_record().""" + """Test SzEngine.reevaluate_record().""" sz_engine.reevaluate_record("", "") def test_search_by_attributes(sz_engine: SzEngine) -> None: - """Test SzEngine().search_by_attributes().""" + """Test SzEngine.search_by_attributes().""" sz_engine.search_by_attributes("") def test_why_entities(sz_engine: SzEngine) -> None: - """Test SzEngine().why_entities().""" + """Test SzEngine.why_entities().""" sz_engine.why_entities(0, 0) def test_why_record_in_entity(sz_engine: SzEngine) -> None: - """Test SzEngine().why_record_in_entity().""" + """Test SzEngine.why_record_in_entity().""" sz_engine.why_record_in_entity("", "") def test_why_records(sz_engine: SzEngine) -> None: - """Test SzEngine().why_records().""" + """Test SzEngine.why_records().""" sz_engine.why_records("", "", "", "") +def test_why_search(sz_engine: SzEngine) -> None: + """Test SzEngine.why_search().""" + sz_engine.why_search("", 0) + + +# ----------------------------------------------------------------------------- +# Unique testcases +# ----------------------------------------------------------------------------- + + +# def test_initialize(sz_engine: SzEngine) -> None: +# """Test SzEngine.initialize().""" +# sz_engine.initialize("", "") + + +# def test_destroy(sz_engine: SzEngine) -> None: +# """Test SzEngine.destroy().""" +# sz_engine.destroy() + + # ----------------------------------------------------------------------------- -# SzEngine fixtures +# Fixtures # ----------------------------------------------------------------------------- diff --git a/tests/szproduct_test.py b/tests/szproduct_test.py index e1f7c75e..889a728b 100644 --- a/tests/szproduct_test.py +++ b/tests/szproduct_test.py @@ -15,38 +15,43 @@ # ----------------------------------------------------------------------------- -# def test_destroy(sz_product: SzProduct) -> None: -# """Test SzProduct().destroy().""" -# sz_product.destroy() - - -# def test_initialize(sz_product: SzProduct) -> None: -# """Test SzProduct().initialize().""" -# sz_product.initialize("", "") - - def test_get_license(sz_product: SzProduct) -> None: - """Test SzProduct().get_license().""" + """Test SzProduct.get_license().""" sz_product.get_license() def test_get_version(sz_product: SzProduct) -> None: - """Test SzProduct().get_version().""" + """Test SzProduct.get_version().""" sz_product.get_version() def test_help_1(sz_product: SzProduct) -> None: - """Test SzProduct().help().""" + """Test SzProduct.help().""" sz_product.help() def test_help_2(sz_product: SzProduct) -> None: - """Test SzProduct().help(...).""" + """Test SzProduct.help(...).""" sz_product.help("get_license") # ----------------------------------------------------------------------------- -# SzConfig fixtures +# Unique testcases +# ----------------------------------------------------------------------------- + + +# def test_initialize(sz_product: SzProduct) -> None: +# """Test SzProduct.initialize().""" +# sz_product.initialize("", "") + + +# def test_destroy(sz_product: SzProduct) -> None: +# """Test SzProduct.destroy().""" +# sz_product.destroy() + + +# ----------------------------------------------------------------------------- +# Fixtures # -----------------------------------------------------------------------------