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

SAT: support yaml files in spec_path #12228

Merged
merged 4 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.1.50
Added support for passing a `.yaml` file as `spec_path`.

## 0.1.49
Fixed schema parsing when a JSONschema `type` was not present - we now assume `object` if the `type` is not present.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ COPY pytest.ini setup.py ./
COPY source_acceptance_test ./source_acceptance_test
RUN pip install .

LABEL io.airbyte.version=0.1.49
LABEL io.airbyte.version=0.1.50
LABEL io.airbyte.name=airbyte/source-acceptance-test

ENTRYPOINT ["python", "-m", "pytest", "-p", "source_acceptance_test.plugin", "-r", "fEsx"]
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
)
from docker import errors
from source_acceptance_test.config import Config
from source_acceptance_test.utils import ConnectorRunner, SecretDict, load_config
from source_acceptance_test.utils import ConnectorRunner, SecretDict, load_config, load_yaml_or_json_path


@pytest.fixture(name="base_path")
Expand Down Expand Up @@ -117,7 +117,8 @@ def malformed_connector_config_fixture(connector_config) -> MutableMapping[str,

@pytest.fixture(name="connector_spec")
def connector_spec_fixture(connector_spec_path) -> ConnectorSpecification:
return ConnectorSpecification.parse_file(connector_spec_path)
spec_obj = load_yaml_or_json_path(connector_spec_path)
return ConnectorSpecification.parse_obj(spec_obj)
Comment on lines 119 to +121
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like we can't test these fixtures directly, so moved the yaml/json logic into a utility method



@pytest.fixture(name="docker_runner")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def test_config_match_spec(self, actual_connector_spec: ConnectorSpecification,
def test_match_expected(self, connector_spec: ConnectorSpecification, actual_connector_spec: ConnectorSpecification):
"""Check that spec call returns a spec equals to expected one"""
if connector_spec:
assert actual_connector_spec == connector_spec, "Spec should be equal to the one in spec.json file"
assert actual_connector_spec == connector_spec, "Spec should be equal to the one in spec.yaml or spec.json file"

def test_docker_env(self, actual_connector_spec: ConnectorSpecification, docker_runner: ConnectorRunner):
"""Check that connector's docker image has required envs"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
# Copyright (c) 2021 Airbyte, Inc., all rights reserved.
#
from .asserts import verify_records_schema
from .common import SecretDict, filter_output, full_refresh_only_catalog, incremental_only_catalog, load_config
from .common import SecretDict, filter_output, full_refresh_only_catalog, incremental_only_catalog, load_config, load_yaml_or_json_path
from .compare import diff_dicts, make_hashable
from .connector_runner import ConnectorRunner
from .json_schema_helper import JsonSchemaHelper

__all__ = [
"JsonSchemaHelper",
"load_config",
"load_yaml_or_json_path",
"filter_output",
"full_refresh_only_catalog",
"incremental_only_catalog",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Copyright (c) 2021 Airbyte, Inc., all rights reserved.
#


import json
from collections import UserDict
from pathlib import Path
from typing import Iterable, List, Union
Expand Down Expand Up @@ -102,3 +102,15 @@ def _find_keyword(schema, key, _skip=False):
except StopIteration:
return True
return False


def load_yaml_or_json_path(path: Path):
with open(str(path), "r") as file:
file_data = file.read()
file_ext = path.suffix
if file_ext == ".json":
return json.loads(file_data)
elif file_ext == ".yaml":
return load(file_data, Loader=Loader)
else:
raise RuntimeError("path must be a '.yaml' or '.json' file")
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@
# Copyright (c) 2021 Airbyte, Inc., all rights reserved.
#

import json
import random
import string
import tempfile
import time
from functools import partial
from pathlib import Path
from typing import Iterable
from unittest.mock import Mock

import docker
import pytest
import yaml
from docker.errors import ContainerError, NotFound
from source_acceptance_test.utils.common import load_yaml_or_json_path
from source_acceptance_test.utils.compare import make_hashable
from source_acceptance_test.utils.connector_runner import ConnectorRunner

Expand Down Expand Up @@ -310,3 +315,34 @@ def test_not_found_container():

with pytest.raises(NotFound):
list(ConnectorRunner.read(new_container, command=cmd))


class TestLoadYamlOrJsonPath:
VALID_SPEC = {
"documentationUrl": "https://google.com",
"connectionSpecification": {
"type": "object",
"required": ["api_token"],
"additionalProperties": False,
"properties": {"api_token": {"type": "string"}},
},
}

def test_load_json(self):
with tempfile.NamedTemporaryFile("w", suffix=".json") as f:
f.write(json.dumps(self.VALID_SPEC))
f.flush()
actual = load_yaml_or_json_path(Path(f.name))
assert self.VALID_SPEC == actual

def test_load_yaml(self):
with tempfile.NamedTemporaryFile("w", suffix=".yaml") as f:
f.write(yaml.dump(self.VALID_SPEC))
f.flush()
actual = load_yaml_or_json_path(Path(f.name))
assert self.VALID_SPEC == actual

def test_load_other(self):
with tempfile.NamedTemporaryFile("w", suffix=".txt") as f:
with pytest.raises(RuntimeError):
load_yaml_or_json_path(Path(f.name))