Skip to content

Commit 7149962

Browse files
committed
Merge branch 'main' into pnilan/feat/implement-validators
2 parents 01415e2 + 8906ed2 commit 7149962

File tree

18 files changed

+559
-405
lines changed

18 files changed

+559
-405
lines changed

airbyte_cdk/cli/airbyte_cdk/_connector.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@
4444

4545
import rich_click as click
4646

47-
# from airbyte_cdk.test.standard_tests import pytest_hooks
48-
from airbyte_cdk.cli.airbyte_cdk._util import resolve_connector_name_and_directory
49-
from airbyte_cdk.test.standard_tests.test_resources import find_connector_root_from_name
5047
from airbyte_cdk.test.standard_tests.util import create_connector_test_suite
5148

49+
# from airbyte_cdk.test.standard_tests import pytest_hooks
50+
from airbyte_cdk.utils.connector_paths import (
51+
find_connector_root_from_name,
52+
resolve_connector_name_and_directory,
53+
)
54+
5255
click.rich_click.TEXT_MARKUP = "markdown"
5356

5457
pytest: ModuleType | None
@@ -63,7 +66,7 @@
6366

6467
TEST_FILE_TEMPLATE = '''
6568
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
66-
"""FAST Airbyte Standard Tests for the source_pokeapi_w_components source."""
69+
"""FAST Airbyte Standard Tests for the {connector_name} source."""
6770
6871
#from airbyte_cdk.test.standard_tests import {base_class_name}
6972
from airbyte_cdk.test.standard_tests.util import create_connector_test_suite
@@ -78,7 +81,7 @@
7881
)
7982
8083
# class TestSuite({base_class_name}):
81-
# """Test suite for the source_pokeapi_w_components source.
84+
# """Test suite for the {connector_name} source.
8285
8386
# This class inherits from SourceTestSuiteBase and implements all of the tests in the suite.
8487
@@ -98,15 +101,11 @@ def connector_cli_group() -> None:
98101

99102

100103
@connector_cli_group.command()
101-
@click.option(
102-
"--connector-name",
104+
@click.argument(
105+
"connector",
106+
required=False,
103107
type=str,
104-
help="Name of the connector to test. Ignored if --connector-directory is provided.",
105-
)
106-
@click.option(
107-
"--connector-directory",
108-
type=click.Path(exists=True, file_okay=False, path_type=Path),
109-
help="Path to the connector directory.",
108+
metavar="[CONNECTOR]",
110109
)
111110
@click.option(
112111
"--collect-only",
@@ -115,15 +114,17 @@ def connector_cli_group() -> None:
115114
help="Only collect tests, do not run them.",
116115
)
117116
def test(
118-
connector_name: str | None = None,
119-
connector_directory: Path | None = None,
117+
connector: str | Path | None = None,
120118
*,
121119
collect_only: bool = False,
122120
) -> None:
123121
"""Run connector tests.
124122
125123
This command runs the standard connector tests for a specific connector.
126124
125+
[CONNECTOR] can be a connector name (e.g. 'source-pokeapi'), a path to a connector directory, or omitted to use the current working directory.
126+
If a string containing '/' is provided, it is treated as a path. Otherwise, it is treated as a connector name.
127+
127128
If no connector name or directory is provided, we will look within the current working
128129
directory. If the current working directory is not a connector directory (e.g. starting
129130
with 'source-') and no connector name or path is provided, the process will fail.
@@ -133,10 +134,7 @@ def test(
133134
"pytest is not installed. Please install pytest to run the connector tests."
134135
)
135136
click.echo("Connector test command executed.")
136-
connector_name, connector_directory = resolve_connector_name_and_directory(
137-
connector_name=connector_name,
138-
connector_directory=connector_directory,
139-
)
137+
connector_name, connector_directory = resolve_connector_name_and_directory(connector)
140138

141139
connector_test_suite = create_connector_test_suite(
142140
connector_name=connector_name if not connector_directory else None,
@@ -152,7 +150,7 @@ def test(
152150

153151
file_text = TEST_FILE_TEMPLATE.format(
154152
base_class_name=connector_test_suite.__bases__[0].__name__,
155-
connector_directory=str(connector_directory),
153+
connector_name=connector_name,
156154
)
157155
test_file_path = Path() / ".tmp" / "integration_tests/test_airbyte_standards.py"
158156
test_file_path = test_file_path.resolve().absolute()

airbyte_cdk/cli/airbyte_cdk/_image.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
import rich_click as click
1212

13-
from airbyte_cdk.cli.airbyte_cdk._util import resolve_connector_name_and_directory
1413
from airbyte_cdk.models.connector_metadata import MetadataFile
14+
from airbyte_cdk.utils.connector_paths import resolve_connector_name_and_directory
1515
from airbyte_cdk.utils.docker import (
1616
ConnectorImageBuildError,
1717
build_connector_image,
@@ -28,41 +28,38 @@ def image_cli_group() -> None:
2828

2929

3030
@image_cli_group.command()
31-
@click.option(
32-
"--connector-name",
31+
@click.argument(
32+
"connector",
33+
required=False,
3334
type=str,
34-
help="Name of the connector to test. Ignored if --connector-directory is provided.",
35-
)
36-
@click.option(
37-
"--connector-directory",
38-
type=click.Path(exists=True, file_okay=False, path_type=Path),
39-
help="Path to the connector directory.",
35+
metavar="[CONNECTOR]",
4036
)
4137
@click.option("--tag", default="dev", help="Tag to apply to the built image (default: dev)")
4238
@click.option("--no-verify", is_flag=True, help="Skip verification of the built image")
39+
@click.option(
40+
"--dockerfile",
41+
type=click.Path(exists=True, file_okay=True, path_type=Path),
42+
help="Optional. Override the Dockerfile used for building the image.",
43+
)
4344
def build(
44-
connector_name: str | None = None,
45-
connector_directory: Path | None = None,
45+
connector: str | None = None,
4646
*,
4747
tag: str = "dev",
4848
no_verify: bool = False,
49+
dockerfile: Path | None = None,
4950
) -> None:
5051
"""Build a connector Docker image.
5152
52-
This command builds a Docker image for a connector, using either
53-
the connector's Dockerfile or a base image specified in the metadata.
54-
The image is built for both AMD64 and ARM64 architectures.
53+
[CONNECTOR] can be a connector name (e.g. 'source-pokeapi'), a path to a connector directory, or omitted to use the current working directory.
54+
If a string containing '/' is provided, it is treated as a path. Otherwise, it is treated as a connector name.
5555
"""
5656
if not verify_docker_installation():
5757
click.echo(
5858
"Docker is not installed or not running. Please install Docker and try again.", err=True
5959
)
6060
sys.exit(1)
6161

62-
connector_name, connector_directory = resolve_connector_name_and_directory(
63-
connector_name=connector_name,
64-
connector_directory=connector_directory,
65-
)
62+
connector_name, connector_directory = resolve_connector_name_and_directory(connector)
6663

6764
metadata_file_path: Path = connector_directory / "metadata.yaml"
6865
try:
@@ -81,6 +78,7 @@ def build(
8178
metadata=metadata,
8279
tag=tag,
8380
no_verify=no_verify,
81+
dockerfile_override=dockerfile or None,
8482
)
8583
except ConnectorImageBuildError as e:
8684
click.echo(

airbyte_cdk/cli/airbyte_cdk/_secrets.py

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
from rich.console import Console
4444
from rich.table import Table
4545

46-
from airbyte_cdk.cli.airbyte_cdk._util import (
46+
from airbyte_cdk.utils.connector_paths import (
4747
resolve_connector_name,
4848
resolve_connector_name_and_directory,
4949
)
@@ -73,15 +73,11 @@ def secrets_cli_group() -> None:
7373

7474

7575
@secrets_cli_group.command()
76-
@click.option(
77-
"--connector-name",
76+
@click.argument(
77+
"connector",
78+
required=False,
7879
type=str,
79-
help="Name of the connector to fetch secrets for. Ignored if --connector-directory is provided.",
80-
)
81-
@click.option(
82-
"--connector-directory",
83-
type=click.Path(exists=True, file_okay=False, path_type=Path),
84-
help="Path to the connector directory.",
80+
metavar="[CONNECTOR]",
8581
)
8682
@click.option(
8783
"--gcp-project-id",
@@ -97,8 +93,7 @@ def secrets_cli_group() -> None:
9793
default=False,
9894
)
9995
def fetch(
100-
connector_name: str | None = None,
101-
connector_directory: Path | None = None,
96+
connector: str | Path | None = None,
10297
gcp_project_id: str = AIRBYTE_INTERNAL_GCP_PROJECT,
10398
print_ci_secrets_masks: bool = False,
10499
) -> None:
@@ -107,24 +102,24 @@ def fetch(
107102
This command fetches secrets for a connector from Google Secret Manager and writes them
108103
to the connector's secrets directory.
109104
105+
[CONNECTOR] can be a connector name (e.g. 'source-pokeapi'), a path to a connector directory, or omitted to use the current working directory.
106+
If a string containing '/' is provided, it is treated as a path. Otherwise, it is treated as a connector name.
107+
110108
If no connector name or directory is provided, we will look within the current working
111109
directory. If the current working directory is not a connector directory (e.g. starting
112110
with 'source-') and no connector name or path is provided, the process will fail.
113111
114112
The `--print-ci-secrets-masks` option will print the GitHub CI mask for the secrets.
115113
This is useful for masking secrets in CI logs.
116114
117-
WARNING: This action causes the secrets to be printed in clear text to `STDOUT`. For security
118-
reasons, this function will only execute if the `CI` environment variable is set. Otherwise,
119-
masks will not be printed.
115+
WARNING: The `--print-ci-secrets-masks` option causes the secrets to be printed in clear text to
116+
`STDOUT`. For security reasons, this argument will be ignored if the `CI` environment
117+
variable is not set.
120118
"""
121119
click.echo("Fetching secrets...", err=True)
122120

123121
client = _get_gsm_secrets_client()
124-
connector_name, connector_directory = resolve_connector_name_and_directory(
125-
connector_name=connector_name,
126-
connector_directory=connector_directory,
127-
)
122+
connector_name, connector_directory = resolve_connector_name_and_directory(connector)
128123
secrets_dir = _get_secrets_dir(
129124
connector_directory=connector_directory,
130125
connector_name=connector_name,
@@ -289,21 +284,7 @@ def _get_secrets_dir(
289284
connector_name: str,
290285
ensure_exists: bool = True,
291286
) -> Path:
292-
try:
293-
connector_name, connector_directory = resolve_connector_name_and_directory(
294-
connector_name=connector_name,
295-
connector_directory=connector_directory,
296-
)
297-
except FileNotFoundError as e:
298-
raise FileNotFoundError(
299-
f"Could not find connector directory for '{connector_name}'. "
300-
"Please provide the --connector-directory option with the path to the connector. "
301-
"Note: This command requires either running from within a connector directory, "
302-
"being in the airbyte monorepo, or explicitly providing the connector directory path."
303-
) from e
304-
except ValueError as e:
305-
raise ValueError(str(e))
306-
287+
_ = connector_name # Unused, but it may be used in the future for logging
307288
secrets_dir = connector_directory / "secrets"
308289
if ensure_exists:
309290
secrets_dir.mkdir(parents=True, exist_ok=True)

airbyte_cdk/cli/airbyte_cdk/_util.py

Lines changed: 0 additions & 69 deletions
This file was deleted.

airbyte_cdk/sources/declarative/models/base_model_with_deprecations.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
# WHEN DEPRECATED FIELDS ARE ACCESSED
55

66
import warnings
7+
8+
# ignore the SyntaxWarning in the Airbyte log messages, during the string evaluation
9+
warnings.filterwarnings("ignore", category=SyntaxWarning)
10+
711
from typing import Any, List
812

913
from pydantic.v1 import BaseModel
@@ -12,9 +16,10 @@
1216

1317
# format the warning message
1418
warnings.formatwarning = (
15-
lambda message, category, *args, **kwargs: f"{category.__name__}: {message}"
19+
lambda message, category, *args, **kwargs: f"{category.__name__}: {message}\n"
1620
)
1721

22+
1823
FIELDS_TAG = "__fields__"
1924
DEPRECATED = "deprecated"
2025
DEPRECATION_MESSAGE = "deprecation_message"

airbyte_cdk/test/entrypoint_wrapper.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ def records(self) -> List[AirbyteMessage]:
8282
def state_messages(self) -> List[AirbyteMessage]:
8383
return self._get_message_by_types([Type.STATE])
8484

85+
@property
86+
def spec_messages(self) -> List[AirbyteMessage]:
87+
return self._get_message_by_types([Type.SPEC])
88+
8589
@property
8690
def connection_status_messages(self) -> List[AirbyteMessage]:
8791
return self._get_message_by_types([Type.CONNECTION_STATUS])

0 commit comments

Comments
 (0)