Skip to content

Commit f83eca5

Browse files
keueugene-kulakAugan93
authored
CDK: Fix typing errors (#9037)
* fix typing, drop AirbyteLogger * format * bump the version * use logger instead of fixture logger Co-authored-by: Eugene Kulak <[email protected]> Co-authored-by: auganbay <[email protected]>
1 parent 41f89d1 commit f83eca5

26 files changed

+126
-144
lines changed

airbyte-cdk/python/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## 0.1.47
4+
Fix typing errors.
5+
36
## 0.1.45
47
Integrate Sentry for performance and errors tracking.
58

airbyte-cdk/python/airbyte_cdk/connector.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55

66
import json
7+
import logging
78
import os
89
import pkgutil
910
from abc import ABC, abstractmethod
1011
from typing import Any, Mapping, Optional
1112

12-
from airbyte_cdk.logger import AirbyteLogger
1313
from airbyte_cdk.models import AirbyteConnectionStatus, ConnectorSpecification
1414

1515

@@ -48,7 +48,7 @@ def write_config(config: Mapping[str, Any], config_path: str):
4848
with open(config_path, "w") as fh:
4949
fh.write(json.dumps(config))
5050

51-
def spec(self, logger: AirbyteLogger) -> ConnectorSpecification:
51+
def spec(self, logger: logging.Logger) -> ConnectorSpecification:
5252
"""
5353
Returns the spec for this integration. The spec is a JSON-Schema object describing the required configurations (e.g: username and password)
5454
required to run this integration.
@@ -59,7 +59,7 @@ def spec(self, logger: AirbyteLogger) -> ConnectorSpecification:
5959
return ConnectorSpecification.parse_obj(json.loads(raw_spec))
6060

6161
@abstractmethod
62-
def check(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> AirbyteConnectionStatus:
62+
def check(self, logger: logging.Logger, config: Mapping[str, Any]) -> AirbyteConnectionStatus:
6363
"""
6464
Tests if the input configuration can be used to successfully connect to the integration e.g: if a provided Stripe API token can be used to connect
6565
to the Stripe API.

airbyte-cdk/python/airbyte_cdk/destinations/destination.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44

55
import argparse
66
import io
7+
import logging
78
import sys
89
from abc import ABC, abstractmethod
910
from typing import Any, Iterable, List, Mapping
1011

11-
from airbyte_cdk import AirbyteLogger
1212
from airbyte_cdk.connector import Connector
1313
from airbyte_cdk.models import AirbyteMessage, ConfiguredAirbyteCatalog, Type
1414
from airbyte_cdk.sources.utils.schema_helpers import check_config_against_spec_or_exit
1515
from pydantic import ValidationError
1616

17+
logger = logging.getLogger("airbyte")
18+
1719

1820
class Destination(Connector, ABC):
19-
logger = AirbyteLogger()
2021
VALID_CMDS = {"spec", "check", "write"}
2122

2223
@abstractmethod
@@ -26,7 +27,7 @@ def write(
2627
"""Implement to define how the connector writes data to the destination"""
2728

2829
def _run_check(self, config: Mapping[str, Any]) -> AirbyteMessage:
29-
check_result = self.check(self.logger, config)
30+
check_result = self.check(logger, config)
3031
return AirbyteMessage(type=Type.CONNECTION_STATUS, connectionStatus=check_result)
3132

3233
def _parse_input_stream(self, input_stream: io.TextIOWrapper) -> Iterable[AirbyteMessage]:
@@ -35,16 +36,16 @@ def _parse_input_stream(self, input_stream: io.TextIOWrapper) -> Iterable[Airbyt
3536
try:
3637
yield AirbyteMessage.parse_raw(line)
3738
except ValidationError:
38-
self.logger.info(f"ignoring input which can't be deserialized as Airbyte Message: {line}")
39+
logger.info(f"ignoring input which can't be deserialized as Airbyte Message: {line}")
3940

4041
def _run_write(
4142
self, config: Mapping[str, Any], configured_catalog_path: str, input_stream: io.TextIOWrapper
4243
) -> Iterable[AirbyteMessage]:
4344
catalog = ConfiguredAirbyteCatalog.parse_file(configured_catalog_path)
4445
input_messages = self._parse_input_stream(input_stream)
45-
self.logger.info("Begin writing to the destination...")
46+
logger.info("Begin writing to the destination...")
4647
yield from self.write(config=config, configured_catalog=catalog, input_messages=input_messages)
47-
self.logger.info("Writing complete.")
48+
logger.info("Writing complete.")
4849

4950
def parse_args(self, args: List[str]) -> argparse.Namespace:
5051
"""
@@ -86,7 +87,7 @@ def run_cmd(self, parsed_args: argparse.Namespace) -> Iterable[AirbyteMessage]:
8687
if cmd not in self.VALID_CMDS:
8788
raise Exception(f"Unrecognized command: {cmd}")
8889

89-
spec = self.spec(self.logger)
90+
spec = self.spec(logger)
9091
if cmd == "spec":
9192
yield AirbyteMessage(type=Type.SPEC, spec=spec)
9293
return

airbyte-cdk/python/airbyte_cdk/logger.py

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import logging.config
77
import sys
88
import traceback
9-
from typing import List
9+
from typing import List, Tuple
1010

1111
from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage
1212

@@ -49,7 +49,6 @@ def hook_fn(exception_type, exception_value, traceback_):
4949

5050
def init_logger(name: str = None):
5151
"""Initial set up of logger"""
52-
logging.setLoggerClass(AirbyteNativeLogger)
5352
logging.addLevelName(TRACE_LEVEL_NUM, "TRACE")
5453
logger = logging.getLogger(name)
5554
logger.setLevel(TRACE_LEVEL_NUM)
@@ -61,7 +60,7 @@ def init_logger(name: str = None):
6160
class AirbyteLogFormatter(logging.Formatter):
6261
"""Output log records using AirbyteMessage"""
6362

64-
_secrets = []
63+
_secrets: List[str] = []
6564

6665
@classmethod
6766
def update_secrets(cls, secrets: List[str]):
@@ -88,46 +87,22 @@ def format(self, record: logging.LogRecord) -> str:
8887
return log_message.json(exclude_unset=True)
8988

9089

91-
class AirbyteNativeLogger(logging.Logger):
92-
"""Using native logger with implementing all AirbyteLogger features"""
90+
def log_by_prefix(msg: str, default_level: str) -> Tuple[int, str]:
91+
"""Custom method, which takes log level from first word of message"""
92+
valid_log_types = ["FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]
93+
split_line = msg.split()
94+
first_word = next(iter(split_line), None)
95+
if first_word in valid_log_types:
96+
log_level = logging.getLevelName(first_word)
97+
rendered_message = " ".join(split_line[1:])
98+
else:
99+
log_level = logging.getLevelName(default_level)
100+
rendered_message = msg
93101

94-
def __init__(self, name):
95-
super().__init__(name)
96-
self.valid_log_types = ["FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]
97-
98-
def log_by_prefix(self, msg, default_level):
99-
"""Custom method, which takes log level from first word of message"""
100-
split_line = msg.split()
101-
first_word = next(iter(split_line), None)
102-
if first_word in self.valid_log_types:
103-
log_level = logging.getLevelName(first_word)
104-
rendered_message = " ".join(split_line[1:])
105-
else:
106-
default_level = default_level if default_level in self.valid_log_types else "INFO"
107-
log_level = logging.getLevelName(default_level)
108-
rendered_message = msg
109-
self.log(log_level, rendered_message)
110-
111-
def trace(self, msg, *args, **kwargs):
112-
self._log(TRACE_LEVEL_NUM, msg, args, **kwargs)
102+
return log_level, rendered_message
113103

114104

115105
class AirbyteLogger:
116-
def __init__(self):
117-
self.valid_log_types = ["FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]
118-
119-
def log_by_prefix(self, message, default_level):
120-
"""Custom method, which takes log level from first word of message"""
121-
split_line = message.split()
122-
first_word = next(iter(split_line), None)
123-
if first_word in self.valid_log_types:
124-
log_level = first_word
125-
rendered_message = " ".join(split_line[1:])
126-
else:
127-
log_level = default_level
128-
rendered_message = message
129-
self.log(log_level, rendered_message)
130-
131106
def log(self, level, message):
132107
log_record = AirbyteLogMessage(level=level, message=message)
133108
log_message = AirbyteMessage(type="LOG", log=log_record)

airbyte-cdk/python/airbyte_cdk/sources/abstract_source.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,18 @@
44

55

66
import copy
7+
import logging
78
from abc import ABC, abstractmethod
89
from datetime import datetime
910
from functools import lru_cache
1011
from typing import Any, Dict, Iterator, List, Mapping, MutableMapping, Optional, Tuple
1112

12-
from airbyte_cdk.logger import AirbyteLogger
1313
from airbyte_cdk.models import (
1414
AirbyteCatalog,
1515
AirbyteConnectionStatus,
1616
AirbyteMessage,
1717
AirbyteRecordMessage,
1818
AirbyteStateMessage,
19-
AirbyteStream,
2019
ConfiguredAirbyteCatalog,
2120
ConfiguredAirbyteStream,
2221
Status,
@@ -38,8 +37,9 @@ class AbstractSource(Source, ABC):
3837
"""
3938

4039
@abstractmethod
41-
def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> Tuple[bool, Optional[Any]]:
40+
def check_connection(self, logger: logging.Logger, config: Mapping[str, Any]) -> Tuple[bool, Optional[Any]]:
4241
"""
42+
:param logger: source logger
4343
:param config: The user-provided configuration as specified by the source's spec.
4444
This usually contains information required to check connection e.g. tokens, secrets and keys etc.
4545
:return: A tuple of (boolean, error). If boolean is true, then the connection check is successful
@@ -57,19 +57,19 @@ def streams(self, config: Mapping[str, Any]) -> List[Stream]:
5757
"""
5858

5959
# Stream name to instance map for applying output object transformation
60-
_stream_to_instance_map: Dict[str, AirbyteStream] = {}
60+
_stream_to_instance_map: Dict[str, Stream] = {}
6161

6262
@property
6363
def name(self) -> str:
6464
"""Source name"""
6565
return self.__class__.__name__
6666

67-
def discover(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> AirbyteCatalog:
67+
def discover(self, logger: logging.Logger, config: Mapping[str, Any]) -> AirbyteCatalog:
6868
"""Implements the Discover operation from the Airbyte Specification. See https://docs.airbyte.io/architecture/airbyte-specification."""
6969
streams = [stream.as_airbyte_stream() for stream in self.streams(config=config)]
7070
return AirbyteCatalog(streams=streams)
7171

72-
def check(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> AirbyteConnectionStatus:
72+
def check(self, logger: logging.Logger, config: Mapping[str, Any]) -> AirbyteConnectionStatus:
7373
"""Implements the Check Connection operation from the Airbyte Specification. See https://docs.airbyte.io/architecture/airbyte-specification."""
7474
try:
7575
check_succeeded, error = self.check_connection(logger, config)
@@ -81,7 +81,7 @@ def check(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> AirbyteConn
8181
return AirbyteConnectionStatus(status=Status.SUCCEEDED)
8282

8383
def read(
84-
self, logger: AirbyteLogger, config: Mapping[str, Any], catalog: ConfiguredAirbyteCatalog, state: MutableMapping[str, Any] = None
84+
self, logger: logging.Logger, config: Mapping[str, Any], catalog: ConfiguredAirbyteCatalog, state: MutableMapping[str, Any] = None
8585
) -> Iterator[AirbyteMessage]:
8686
"""Implements the Read operation from the Airbyte Specification. See https://docs.airbyte.io/architecture/airbyte-specification."""
8787
connector_state = copy.deepcopy(state or {})
@@ -118,7 +118,7 @@ def read(
118118

119119
def _read_stream(
120120
self,
121-
logger: AirbyteLogger,
121+
logger: logging.Logger,
122122
stream_instance: Stream,
123123
configured_stream: ConfiguredAirbyteStream,
124124
connector_state: MutableMapping[str, Any],
@@ -160,7 +160,7 @@ def _limit_reached(internal_config: InternalConfig, records_counter: int) -> boo
160160

161161
def _read_incremental(
162162
self,
163-
logger: AirbyteLogger,
163+
logger: logging.Logger,
164164
stream_instance: Stream,
165165
configured_stream: ConfiguredAirbyteStream,
166166
connector_state: MutableMapping[str, Any],
@@ -222,15 +222,15 @@ def _checkpoint_state(self, stream_name, stream_state, connector_state, logger):
222222
return AirbyteMessage(type=MessageType.STATE, state=AirbyteStateMessage(data=connector_state))
223223

224224
@lru_cache(maxsize=None)
225-
def _get_stream_transformer_and_schema(self, stream_name: str) -> Tuple[TypeTransformer, dict]:
225+
def _get_stream_transformer_and_schema(self, stream_name: str) -> Tuple[TypeTransformer, Mapping[str, Any]]:
226226
"""
227227
Lookup stream's transform object and jsonschema based on stream name.
228228
This function would be called a lot so using caching to save on costly
229229
get_json_schema operation.
230230
:param stream_name name of stream from catalog.
231231
:return tuple with stream transformer object and discover json schema.
232232
"""
233-
stream_instance = self._stream_to_instance_map.get(stream_name)
233+
stream_instance = self._stream_to_instance_map[stream_name]
234234
return stream_instance.transformer, stream_instance.get_json_schema()
235235

236236
def _as_airbyte_record(self, stream_name: str, data: Mapping[str, Any]):
@@ -240,6 +240,6 @@ def _as_airbyte_record(self, stream_name: str, data: Mapping[str, Any]):
240240
# need it to normalize values against json schema. By default no action
241241
# taken unless configured. See
242242
# docs/connector-development/cdk-python/schemas.md for details.
243-
transformer.transform(data, schema)
243+
transformer.transform(data, schema) # type: ignore
244244
message = AirbyteRecordMessage(stream=stream_name, data=data, emitted_at=now_millis)
245245
return AirbyteMessage(type=MessageType.RECORD, record=message)

airbyte-cdk/python/airbyte_cdk/sources/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ class BaseConfig(BaseModel):
1717
"""
1818

1919
@classmethod
20-
def schema(cls, **kwargs) -> Dict[str, Any]:
20+
def schema(cls, *args, **kwargs) -> Dict[str, Any]:
2121
"""We're overriding the schema classmethod to enable some post-processing"""
22-
schema = super().schema(**kwargs)
22+
schema = super().schema(*args, **kwargs)
2323
rename_key(schema, old_key="anyOf", new_key="oneOf") # UI supports only oneOf
2424
expand_refs(schema)
2525
schema.pop("description", None) # description added from the docstring

airbyte-cdk/python/airbyte_cdk/sources/deprecated/base_source.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55

66
import copy
7+
import logging
78
from datetime import datetime
89
from typing import Any, Iterable, Mapping, MutableMapping, Type
910

10-
from airbyte_cdk.logger import AirbyteLogger
1111
from airbyte_cdk.models import (
1212
AirbyteCatalog,
1313
AirbyteConnectionStatus,
@@ -39,13 +39,13 @@ def _get_client(self, config: Mapping):
3939
"""Construct client"""
4040
return self.client_class(**config)
4141

42-
def discover(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> AirbyteCatalog:
42+
def discover(self, logger: logging.Logger, config: Mapping[str, Any]) -> AirbyteCatalog:
4343
"""Discover streams"""
4444
client = self._get_client(config)
4545

4646
return AirbyteCatalog(streams=[stream for stream in client.streams])
4747

48-
def check(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> AirbyteConnectionStatus:
48+
def check(self, logger: logging.Logger, config: Mapping[str, Any]) -> AirbyteConnectionStatus:
4949
"""Check connection"""
5050
client = self._get_client(config)
5151
alive, error = client.health_check()
@@ -55,7 +55,7 @@ def check(self, logger: AirbyteLogger, config: Mapping[str, Any]) -> AirbyteConn
5555
return AirbyteConnectionStatus(status=Status.SUCCEEDED)
5656

5757
def read(
58-
self, logger: AirbyteLogger, config: Mapping[str, Any], catalog: ConfiguredAirbyteCatalog, state: MutableMapping[str, Any] = None
58+
self, logger: logging.Logger, config: Mapping[str, Any], catalog: ConfiguredAirbyteCatalog, state: MutableMapping[str, Any] = None
5959
) -> Iterable[AirbyteMessage]:
6060
state = state or {}
6161
client = self._get_client(config)
@@ -73,7 +73,7 @@ def read(
7373
logger.info(f"Finished syncing {self.name}")
7474

7575
def _read_stream(
76-
self, logger: AirbyteLogger, client: BaseClient, configured_stream: ConfiguredAirbyteStream, state: MutableMapping[str, Any]
76+
self, logger: logging.Logger, client: BaseClient, configured_stream: ConfiguredAirbyteStream, state: MutableMapping[str, Any]
7777
):
7878
stream_name = configured_stream.stream.name
7979
use_incremental = configured_stream.sync_mode == SyncMode.incremental and client.stream_has_state(stream_name)

airbyte-cdk/python/airbyte_cdk/sources/singer/singer_helpers.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from io import TextIOWrapper
1313
from typing import Any, DefaultDict, Dict, Iterator, List, Mapping, Optional, Tuple
1414

15+
from airbyte_cdk.logger import log_by_prefix
1516
from airbyte_cdk.models import (
1617
AirbyteCatalog,
1718
AirbyteMessage,
@@ -138,7 +139,7 @@ def _read_singer_catalog(logger, shell_command: str) -> Mapping[str, Any]:
138139
shell_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True
139140
)
140141
for line in completed_process.stderr.splitlines():
141-
logger.log_by_prefix(line, "ERROR")
142+
logger.log(*log_by_prefix(line, "ERROR"))
142143

143144
return json.loads(completed_process.stdout)
144145

@@ -169,9 +170,9 @@ def read(logger, shell_command, is_message=(lambda x: True)) -> Iterator[Airbyte
169170
if message_data is not None:
170171
yield message_data
171172
else:
172-
logger.log_by_prefix(line, "INFO")
173+
logger.log(*log_by_prefix(line, "INFO"))
173174
else:
174-
logger.log_by_prefix(line, "ERROR")
175+
logger.log(*log_by_prefix(line, "ERROR"))
175176

176177
@staticmethod
177178
def _read_lines(process: subprocess.Popen) -> Iterator[Tuple[str, TextIOWrapper]]:

0 commit comments

Comments
 (0)