1
0
mirror of synced 2025-12-31 06:05:12 -05:00
Files
Cole Snodgrass 2e099acc52 update headers from 2022 -> 2023 (#22594)
* It's 2023!

* 2022 -> 2023

---------

Co-authored-by: evantahler <evan@airbyte.io>
2023-02-08 13:01:16 -08:00

103 lines
4.3 KiB
Python

#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
#
import logging
from typing import Any, Iterator, List, Mapping, MutableMapping, Tuple, Union
from airbyte_cdk.models import AirbyteCatalog, AirbyteMessage, AirbyteStateMessage, AirbyteStream, ConfiguredAirbyteCatalog, SyncMode
from airbyte_cdk.sources import AbstractSource
from airbyte_cdk.sources.streams import Stream
from .dataverse import convert_dataverse_type, do_request, get_auth
from .streams import IncrementalMicrosoftDataverseStream, MicrosoftDataverseStream
class SourceMicrosoftDataverse(AbstractSource):
def __init__(self):
self.catalogs = None
def discover(self, logger: logging.Logger, config: Mapping[str, Any]) -> AirbyteCatalog:
response = do_request(config, "EntityDefinitions?$expand=Attributes")
response_json = response.json()
streams = []
for entity in response_json["value"]:
schema = {"properties": {}}
for attribute in entity["Attributes"]:
dataverse_type = attribute["AttributeType"]
if dataverse_type == "Lookup":
attribute["LogicalName"] = "_" + attribute["LogicalName"] + "_value"
attribute_type = convert_dataverse_type(dataverse_type)
if not attribute_type:
continue
schema["properties"][attribute["LogicalName"]] = attribute_type
if entity["CanChangeTrackingBeEnabled"]["Value"] and entity["ChangeTrackingEnabled"]:
schema["properties"].update({"_ab_cdc_updated_at": {"type": "string"}, "_ab_cdc_deleted_at": {"type": ["null", "string"]}})
stream = AirbyteStream(
name=entity["LogicalName"], json_schema=schema, supported_sync_modes=[SyncMode.full_refresh, SyncMode.incremental]
)
stream.source_defined_cursor = True
if "modifiedon" in schema["properties"]:
stream.default_cursor_field = ["modifiedon"]
else:
stream = AirbyteStream(name=entity["LogicalName"], json_schema=schema, supported_sync_modes=[SyncMode.full_refresh])
stream.source_defined_primary_key = [[entity["PrimaryIdAttribute"]]]
streams.append(stream)
return AirbyteCatalog(streams=streams)
def check_connection(self, logger, config) -> Tuple[bool, any]:
"""
:param config: the user-input config object conforming to the connector's spec.yaml
:param logger: logger object
:return Tuple[bool, any]: (True, None) if the input config can be used to connect to the API successfully, (False, error) otherwise.
"""
try:
response = do_request(config, "")
# Raises an exception for error codes (4xx or 5xx)
response.raise_for_status()
return True, None
except Exception as e:
return False, e
def read(
self,
logger: logging.Logger,
config: Mapping[str, Any],
catalog: ConfiguredAirbyteCatalog,
state: Union[List[AirbyteStateMessage], MutableMapping[str, Any]] = None,
) -> Iterator[AirbyteMessage]:
self.catalogs = catalog
return super().read(logger, config, catalog, state)
def streams(self, config: Mapping[str, Any]) -> List[Stream]:
"""
:param config: A Mapping of the user input configuration as defined in the connector spec.
"""
auth = get_auth(config)
streams = []
for catalog in self.catalogs.streams:
response = do_request(config, f"EntityDefinitions(LogicalName='{catalog.stream.name}')")
response_json = response.json()
args = {
"url": config["url"],
"stream_name": catalog.stream.name,
"stream_path": response_json["EntitySetName"],
"primary_key": catalog.primary_key,
"schema": catalog.stream.json_schema,
"odata_maxpagesize": config["odata_maxpagesize"],
"authenticator": auth,
}
if catalog.sync_mode == SyncMode.incremental:
streams.append(IncrementalMicrosoftDataverseStream(**args, config_cursor_field=catalog.cursor_field))
else:
streams.append(MicrosoftDataverseStream(**args))
return streams