bb-integrations-library 3.0.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bb_integrations_lib/__init__.py +0 -0
- bb_integrations_lib/converters/__init__.py +0 -0
- bb_integrations_lib/gravitate/__init__.py +0 -0
- bb_integrations_lib/gravitate/base_api.py +20 -0
- bb_integrations_lib/gravitate/model.py +29 -0
- bb_integrations_lib/gravitate/pe_api.py +122 -0
- bb_integrations_lib/gravitate/rita_api.py +552 -0
- bb_integrations_lib/gravitate/sd_api.py +572 -0
- bb_integrations_lib/gravitate/testing/TTE/sd/models.py +1398 -0
- bb_integrations_lib/gravitate/testing/TTE/sd/tests/test_models.py +2987 -0
- bb_integrations_lib/gravitate/testing/__init__.py +0 -0
- bb_integrations_lib/gravitate/testing/builder.py +55 -0
- bb_integrations_lib/gravitate/testing/openapi.py +70 -0
- bb_integrations_lib/gravitate/testing/util.py +274 -0
- bb_integrations_lib/mappers/__init__.py +0 -0
- bb_integrations_lib/mappers/prices/__init__.py +0 -0
- bb_integrations_lib/mappers/prices/model.py +106 -0
- bb_integrations_lib/mappers/prices/price_mapper.py +127 -0
- bb_integrations_lib/mappers/prices/protocol.py +20 -0
- bb_integrations_lib/mappers/prices/util.py +61 -0
- bb_integrations_lib/mappers/rita_mapper.py +523 -0
- bb_integrations_lib/models/__init__.py +0 -0
- bb_integrations_lib/models/dtn_supplier_invoice.py +487 -0
- bb_integrations_lib/models/enums.py +28 -0
- bb_integrations_lib/models/pipeline_structs.py +76 -0
- bb_integrations_lib/models/probe/probe_event.py +20 -0
- bb_integrations_lib/models/probe/request_data.py +431 -0
- bb_integrations_lib/models/probe/resume_token.py +7 -0
- bb_integrations_lib/models/rita/audit.py +113 -0
- bb_integrations_lib/models/rita/auth.py +30 -0
- bb_integrations_lib/models/rita/bucket.py +17 -0
- bb_integrations_lib/models/rita/config.py +188 -0
- bb_integrations_lib/models/rita/constants.py +19 -0
- bb_integrations_lib/models/rita/crossroads_entities.py +293 -0
- bb_integrations_lib/models/rita/crossroads_mapping.py +428 -0
- bb_integrations_lib/models/rita/crossroads_monitoring.py +78 -0
- bb_integrations_lib/models/rita/crossroads_network.py +41 -0
- bb_integrations_lib/models/rita/crossroads_rules.py +80 -0
- bb_integrations_lib/models/rita/email.py +39 -0
- bb_integrations_lib/models/rita/issue.py +63 -0
- bb_integrations_lib/models/rita/mapping.py +227 -0
- bb_integrations_lib/models/rita/probe.py +58 -0
- bb_integrations_lib/models/rita/reference_data.py +110 -0
- bb_integrations_lib/models/rita/source_system.py +9 -0
- bb_integrations_lib/models/rita/workers.py +76 -0
- bb_integrations_lib/models/sd/bols_and_drops.py +241 -0
- bb_integrations_lib/models/sd/get_order.py +301 -0
- bb_integrations_lib/models/sd/orders.py +18 -0
- bb_integrations_lib/models/sd_api.py +115 -0
- bb_integrations_lib/pipelines/__init__.py +0 -0
- bb_integrations_lib/pipelines/parsers/__init__.py +0 -0
- bb_integrations_lib/pipelines/parsers/distribution_report/__init__.py +0 -0
- bb_integrations_lib/pipelines/parsers/distribution_report/order_by_site_product_parser.py +50 -0
- bb_integrations_lib/pipelines/parsers/distribution_report/tank_configs_parser.py +47 -0
- bb_integrations_lib/pipelines/parsers/dtn/__init__.py +0 -0
- bb_integrations_lib/pipelines/parsers/dtn/dtn_price_parser.py +102 -0
- bb_integrations_lib/pipelines/parsers/dtn/model.py +79 -0
- bb_integrations_lib/pipelines/parsers/price_engine/__init__.py +0 -0
- bb_integrations_lib/pipelines/parsers/price_engine/parse_accessorials_prices_parser.py +67 -0
- bb_integrations_lib/pipelines/parsers/price_engine/price_file_upload/__init__.py +0 -0
- bb_integrations_lib/pipelines/parsers/price_engine/price_file_upload/price_merge_parser.py +111 -0
- bb_integrations_lib/pipelines/parsers/price_engine/price_file_upload/price_sync_parser.py +107 -0
- bb_integrations_lib/pipelines/parsers/price_engine/price_file_upload/shared.py +81 -0
- bb_integrations_lib/pipelines/parsers/tank_reading_parser.py +155 -0
- bb_integrations_lib/pipelines/parsers/tank_sales_parser.py +144 -0
- bb_integrations_lib/pipelines/shared/__init__.py +0 -0
- bb_integrations_lib/pipelines/shared/allocation_matching.py +227 -0
- bb_integrations_lib/pipelines/shared/bol_allocation.py +2793 -0
- bb_integrations_lib/pipelines/steps/__init__.py +0 -0
- bb_integrations_lib/pipelines/steps/create_accessorials_step.py +80 -0
- bb_integrations_lib/pipelines/steps/distribution_report/__init__.py +0 -0
- bb_integrations_lib/pipelines/steps/distribution_report/distribution_report_datafram_to_raw_data.py +33 -0
- bb_integrations_lib/pipelines/steps/distribution_report/get_model_history_step.py +50 -0
- bb_integrations_lib/pipelines/steps/distribution_report/get_order_by_site_product_step.py +62 -0
- bb_integrations_lib/pipelines/steps/distribution_report/get_tank_configs_step.py +40 -0
- bb_integrations_lib/pipelines/steps/distribution_report/join_distribution_order_dos_step.py +85 -0
- bb_integrations_lib/pipelines/steps/distribution_report/upload_distribution_report_datafram_to_big_query.py +47 -0
- bb_integrations_lib/pipelines/steps/echo_step.py +14 -0
- bb_integrations_lib/pipelines/steps/export_dataframe_to_rawdata_step.py +28 -0
- bb_integrations_lib/pipelines/steps/exporting/__init__.py +0 -0
- bb_integrations_lib/pipelines/steps/exporting/bbd_export_payroll_file_step.py +107 -0
- bb_integrations_lib/pipelines/steps/exporting/bbd_export_readings_step.py +236 -0
- bb_integrations_lib/pipelines/steps/exporting/cargas_wholesale_bundle_upload_step.py +33 -0
- bb_integrations_lib/pipelines/steps/exporting/dataframe_flat_file_export.py +29 -0
- bb_integrations_lib/pipelines/steps/exporting/gcs_bucket_export_file_step.py +34 -0
- bb_integrations_lib/pipelines/steps/exporting/keyvu_export_step.py +356 -0
- bb_integrations_lib/pipelines/steps/exporting/pe_price_export_step.py +238 -0
- bb_integrations_lib/pipelines/steps/exporting/platform_science_order_sync_step.py +500 -0
- bb_integrations_lib/pipelines/steps/exporting/save_rawdata_to_disk.py +15 -0
- bb_integrations_lib/pipelines/steps/exporting/sftp_export_file_step.py +60 -0
- bb_integrations_lib/pipelines/steps/exporting/sftp_export_many_files_step.py +23 -0
- bb_integrations_lib/pipelines/steps/exporting/update_exported_orders_table_step.py +64 -0
- bb_integrations_lib/pipelines/steps/filter_step.py +22 -0
- bb_integrations_lib/pipelines/steps/get_latest_sync_date.py +34 -0
- bb_integrations_lib/pipelines/steps/importing/bbd_import_payroll_step.py +30 -0
- bb_integrations_lib/pipelines/steps/importing/get_order_numbers_to_export_step.py +138 -0
- bb_integrations_lib/pipelines/steps/importing/load_file_to_dataframe_step.py +46 -0
- bb_integrations_lib/pipelines/steps/importing/load_imap_attachment_step.py +172 -0
- bb_integrations_lib/pipelines/steps/importing/pe_bulk_sync_price_structure_step.py +68 -0
- bb_integrations_lib/pipelines/steps/importing/pe_price_merge_step.py +86 -0
- bb_integrations_lib/pipelines/steps/importing/sftp_file_config_step.py +124 -0
- bb_integrations_lib/pipelines/steps/importing/test_exact_file_match.py +57 -0
- bb_integrations_lib/pipelines/steps/null_step.py +15 -0
- bb_integrations_lib/pipelines/steps/pe_integration_job_step.py +32 -0
- bb_integrations_lib/pipelines/steps/processing/__init__.py +0 -0
- bb_integrations_lib/pipelines/steps/processing/archive_gcs_step.py +76 -0
- bb_integrations_lib/pipelines/steps/processing/archive_sftp_step.py +48 -0
- bb_integrations_lib/pipelines/steps/processing/bbd_format_tank_readings_step.py +492 -0
- bb_integrations_lib/pipelines/steps/processing/bbd_upload_prices_step.py +54 -0
- bb_integrations_lib/pipelines/steps/processing/bbd_upload_tank_sales_step.py +124 -0
- bb_integrations_lib/pipelines/steps/processing/bbd_upload_tankreading_step.py +80 -0
- bb_integrations_lib/pipelines/steps/processing/convert_bbd_order_to_cargas_step.py +226 -0
- bb_integrations_lib/pipelines/steps/processing/delete_sftp_step.py +33 -0
- bb_integrations_lib/pipelines/steps/processing/dtn/__init__.py +2 -0
- bb_integrations_lib/pipelines/steps/processing/dtn/convert_dtn_invoice_to_sd_model.py +145 -0
- bb_integrations_lib/pipelines/steps/processing/dtn/parse_dtn_invoice_step.py +38 -0
- bb_integrations_lib/pipelines/steps/processing/file_config_parser_step.py +720 -0
- bb_integrations_lib/pipelines/steps/processing/file_config_parser_step_v2.py +418 -0
- bb_integrations_lib/pipelines/steps/processing/get_sd_price_price_request.py +105 -0
- bb_integrations_lib/pipelines/steps/processing/keyvu_upload_deliveryplan_step.py +39 -0
- bb_integrations_lib/pipelines/steps/processing/mark_orders_exported_in_bbd_step.py +185 -0
- bb_integrations_lib/pipelines/steps/processing/pe_price_rows_processing_step.py +174 -0
- bb_integrations_lib/pipelines/steps/processing/send_process_report_step.py +47 -0
- bb_integrations_lib/pipelines/steps/processing/sftp_renamer_step.py +61 -0
- bb_integrations_lib/pipelines/steps/processing/tank_reading_touchup_steps.py +75 -0
- bb_integrations_lib/pipelines/steps/processing/upload_supplier_invoice_step.py +16 -0
- bb_integrations_lib/pipelines/steps/send_attached_in_rita_email_step.py +44 -0
- bb_integrations_lib/pipelines/steps/send_rita_email_step.py +34 -0
- bb_integrations_lib/pipelines/steps/sleep_step.py +24 -0
- bb_integrations_lib/pipelines/wrappers/__init__.py +0 -0
- bb_integrations_lib/pipelines/wrappers/accessorials_transformation.py +104 -0
- bb_integrations_lib/pipelines/wrappers/distribution_report.py +191 -0
- bb_integrations_lib/pipelines/wrappers/export_tank_readings.py +237 -0
- bb_integrations_lib/pipelines/wrappers/import_tank_readings.py +192 -0
- bb_integrations_lib/pipelines/wrappers/wrapper.py +81 -0
- bb_integrations_lib/protocols/__init__.py +0 -0
- bb_integrations_lib/protocols/flat_file.py +210 -0
- bb_integrations_lib/protocols/gravitate_client.py +104 -0
- bb_integrations_lib/protocols/pipelines.py +697 -0
- bb_integrations_lib/provider/__init__.py +0 -0
- bb_integrations_lib/provider/api/__init__.py +0 -0
- bb_integrations_lib/provider/api/cargas/__init__.py +0 -0
- bb_integrations_lib/provider/api/cargas/client.py +43 -0
- bb_integrations_lib/provider/api/cargas/model.py +49 -0
- bb_integrations_lib/provider/api/cargas/protocol.py +23 -0
- bb_integrations_lib/provider/api/dtn/__init__.py +0 -0
- bb_integrations_lib/provider/api/dtn/client.py +128 -0
- bb_integrations_lib/provider/api/dtn/protocol.py +9 -0
- bb_integrations_lib/provider/api/keyvu/__init__.py +0 -0
- bb_integrations_lib/provider/api/keyvu/client.py +30 -0
- bb_integrations_lib/provider/api/keyvu/model.py +149 -0
- bb_integrations_lib/provider/api/macropoint/__init__.py +0 -0
- bb_integrations_lib/provider/api/macropoint/client.py +28 -0
- bb_integrations_lib/provider/api/macropoint/model.py +40 -0
- bb_integrations_lib/provider/api/pc_miler/__init__.py +0 -0
- bb_integrations_lib/provider/api/pc_miler/client.py +130 -0
- bb_integrations_lib/provider/api/pc_miler/model.py +6 -0
- bb_integrations_lib/provider/api/pc_miler/web_services_apis.py +131 -0
- bb_integrations_lib/provider/api/platform_science/__init__.py +0 -0
- bb_integrations_lib/provider/api/platform_science/client.py +147 -0
- bb_integrations_lib/provider/api/platform_science/model.py +82 -0
- bb_integrations_lib/provider/api/quicktrip/__init__.py +0 -0
- bb_integrations_lib/provider/api/quicktrip/client.py +52 -0
- bb_integrations_lib/provider/api/telapoint/__init__.py +0 -0
- bb_integrations_lib/provider/api/telapoint/client.py +68 -0
- bb_integrations_lib/provider/api/telapoint/model.py +178 -0
- bb_integrations_lib/provider/api/warren_rogers/__init__.py +0 -0
- bb_integrations_lib/provider/api/warren_rogers/client.py +207 -0
- bb_integrations_lib/provider/aws/__init__.py +0 -0
- bb_integrations_lib/provider/aws/s3/__init__.py +0 -0
- bb_integrations_lib/provider/aws/s3/client.py +126 -0
- bb_integrations_lib/provider/ftp/__init__.py +0 -0
- bb_integrations_lib/provider/ftp/client.py +140 -0
- bb_integrations_lib/provider/ftp/interface.py +273 -0
- bb_integrations_lib/provider/ftp/model.py +76 -0
- bb_integrations_lib/provider/imap/__init__.py +0 -0
- bb_integrations_lib/provider/imap/client.py +228 -0
- bb_integrations_lib/provider/imap/model.py +3 -0
- bb_integrations_lib/provider/sqlserver/__init__.py +0 -0
- bb_integrations_lib/provider/sqlserver/client.py +106 -0
- bb_integrations_lib/secrets/__init__.py +4 -0
- bb_integrations_lib/secrets/adapters.py +98 -0
- bb_integrations_lib/secrets/credential_models.py +222 -0
- bb_integrations_lib/secrets/factory.py +85 -0
- bb_integrations_lib/secrets/providers.py +160 -0
- bb_integrations_lib/shared/__init__.py +0 -0
- bb_integrations_lib/shared/exceptions.py +25 -0
- bb_integrations_lib/shared/model.py +1039 -0
- bb_integrations_lib/shared/shared_enums.py +510 -0
- bb_integrations_lib/storage/README.md +236 -0
- bb_integrations_lib/storage/__init__.py +0 -0
- bb_integrations_lib/storage/aws/__init__.py +0 -0
- bb_integrations_lib/storage/aws/s3.py +8 -0
- bb_integrations_lib/storage/defaults.py +72 -0
- bb_integrations_lib/storage/gcs/__init__.py +0 -0
- bb_integrations_lib/storage/gcs/client.py +8 -0
- bb_integrations_lib/storage/gcsmanager/__init__.py +0 -0
- bb_integrations_lib/storage/gcsmanager/client.py +8 -0
- bb_integrations_lib/storage/setup.py +29 -0
- bb_integrations_lib/util/__init__.py +0 -0
- bb_integrations_lib/util/cache/__init__.py +0 -0
- bb_integrations_lib/util/cache/custom_ttl_cache.py +75 -0
- bb_integrations_lib/util/cache/protocol.py +9 -0
- bb_integrations_lib/util/config/__init__.py +0 -0
- bb_integrations_lib/util/config/manager.py +391 -0
- bb_integrations_lib/util/config/model.py +41 -0
- bb_integrations_lib/util/exception_logger/__init__.py +0 -0
- bb_integrations_lib/util/exception_logger/exception_logger.py +146 -0
- bb_integrations_lib/util/exception_logger/test.py +114 -0
- bb_integrations_lib/util/utils.py +364 -0
- bb_integrations_lib/workers/__init__.py +0 -0
- bb_integrations_lib/workers/groups.py +13 -0
- bb_integrations_lib/workers/rpc_worker.py +50 -0
- bb_integrations_lib/workers/topics.py +20 -0
- bb_integrations_library-3.0.11.dist-info/METADATA +59 -0
- bb_integrations_library-3.0.11.dist-info/RECORD +217 -0
- bb_integrations_library-3.0.11.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from typing import Dict, Union, Protocol, Type, runtime_checkable
|
|
2
|
+
from bb_integrations_lib.gravitate.rita_api import GravitateRitaAPI, RitaBackendAPI
|
|
3
|
+
from bb_integrations_lib.mappers.prices.model import IntegrationType, PricingIntegrationConfig
|
|
4
|
+
from bb_integrations_lib.mappers.prices.protocol import ExternalPriceMapperIntegration
|
|
5
|
+
from bb_integrations_lib.provider.sqlserver.client import SQLServerClient
|
|
6
|
+
from bb_integrations_lib.util.config.manager import GlobalConfigManager
|
|
7
|
+
from bb_integrations_lib.util.config.model import GlobalConfig
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@runtime_checkable
|
|
11
|
+
class PricingIntegrationGetterProtocol(Protocol):
|
|
12
|
+
def get_integration_mapping_client_by_entity(self, entity_key: str) -> Union[
|
|
13
|
+
ExternalPriceMapperIntegration, RitaBackendAPI]:
|
|
14
|
+
"""Gets integration by entity key."""
|
|
15
|
+
|
|
16
|
+
def init_class(self, integration_type: IntegrationType) -> Union[
|
|
17
|
+
ExternalPriceMapperIntegration, RitaBackendAPI]:
|
|
18
|
+
"""Initializes integration class given a key"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PricingIntegrationGetter:
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
config: PricingIntegrationConfig
|
|
25
|
+
):
|
|
26
|
+
self.config: PricingIntegrationConfig = config
|
|
27
|
+
self.entity_config = config.entity_config
|
|
28
|
+
self.config_manager = GlobalConfigManager()
|
|
29
|
+
self.client_secret: GlobalConfig = self.config_manager.get_environment(config.environment)
|
|
30
|
+
|
|
31
|
+
def get_integration_mapping_client_by_entity(self, entity_key: str) -> Union[
|
|
32
|
+
ExternalPriceMapperIntegration, RitaBackendAPI]:
|
|
33
|
+
try:
|
|
34
|
+
integration_type = self.entity_config.get(entity_key).mapping_integration.type
|
|
35
|
+
if integration_type is None:
|
|
36
|
+
raise KeyError(f"No integration type found for entity key: {entity_key}")
|
|
37
|
+
client_class = self.init_class(integration_type)
|
|
38
|
+
if client_class is None:
|
|
39
|
+
raise KeyError(f"No client class found for integration type: {integration_type}")
|
|
40
|
+
return client_class
|
|
41
|
+
except KeyError as e:
|
|
42
|
+
raise NotImplementedError(str(e))
|
|
43
|
+
|
|
44
|
+
def init_class(self, integration_type: IntegrationType) -> Union[
|
|
45
|
+
ExternalPriceMapperIntegration, RitaBackendAPI]:
|
|
46
|
+
if integration_type == IntegrationType.sql:
|
|
47
|
+
return SQLServerClient(
|
|
48
|
+
server=self.client_secret.extra_data.get("server"),
|
|
49
|
+
database=self.client_secret.extra_data.get("database"),
|
|
50
|
+
username=self.client_secret.extra_data.get("username"),
|
|
51
|
+
password=self.client_secret.extra_data.get("password"),
|
|
52
|
+
)
|
|
53
|
+
if integration_type == IntegrationType.rita:
|
|
54
|
+
return GravitateRitaAPI(
|
|
55
|
+
client_id=self.client_secret.prod.rita.client_id,
|
|
56
|
+
client_secret=self.client_secret.prod.rita.client_secret,
|
|
57
|
+
tenant=self.config.environment
|
|
58
|
+
)
|
|
59
|
+
else:
|
|
60
|
+
raise NotImplementedError(f"Integration type {integration_type} is not supported")
|
|
61
|
+
|
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
from abc import abstractmethod, ABC
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Optional, Union
|
|
5
|
+
|
|
6
|
+
from bb_integrations_lib.gravitate.rita_api import GravitateRitaAPI
|
|
7
|
+
from bb_integrations_lib.models.rita.mapping import Map, MappingType, Children, CompositeMapKey
|
|
8
|
+
from bb_integrations_lib.secrets import RITACredential
|
|
9
|
+
from bb_integrations_lib.util.cache.custom_ttl_cache import CustomAsyncTTLCache
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MappingsNotLoadedException(Exception):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FastMapDirection(Enum):
|
|
17
|
+
source_to_grav = 1
|
|
18
|
+
grav_to_source = 2
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class FastMapKey:
|
|
22
|
+
"""
|
|
23
|
+
A hashable key that can be used to identify mappings quickly if enough properties are known.
|
|
24
|
+
Supports both simple string IDs and composite keys for entity identity (from_id).
|
|
25
|
+
|
|
26
|
+
Note: parent_id is always a simple string. Composite keys are for entity identity resolution,
|
|
27
|
+
not for hierarchical relationships. Children mappings only support string identifiers.
|
|
28
|
+
"""
|
|
29
|
+
from_id: Union[str, CompositeMapKey]
|
|
30
|
+
type: Optional[MappingType] = None
|
|
31
|
+
parent_id: Optional[str] = None
|
|
32
|
+
direction: FastMapDirection
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
from_id: Union[str, CompositeMapKey, dict],
|
|
37
|
+
type: MappingType,
|
|
38
|
+
parent_id: Optional[str],
|
|
39
|
+
direction: FastMapDirection
|
|
40
|
+
):
|
|
41
|
+
# Normalize dict inputs to CompositeMapKey for entity identity
|
|
42
|
+
if isinstance(from_id, dict):
|
|
43
|
+
self.from_id = CompositeMapKey(key=from_id)
|
|
44
|
+
else:
|
|
45
|
+
self.from_id = from_id
|
|
46
|
+
self.type = type
|
|
47
|
+
# parent_id is always a simple string (hierarchy uses string IDs)
|
|
48
|
+
self.parent_id = parent_id
|
|
49
|
+
self.direction = direction
|
|
50
|
+
|
|
51
|
+
# Cache normalized values for hash/equality
|
|
52
|
+
self._from_id_normalized = self._normalize_from_id(self.from_id)
|
|
53
|
+
self._parent_id_normalized = self.parent_id or ""
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def _normalize_from_id(value: Union[str, CompositeMapKey]) -> str:
|
|
57
|
+
"""Convert from_id to hashable string representation."""
|
|
58
|
+
if isinstance(value, CompositeMapKey):
|
|
59
|
+
return value.to_cache_key()
|
|
60
|
+
return value
|
|
61
|
+
|
|
62
|
+
def __hash__(self):
|
|
63
|
+
return hash((
|
|
64
|
+
self._from_id_normalized,
|
|
65
|
+
self.type,
|
|
66
|
+
self._parent_id_normalized,
|
|
67
|
+
self.direction.value
|
|
68
|
+
))
|
|
69
|
+
|
|
70
|
+
def __eq__(self, other):
|
|
71
|
+
if not isinstance(other, FastMapKey):
|
|
72
|
+
return False
|
|
73
|
+
return (
|
|
74
|
+
self._from_id_normalized == other._from_id_normalized and
|
|
75
|
+
self.type == other.type and
|
|
76
|
+
self._parent_id_normalized == other._parent_id_normalized and
|
|
77
|
+
self.direction == other.direction
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def __repr__(self):
|
|
81
|
+
type_name = self.type.name if self.type else None
|
|
82
|
+
parent_id_str = self._parent_id_normalized or None
|
|
83
|
+
return f"FastMap<from_id={self._from_id_normalized}, type_name={type_name}, parent_id={parent_id_str}, direction={self.direction.name}>"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class MappingProvider(ABC):
|
|
87
|
+
"""An abstract base class for implementing synchronous mapping providers for the Mapper class."""
|
|
88
|
+
|
|
89
|
+
def __init__(self):
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
@abstractmethod
|
|
93
|
+
def get_mappings_by_source_system(self, source_system: str) -> list[Map]:
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class AsyncMappingProvider(ABC):
|
|
98
|
+
"""An abstract base class for implementing asynchronous mapping providers for the Mapper class."""
|
|
99
|
+
|
|
100
|
+
def __init__(self):
|
|
101
|
+
pass
|
|
102
|
+
|
|
103
|
+
@abstractmethod
|
|
104
|
+
async def get_mappings_by_source_system(self, source_system: str) -> list[Map]:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class MockMappingProvider(MappingProvider):
|
|
109
|
+
"""A mapping provider that uses a constant list of mappings, intended for testing."""
|
|
110
|
+
|
|
111
|
+
def __init__(self, mappings: list[Map]):
|
|
112
|
+
super().__init__()
|
|
113
|
+
self.mappings = mappings
|
|
114
|
+
|
|
115
|
+
def get_mappings_by_source_system(self, source_system: str) -> list[Map]:
|
|
116
|
+
"""Returns mappings originally passed to init, filtered by source system."""
|
|
117
|
+
return list(filter(lambda m: m.source_system == source_system, self.mappings))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class MockAsyncMappingProvider(AsyncMappingProvider):
|
|
121
|
+
"""A mapping provider that uses a constant list of mappings, intended for testing."""
|
|
122
|
+
|
|
123
|
+
def __init__(self, mappings: list[Map]):
|
|
124
|
+
super().__init__()
|
|
125
|
+
self.mappings = mappings
|
|
126
|
+
|
|
127
|
+
async def get_mappings_by_source_system(self, source_system: str) -> list[Map]:
|
|
128
|
+
"""Returns mappings originally passed to init, filtered by source system."""
|
|
129
|
+
return list(filter(lambda m: m.source_system == source_system, self.mappings))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class RitaAPIMappingProvider(AsyncMappingProvider):
|
|
133
|
+
"""Accesses the RITA API to retrieve mappings, providing them to a Mapper."""
|
|
134
|
+
|
|
135
|
+
def __init__(self, rita_client: GravitateRitaAPI):
|
|
136
|
+
super().__init__()
|
|
137
|
+
self.rita_client = rita_client
|
|
138
|
+
|
|
139
|
+
async def from_credential(self, credential: RITACredential):
|
|
140
|
+
self.rita_client = GravitateRitaAPI.from_credential(credential)
|
|
141
|
+
|
|
142
|
+
async def get_mappings_by_source_system(self, source_system: str) -> list[Map]:
|
|
143
|
+
return await self.rita_client.get_mappings_by_source_system(source_system)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class RitaAPICachedMappingProvider(RitaAPIMappingProvider):
|
|
147
|
+
def __init__(
|
|
148
|
+
self,
|
|
149
|
+
rita_client: GravitateRitaAPI,
|
|
150
|
+
ttl_seconds: int = 120
|
|
151
|
+
):
|
|
152
|
+
super().__init__(rita_client)
|
|
153
|
+
self.ttl_seconds = ttl_seconds
|
|
154
|
+
self.cache: CustomAsyncTTLCache = CustomAsyncTTLCache(verbose=False)
|
|
155
|
+
|
|
156
|
+
async def get_mappings_by_source_system(self, source_system: str) -> list[Map]:
|
|
157
|
+
return await self.cache.get_or_set(
|
|
158
|
+
source_system, self.ttl_seconds, super().get_mappings_by_source_system, source_system
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class RitaMapperCore(ABC):
|
|
163
|
+
"""
|
|
164
|
+
Provides the core logic of mapping lookups. Entirely synchronous; the concrete implementations can use these
|
|
165
|
+
methods directly, and should generally only implement loading mappings.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
def __init__(self):
|
|
169
|
+
self.loaded = False
|
|
170
|
+
self.fast_maps = defaultdict(list)
|
|
171
|
+
|
|
172
|
+
def _raise_if_not_loaded(self):
|
|
173
|
+
if not self.loaded:
|
|
174
|
+
raise MappingsNotLoadedException("Mappings used before getting loaded")
|
|
175
|
+
|
|
176
|
+
def _load_mappings(self, mappings: list[Map]):
|
|
177
|
+
"""
|
|
178
|
+
Load the mappings from mappings into the mapper's internal data structures, making the get_ calls available
|
|
179
|
+
for use. Supports both simple string IDs and composite keys for entity identity.
|
|
180
|
+
|
|
181
|
+
Note: parent_id in FastMapKey is always a string. If a parent Map has a composite source_id,
|
|
182
|
+
it's converted to string for hierarchical lookups.
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
def _get_identifier(map_obj: Map | Children, direction: FastMapDirection):
|
|
186
|
+
"""Extract the appropriate identifier based on a map direction."""
|
|
187
|
+
if direction == FastMapDirection.grav_to_source:
|
|
188
|
+
return map_obj.gravitate_id
|
|
189
|
+
return map_obj.source_id
|
|
190
|
+
|
|
191
|
+
def _get_parent_id_str(parent: Map | None, direction: FastMapDirection) -> str | None:
|
|
192
|
+
"""Get parent identifier as string (hierarchy always uses string IDs)."""
|
|
193
|
+
if parent is None:
|
|
194
|
+
return None
|
|
195
|
+
parent_id = _get_identifier(parent, direction)
|
|
196
|
+
# Convert composite keys to string for parent_id (hierarchy uses strings)
|
|
197
|
+
if isinstance(parent_id, CompositeMapKey):
|
|
198
|
+
return parent_id.to_cache_key()
|
|
199
|
+
return parent_id
|
|
200
|
+
|
|
201
|
+
def _reg_map(map: Map | Children, direction: FastMapDirection, parent: Map | None = None):
|
|
202
|
+
from_id = _get_identifier(map, direction)
|
|
203
|
+
parent_id = _get_parent_id_str(parent, direction)
|
|
204
|
+
map_key = FastMapKey(from_id, map.type, parent_id, direction)
|
|
205
|
+
self.fast_maps[map_key].append(map)
|
|
206
|
+
|
|
207
|
+
for direction in FastMapDirection:
|
|
208
|
+
for m in mappings:
|
|
209
|
+
for child in m.children:
|
|
210
|
+
_reg_map(child, direction, m)
|
|
211
|
+
_reg_map(m, direction, None)
|
|
212
|
+
|
|
213
|
+
self.loaded = True
|
|
214
|
+
|
|
215
|
+
# noinspection PyUnreachableCode
|
|
216
|
+
def get_mappings(self, from_id: str, direction: FastMapDirection, mapping_type: MappingType,
|
|
217
|
+
parent_from_id: str | None = None) -> list[Map | Children]:
|
|
218
|
+
"""
|
|
219
|
+
Retrieve mappings meeting the criteria. Base method for many of the get_gravitate/source* methods - prefer using
|
|
220
|
+
those for a more expressive syntax.
|
|
221
|
+
|
|
222
|
+
:arg str from_id: The original value we're looking to map. If direction is source_to_grav, this matches on the
|
|
223
|
+
source_id field; if direction is grav_to_source, this matches on the gravitate_id field.
|
|
224
|
+
:arg FastMapDirection direction: The direction of the mapping (gravitate->source or source->gravitate).
|
|
225
|
+
:arg MappingType mapping_type: The type of the mapping.
|
|
226
|
+
:arg str | None parent_from_id: The from_id of the child mapping's parent, if searching for a child. To get
|
|
227
|
+
parent mappings instead, use None (the default).
|
|
228
|
+
:raises MappingsNotLoadedException: If mappings have not been loaded yet.
|
|
229
|
+
"""
|
|
230
|
+
self._raise_if_not_loaded()
|
|
231
|
+
if mapping_type is not None and not isinstance(mapping_type, MappingType):
|
|
232
|
+
raise TypeError(
|
|
233
|
+
"mapping_type must be of type bb_integrations_lib.models.rita.mapping.MappingType "
|
|
234
|
+
"(check whether you imported the right MappingType)"
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
return self.fast_maps.get(FastMapKey(from_id, mapping_type, parent_from_id, direction), [])
|
|
238
|
+
|
|
239
|
+
def get_mappings_guaranteed(
|
|
240
|
+
self, from_id: str, direction: FastMapDirection, mapping_type: MappingType,
|
|
241
|
+
parent_from_id: str | None = None
|
|
242
|
+
) -> list[Map | Children]:
|
|
243
|
+
"""Like get_mappings, but additionally raises a KeyError if no mappings are found."""
|
|
244
|
+
self._raise_if_not_loaded()
|
|
245
|
+
mappings = self.get_mappings(from_id, direction, mapping_type, parent_from_id)
|
|
246
|
+
if not mappings:
|
|
247
|
+
from_name = "gravitate" if direction == FastMapDirection.grav_to_source else "source"
|
|
248
|
+
child_slug = f", parent_{from_name}_id='{parent_from_id}'" if parent_from_id else ""
|
|
249
|
+
mapping_type_name = "None" if mapping_type is None else mapping_type.name
|
|
250
|
+
raise KeyError(
|
|
251
|
+
f"No mappings found for {from_name}_id='{from_id}'{child_slug} with type='{mapping_type_name}'"
|
|
252
|
+
)
|
|
253
|
+
return mappings
|
|
254
|
+
|
|
255
|
+
def get_single_mapping_guaranteed(
|
|
256
|
+
self, from_id: str, direction: FastMapDirection, mapping_type: MappingType,
|
|
257
|
+
parent_from_id: str | None = None
|
|
258
|
+
) -> Map | Children:
|
|
259
|
+
"""Like get_mappings_guaranteed, but additionally raises a KeyError if more than 1 mapping is found."""
|
|
260
|
+
mappings = self.get_mappings_guaranteed(from_id, direction, mapping_type, parent_from_id)
|
|
261
|
+
if len(mappings) > 1:
|
|
262
|
+
from_name = "gravitate" if direction == FastMapDirection.grav_to_source else "source"
|
|
263
|
+
child_slug = f", parent_{from_name}_id='{parent_from_id}'" if parent_from_id else ""
|
|
264
|
+
raise KeyError(
|
|
265
|
+
f"Too many mappings ({len(mappings)}) for {from_name}_id='{from_id}'{child_slug} "
|
|
266
|
+
f"with type='{mapping_type.name}', expected 1"
|
|
267
|
+
)
|
|
268
|
+
return mappings[0]
|
|
269
|
+
|
|
270
|
+
def get_gravitate_parent_id(
|
|
271
|
+
self,
|
|
272
|
+
source_id: str | CompositeMapKey,
|
|
273
|
+
mapping_type: MappingType | None
|
|
274
|
+
) -> str | CompositeMapKey:
|
|
275
|
+
return self.get_single_mapping_guaranteed(source_id, FastMapDirection.source_to_grav, mapping_type).gravitate_id
|
|
276
|
+
|
|
277
|
+
def get_gravitate_child_id(
|
|
278
|
+
self,
|
|
279
|
+
source_parent_id: str,
|
|
280
|
+
source_child_id: str,
|
|
281
|
+
mapping_type: MappingType | None
|
|
282
|
+
) -> str:
|
|
283
|
+
"""
|
|
284
|
+
Get gravitate_id for a child mapping.
|
|
285
|
+
|
|
286
|
+
Note: Child lookups use string IDs only. Children mappings don't support composite keys.
|
|
287
|
+
For composite key lookups (without hierarchy), use get_gravitate_id_by_composite().
|
|
288
|
+
"""
|
|
289
|
+
return self.get_single_mapping_guaranteed(
|
|
290
|
+
source_child_id, FastMapDirection.source_to_grav, mapping_type, source_parent_id
|
|
291
|
+
).gravitate_id
|
|
292
|
+
|
|
293
|
+
def get_source_parent_id(
|
|
294
|
+
self,
|
|
295
|
+
gravitate_id: str | CompositeMapKey,
|
|
296
|
+
mapping_type: MappingType | None
|
|
297
|
+
) -> str | CompositeMapKey:
|
|
298
|
+
return self.get_single_mapping_guaranteed(gravitate_id, FastMapDirection.grav_to_source, mapping_type).source_id
|
|
299
|
+
|
|
300
|
+
def get_source_child_id(
|
|
301
|
+
self,
|
|
302
|
+
gravitate_parent_id: str,
|
|
303
|
+
gravitate_child_id: str,
|
|
304
|
+
mapping_type: MappingType | None
|
|
305
|
+
) -> str:
|
|
306
|
+
"""
|
|
307
|
+
Get source_id for a child mapping.
|
|
308
|
+
|
|
309
|
+
Note: Child lookups use string IDs only. Children mappings don't support composite keys.
|
|
310
|
+
For composite key lookups (without hierarchy), use get_source_id_by_composite().
|
|
311
|
+
"""
|
|
312
|
+
return self.get_single_mapping_guaranteed(
|
|
313
|
+
gravitate_child_id, FastMapDirection.grav_to_source, mapping_type, gravitate_parent_id
|
|
314
|
+
).source_id
|
|
315
|
+
|
|
316
|
+
def get_gravitate_parent_ids(
|
|
317
|
+
self,
|
|
318
|
+
source_id: str | CompositeMapKey,
|
|
319
|
+
mapping_type: MappingType | None
|
|
320
|
+
) -> list[str | CompositeMapKey]:
|
|
321
|
+
return [
|
|
322
|
+
x.gravitate_id for x in
|
|
323
|
+
self.get_mappings_guaranteed(source_id, FastMapDirection.source_to_grav, mapping_type)
|
|
324
|
+
]
|
|
325
|
+
|
|
326
|
+
def get_gravitate_child_ids(
|
|
327
|
+
self,
|
|
328
|
+
source_parent_id: str,
|
|
329
|
+
source_child_id: str,
|
|
330
|
+
mapping_type: MappingType | None
|
|
331
|
+
) -> list[str]:
|
|
332
|
+
"""
|
|
333
|
+
Get all gravitate_ids for child mappings matching the criteria.
|
|
334
|
+
|
|
335
|
+
Note: Child lookups use string IDs only. Children mappings don't support composite keys.
|
|
336
|
+
"""
|
|
337
|
+
return [
|
|
338
|
+
x.gravitate_id for x in
|
|
339
|
+
self.get_mappings_guaranteed(
|
|
340
|
+
source_child_id, FastMapDirection.source_to_grav, mapping_type, source_parent_id)
|
|
341
|
+
]
|
|
342
|
+
|
|
343
|
+
def get_source_parent_ids(
|
|
344
|
+
self,
|
|
345
|
+
gravitate_id: str | CompositeMapKey,
|
|
346
|
+
mapping_type: MappingType | None
|
|
347
|
+
) -> list[str | CompositeMapKey]:
|
|
348
|
+
return [
|
|
349
|
+
x.source_id for x in
|
|
350
|
+
self.get_mappings_guaranteed(
|
|
351
|
+
gravitate_id, FastMapDirection.grav_to_source, mapping_type)
|
|
352
|
+
]
|
|
353
|
+
|
|
354
|
+
def get_source_child_ids(
|
|
355
|
+
self,
|
|
356
|
+
gravitate_parent_id: str,
|
|
357
|
+
gravitate_child_id: str,
|
|
358
|
+
mapping_type: MappingType | None
|
|
359
|
+
) -> list[str]:
|
|
360
|
+
"""
|
|
361
|
+
Get all source_ids for child mappings matching the criteria.
|
|
362
|
+
|
|
363
|
+
Note: Child lookups use string IDs only. Children mappings don't support composite keys.
|
|
364
|
+
"""
|
|
365
|
+
return [
|
|
366
|
+
x.source_id for x in
|
|
367
|
+
self.get_mappings_guaranteed(
|
|
368
|
+
gravitate_child_id, FastMapDirection.grav_to_source, mapping_type, gravitate_parent_id)
|
|
369
|
+
]
|
|
370
|
+
|
|
371
|
+
def get_gravitate_parent_id_str(
|
|
372
|
+
self,
|
|
373
|
+
source_id: str,
|
|
374
|
+
mapping_type: MappingType | None
|
|
375
|
+
) -> str:
|
|
376
|
+
"""Get gravitate_id as string. Raises TypeError if mapping uses composite key."""
|
|
377
|
+
result = self.get_gravitate_parent_id(source_id, mapping_type)
|
|
378
|
+
if isinstance(result, CompositeMapKey):
|
|
379
|
+
raise TypeError(f"Mapping has composite gravitate_id: {result}")
|
|
380
|
+
return result
|
|
381
|
+
|
|
382
|
+
def get_source_parent_id_str(
|
|
383
|
+
self,
|
|
384
|
+
gravitate_id: str,
|
|
385
|
+
mapping_type: MappingType | None
|
|
386
|
+
) -> str:
|
|
387
|
+
"""Get source_id as string. Raises TypeError if mapping uses composite key."""
|
|
388
|
+
result = self.get_source_parent_id(gravitate_id, mapping_type)
|
|
389
|
+
if isinstance(result, CompositeMapKey):
|
|
390
|
+
raise TypeError(f"Mapping has composite source_id: {result}")
|
|
391
|
+
return result
|
|
392
|
+
|
|
393
|
+
# Composite key lookup methods
|
|
394
|
+
|
|
395
|
+
def get_mappings_by_composite(
|
|
396
|
+
self,
|
|
397
|
+
from_key: Union[dict, CompositeMapKey],
|
|
398
|
+
direction: FastMapDirection,
|
|
399
|
+
mapping_type: MappingType | None,
|
|
400
|
+
parent_from_id: Optional[str] = None
|
|
401
|
+
) -> list[Map | Children]:
|
|
402
|
+
"""
|
|
403
|
+
Retrieve mappings using a composite key for entity identity.
|
|
404
|
+
|
|
405
|
+
:param from_key: Dict or CompositeMapKey for lookup (entity identity)
|
|
406
|
+
:param direction: Mapping direction
|
|
407
|
+
:param mapping_type: Type of mapping
|
|
408
|
+
:param parent_from_id: Parent identifier (string only - hierarchy uses simple IDs)
|
|
409
|
+
|
|
410
|
+
Note: Composite keys are for entity identity, not hierarchy. If looking up children,
|
|
411
|
+
use string parent_from_id. Children mappings don't support composite keys.
|
|
412
|
+
"""
|
|
413
|
+
self._raise_if_not_loaded()
|
|
414
|
+
if isinstance(from_key, dict):
|
|
415
|
+
from_key = CompositeMapKey(key=from_key)
|
|
416
|
+
return self.fast_maps.get(
|
|
417
|
+
FastMapKey(from_key, mapping_type, parent_from_id, direction), []
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
def get_gravitate_id_by_composite(
|
|
421
|
+
self,
|
|
422
|
+
source_key: Union[dict, CompositeMapKey],
|
|
423
|
+
mapping_type: MappingType | None
|
|
424
|
+
) -> str | CompositeMapKey:
|
|
425
|
+
"""Get gravitate_id using a composite source key."""
|
|
426
|
+
mappings = self.get_mappings_by_composite(
|
|
427
|
+
source_key, FastMapDirection.source_to_grav, mapping_type
|
|
428
|
+
)
|
|
429
|
+
if not mappings:
|
|
430
|
+
raise KeyError(f"No mapping found for composite key: {source_key}")
|
|
431
|
+
if len(mappings) > 1:
|
|
432
|
+
raise KeyError(f"Multiple mappings ({len(mappings)}) found for: {source_key}")
|
|
433
|
+
return mappings[0].gravitate_id
|
|
434
|
+
|
|
435
|
+
def get_source_id_by_composite(
|
|
436
|
+
self,
|
|
437
|
+
gravitate_key: Union[dict, CompositeMapKey],
|
|
438
|
+
mapping_type: MappingType | None
|
|
439
|
+
) -> str | CompositeMapKey:
|
|
440
|
+
"""Get source_id using a composite gravitate key."""
|
|
441
|
+
mappings = self.get_mappings_by_composite(
|
|
442
|
+
gravitate_key, FastMapDirection.grav_to_source, mapping_type
|
|
443
|
+
)
|
|
444
|
+
if not mappings:
|
|
445
|
+
raise KeyError(f"No mapping found for composite key: {gravitate_key}")
|
|
446
|
+
if len(mappings) > 1:
|
|
447
|
+
raise KeyError(f"Multiple mappings ({len(mappings)}) found for: {gravitate_key}")
|
|
448
|
+
return mappings[0].source_id
|
|
449
|
+
|
|
450
|
+
def get_mapping_by_composite(
|
|
451
|
+
self,
|
|
452
|
+
from_key: Union[dict, CompositeMapKey],
|
|
453
|
+
direction: FastMapDirection,
|
|
454
|
+
mapping_type: MappingType | None
|
|
455
|
+
) -> Map | Children:
|
|
456
|
+
"""Get single mapping by composite key, raises if not found or multiple."""
|
|
457
|
+
mappings = self.get_mappings_by_composite(from_key, direction, mapping_type)
|
|
458
|
+
if not mappings:
|
|
459
|
+
raise KeyError(f"No mapping found for composite key: {from_key}")
|
|
460
|
+
if len(mappings) > 1:
|
|
461
|
+
raise KeyError(f"Multiple mappings ({len(mappings)}) found for: {from_key}")
|
|
462
|
+
return mappings[0]
|
|
463
|
+
|
|
464
|
+
def find_mappings_by_partial_key(
|
|
465
|
+
self,
|
|
466
|
+
partial_key: dict[str, str],
|
|
467
|
+
direction: FastMapDirection,
|
|
468
|
+
mapping_type: MappingType | None = None
|
|
469
|
+
) -> list[Map | Children]:
|
|
470
|
+
"""
|
|
471
|
+
Find all mappings where the composite key contains the partial key fields.
|
|
472
|
+
|
|
473
|
+
Example: partial_key={"product": "X"} matches {"product": "X", "terminal": "Y"}
|
|
474
|
+
"""
|
|
475
|
+
self._raise_if_not_loaded()
|
|
476
|
+
results = []
|
|
477
|
+
for fast_key, mappings in self.fast_maps.items():
|
|
478
|
+
if fast_key.direction != direction:
|
|
479
|
+
continue
|
|
480
|
+
if mapping_type is not None and fast_key.type != mapping_type:
|
|
481
|
+
continue
|
|
482
|
+
# Check if from_id is a CompositeMapKey and matches partial
|
|
483
|
+
if isinstance(fast_key.from_id, CompositeMapKey):
|
|
484
|
+
if fast_key.from_id.matches(partial_key):
|
|
485
|
+
results.extend(mappings)
|
|
486
|
+
return results
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
class RitaMapper(RitaMapperCore):
|
|
490
|
+
def __init__(self, provider: MappingProvider | AsyncMappingProvider, source_system: str):
|
|
491
|
+
super().__init__()
|
|
492
|
+
self.provider = provider
|
|
493
|
+
self.source_system = source_system
|
|
494
|
+
|
|
495
|
+
async def load_mappings_async(self):
|
|
496
|
+
"""
|
|
497
|
+
Load mappings from the provider asynchronously.
|
|
498
|
+
|
|
499
|
+
:raises TypeError: If the provider is not async.
|
|
500
|
+
|
|
501
|
+
Note that this method does not check whether mappings are already loaded; calling it will overwrite any stored
|
|
502
|
+
mappings with a fresh set from the provider.
|
|
503
|
+
"""
|
|
504
|
+
if isinstance(self.provider, AsyncMappingProvider):
|
|
505
|
+
mappings = await self.provider.get_mappings_by_source_system(self.source_system)
|
|
506
|
+
else:
|
|
507
|
+
raise TypeError("Provider is not async")
|
|
508
|
+
super()._load_mappings(mappings)
|
|
509
|
+
|
|
510
|
+
def load_mappings(self):
|
|
511
|
+
"""
|
|
512
|
+
Load mappings from the provider synchronously.
|
|
513
|
+
|
|
514
|
+
:raises TypeError: If the provider is async.
|
|
515
|
+
|
|
516
|
+
Note that this method does not check whether mappings are already loaded; calling it will overwrite any stored
|
|
517
|
+
mappings with a fresh set from the provider.
|
|
518
|
+
"""
|
|
519
|
+
if isinstance(self.provider, MappingProvider):
|
|
520
|
+
mappings = self.provider.get_mappings_by_source_system(self.source_system)
|
|
521
|
+
else:
|
|
522
|
+
raise TypeError("Provider is not synchronous")
|
|
523
|
+
super()._load_mappings(mappings)
|
|
File without changes
|