Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AirbyteLib: friendly install and post-install messaging #34816

Merged
merged 15 commits into from
Feb 3, 2024
20 changes: 19 additions & 1 deletion airbyte-lib/airbyte_lib/_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
from shutil import rmtree
from typing import IO, TYPE_CHECKING, Any, NoReturn, cast

from rich import print

from airbyte_lib import exceptions as exc
from airbyte_lib.registry import ConnectorMetadata
from airbyte_lib.telemetry import SourceTelemetryInfo, SourceType
Expand Down Expand Up @@ -188,6 +190,14 @@ def uninstall(self) -> None:

self.reported_version = None # Reset the reported version from the previous installation

@property
def docs_url(self) -> str:
"""Get the URL to the connector's documentation."""
# TODO: Refactor installation so that this can just live in the Source class.
return "https://docs.airbyte.com/integrations/sources/" + self.name.lower().replace(
"source-", ""
)

def install(self) -> None:
"""Install the connector in a virtual environment.

Expand All @@ -198,7 +208,10 @@ def install(self) -> None:
)

pip_path = str(self._get_venv_path() / "bin" / "pip")

print(
f"Installing '{self.name}' into virtual environment '{self._get_venv_path()!s}'.\n"
f"Running 'pip install {self.pip_url}'...\n"
)
try:
self._run_subprocess_and_raise_on_failure(
args=[pip_path, "install", *shlex.split(self.pip_url)]
Expand All @@ -214,6 +227,11 @@ def install(self) -> None:

# Assuming the installation succeeded, store the installed version
self.reported_version = self._get_installed_version(raise_on_error=False, recheck=True)
print(
f"Connector '{self.name}' installed successfully!\n"
f"For more information, see the {self.name} documentation:\n"
f"{self.docs_url}#reference\n"
)

def _get_installed_version(
self,
Expand Down
29 changes: 19 additions & 10 deletions airbyte-lib/airbyte_lib/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from __future__ import annotations

from dataclasses import dataclass
from textwrap import indent
from typing import Any


Expand Down Expand Up @@ -69,27 +70,31 @@ def get_message(self) -> str:
return self.__doc__.split("\n")[0] if self.__doc__ else ""

def __str__(self) -> str:
special_properties = ["message", "guidance", "help_url", "log_text"]
properties_str = ", ".join(
f"{k}={v!r}"
special_properties = ["message", "guidance", "help_url", "log_text", "context"]
display_properties = {
k: v
for k, v in self.__dict__.items()
if k not in special_properties and not k.startswith("_") and v is not None
}
display_properties.update(self.context or {})
context_str = "\n ".join(
f"{str(k).replace('_', ' ').title()}: {v!r}" for k, v in display_properties.items()
)
exception_str = f"{self.__class__.__name__}: {self.get_message()}."
if properties_str:
exception_str += f" ({properties_str})"
exception_str = f"{self.__class__.__name__}: {self.get_message()}\n"
if context_str:
exception_str += " " + context_str

if self.log_text:
if isinstance(self.log_text, list):
self.log_text = "\n".join(self.log_text)

exception_str += f"\n\n Log output: {self.log_text}"
exception_str += f"\nLog output: \n {indent(self.log_text, ' ')}"

if self.guidance:
exception_str += f"\n\n Suggestion: {self.guidance}"
exception_str += f"\nSuggestion: {self.guidance}"

if self.help_url:
exception_str += f"\n\n More info: {self.help_url}"
exception_str += f"\nMore info: {self.help_url}"

return exception_str

Expand Down Expand Up @@ -225,7 +230,11 @@ class AirbyteConnectorMissingSpecError(AirbyteConnectorError):


class AirbyteConnectorCheckFailedError(AirbyteConnectorError):
"""Connector did not return a spec."""
"""Connector check failed."""

guidance = (
"Please double-check your config or review the connector's logs for more information."
)


@dataclass
Expand Down
15 changes: 13 additions & 2 deletions airbyte-lib/airbyte_lib/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import jsonschema
import yaml
from rich import print

from airbyte_protocol.models import (
AirbyteCatalog,
Expand Down Expand Up @@ -212,6 +213,14 @@ def _yaml_spec(self) -> str:
# convert to a yaml string
return yaml.dump(spec_dict)

@property
def docs_url(self) -> str:
"""Get the URL to the connector's documentation."""
# TODO: Replace with docs URL from metadata when available
return "https://docs.airbyte.com/integrations/sources/" + self.name.lower().replace(
"source-", ""
)

@property
def discovered_catalog(self) -> AirbyteCatalog:
"""Get the raw catalog for the given streams.
Expand Down Expand Up @@ -318,9 +327,10 @@ def check(self) -> None:
return # Success!

raise exc.AirbyteConnectorCheckFailedError(
help_url=self.docs_url,
context={
"message": msg.connectionStatus.message,
}
"failure_reason": msg.connectionStatus.message,
},
)
raise exc.AirbyteConnectorCheckFailedError(log_text=self._last_log_messages)
except exc.AirbyteConnectorReadError as ex:
Expand All @@ -332,6 +342,7 @@ def check(self) -> None:
def install(self) -> None:
"""Install the connector if it is not yet installed."""
self.executor.install()
print("For configuration instructions, see: \n" f"{self.docs_url}#reference\n")

def uninstall(self) -> None:
"""Uninstall the connector if it is installed.
Expand Down
1 change: 1 addition & 0 deletions airbyte-lib/airbyte_lib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import cast

import sqlalchemy
from rich import print


# Compare to documentation here: https://docs.airbyte.com/understanding-airbyte/supported-data-types
Expand Down
1 change: 1 addition & 0 deletions airbyte-lib/airbyte_lib/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from pathlib import Path

import yaml
from rich import print

import airbyte_lib as ab
from airbyte_lib import exceptions as exc
Expand Down
13 changes: 13 additions & 0 deletions airbyte-lib/docs/generated/airbyte_lib.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading