Skip to content

feat(file-based): Migrate unstructured document parser to MarkItDown#1062

Draft
Aaron ("AJ") Steers (aaronsteers) wants to merge 3 commits into
mainfrom
devin/1782939132-markitdown-migration
Draft

feat(file-based): Migrate unstructured document parser to MarkItDown#1062
Aaron ("AJ") Steers (aaronsteers) wants to merge 3 commits into
mainfrom
devin/1782939132-markitdown-migration

fix: revert config descriptions, pin requests_cache <1.3

484572b
Select commit
Loading
Failed to load commit list.
Sign in for the full log view
GitHub Actions / PyTest Results (Full) failed Jul 1, 2026 in 0s

104 fail, 12 skipped, 3 997 pass in 20635d 21h 27m 42s

4 113 tests  ±0   3 997 ✅  - 31   20635d 21h 27m 42s ⏱️ - 5m 10s
    1 suites ±0      12 💤 ± 0 
    1 files   ±0     104 ❌ +31 

Results for commit 484572b. ± Comparison against earlier commit 27268cf.

Annotations

Check warning on line 0 in unit_tests.test_entrypoint

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_run_check_with_exception (unit_tests.test_entrypoint) failed

build/test-results/pytest-results.xml [took 1m 43s]
Raw output
pydantic_core._pydantic_core.ValidationError: 1 validation error for RunnablePassthrough[Any]
name
  Field required [type=missing, input_value={'func': None, 'afunc': None, 'input_type': None}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.14/v/missing
args = ()
kwargs = {'config_mock': {'username': 'fake'}, 'entrypoint': <airbyte_cdk.entrypoint.AirbyteEntrypoint object at 0x7fa63b942300>, 'mocker': <pytest_mock.plugin.MockerFixture object at 0x7fa63b8a9fd0>, 'spec_mock': <MagicMock id='140351940862336'>}

    @functools.wraps(func)
    def wrapper(*args: "P.args", **kwargs: "P.kwargs") -> T:
>       with self as time_factory:

../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/freezegun/api.py:950: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/freezegun/api.py:738: in __enter__
    return self.start()
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/freezegun/api.py:827: in start
    module_attrs = _get_cached_module_attributes(module)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/freezegun/api.py:144: in _get_cached_module_attributes
    _setup_module_cache(module)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/freezegun/api.py:123: in _setup_module_cache
    all_module_attributes = _get_module_attributes(module)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/freezegun/api.py:112: in _get_module_attributes
    attribute_value = getattr(module, attribute_name)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/langchain_core/runnables/__init__.py:130: in __getattr__
    result = import_attr(attr_name, module_name, __spec__.parent)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/langchain_core/_import_utils.py:36: in import_attr
    module = import_module(f".{module_name}", package=package)
/usr/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/langchain_core/runnables/passthrough.py:349: in <module>
    _graph_passthrough = RunnablePassthrough[Any]()
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/langchain_core/runnables/passthrough.py:178: in __init__
    super().__init__(func=func, afunc=afunc, input_type=input_type, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = RunnablePassthrough[Any](), args = ()
kwargs = {'afunc': None, 'func': None, 'input_type': None}

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        """"""  # noqa: D419  # Intentional blank docstring
>       super().__init__(*args, **kwargs)
E       pydantic_core._pydantic_core.ValidationError: 1 validation error for RunnablePassthrough[Any]
E       name
E         Field required [type=missing, input_value={'func': None, 'afunc': None, 'input_type': None}, input_type=dict]
E           For further information visit https://errors.pydantic.dev/2.14/v/missing

../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/langchain_core/load/serializable.py:118: ValidationError

Check warning on line 0 in unit_tests.connector_builder.test_connector_builder_handler

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_full_resolve_manifest (unit_tests.connector_builder.test_connector_builder_handler) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AttributeError: 'NoneType' object has no attribute 'data'
valid_resolve_manifest_config_file = PosixPath('/tmp/pytest-of-runner/pytest-0/test_full_resolve_manifest0/config.json')

    def test_full_resolve_manifest(valid_resolve_manifest_config_file):
        config = copy.deepcopy(RESOLVE_DYNAMIC_STREAM_MANIFEST_CONFIG)
        command = config["__command"]
        source = ConcurrentDeclarativeSource(
            catalog=None, config=config, state=None, source_config=DYNAMIC_STREAM_MANIFEST
        )
        limits = TestLimits(max_streams=2)
        with HttpMocker() as http_mocker:
            http_mocker.get(
                HttpRequest(url="https://api.test.com/parents"),
                HttpResponse(body=json.dumps([{"id": 1}, {"id": 2}])),
            )
            parent_ids = [1, 2]
            for parent_id in parent_ids:
                http_mocker.get(
                    HttpRequest(url=f"https://api.test.com/parent/{parent_id}/items"),
                    HttpResponse(
                        body=json.dumps(
                            [
                                {"id": 1, "name": "item_1"},
                                {"id": 2, "name": "item_2"},
                            ]
                        )
                    ),
                )
            resolved_manifest = handle_connector_builder_request(
                source, command, config, create_configured_catalog("dummy_stream"), _A_STATE, limits
            )
    
        expected_resolved_manifest = {
            "version": "0.30.3",
            "definitions": {
                "retriever": {
                    "paginator": {
                        "type": "DefaultPaginator",
                        "page_size": 2,
                        "page_size_option": {
                            "inject_into": "request_parameter",
                            "field_name": "page_size",
                        },
                        "page_token_option": {"inject_into": "path", "type": "RequestPath"},
                        "pagination_strategy": {
                            "type": "CursorPagination",
                            "cursor_value": "{{ response._metadata.next }}",
                            "page_size": 2,
                        },
                    },
                    "partition_router": {
                        "type": "ListPartitionRouter",
                        "values": ["0", "1", "2", "3", "4", "5", "6", "7"],
                        "cursor_field": "item_id",
                    },
                    "requester": {
                        "path": "/v3/marketing/lists",
                        "authenticator": {
                            "type": "BearerAuthenticator",
                            "api_token": "{{ config.apikey }}",
                        },
                        "request_parameters": {"a_param": "10"},
                    },
                    "record_selector": {"extractor": {"field_path": ["result"]}},
                }
            },
            "streams": [
                {
                    "type": "DeclarativeStream",
                    "retriever": {
                        "paginator": {
                            "type": "DefaultPaginator",
                            "page_size": 2,
                            "page_size_option": {
                                "inject_into": "request_parameter",
                                "field_name": "page_size",
                                "type": "RequestOption",
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                                "$parameters": {
                                    "name": "stream_with_custom_requester",
                                    "primary_key": "id",
                                    "url_base": "https://api.sendgrid.com",
                                },
                            },
                            "page_token_option": {
                                "inject_into": "path",
                                "type": "RequestPath",
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                                "$parameters": {
                                    "name": "stream_with_custom_requester",
                                    "primary_key": "id",
                                    "url_base": "https://api.sendgrid.com",
                                },
                            },
                            "pagination_strategy": {
                                "type": "CursorPagination",
                                "cursor_value": "{{ response._metadata.next }}",
                                "page_size": 2,
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                                "$parameters": {
                                    "name": "stream_with_custom_requester",
                                    "primary_key": "id",
                                    "url_base": "https://api.sendgrid.com",
                                },
                            },
                            "name": "stream_with_custom_requester",
                            "primary_key": "id",
                            "url_base": "https://api.sendgrid.com",
                            "$parameters": {
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                            },
                        },
                        "partition_router": {
                            "type": "ListPartitionRouter",
                            "values": ["0", "1", "2", "3", "4", "5", "6", "7"],
                            "cursor_field": "item_id",
                            "name": "stream_with_custom_requester",
                            "primary_key": "id",
                            "url_base": "https://api.sendgrid.com",
                            "$parameters": {
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                            },
                        },
                        "requester": {
                            "path": "/v3/marketing/lists",
                            "authenticator": {
                                "type": "BearerAuthenticator",
                                "api_token": "{{ config.apikey }}",
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                                "$parameters": {
                                    "name": "stream_with_custom_requester",
                                    "primary_key": "id",
                                    "url_base": "https://api.sendgrid.com",
                                },
                            },
                            "request_parameters": {"a_param": "10"},
                            "type": "HttpRequester",
                            "name": "stream_with_custom_requester",
                            "primary_key": "id",
                            "url_base": "https://api.sendgrid.com",
                            "$parameters": {
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                            },
                        },
                        "record_selector": {
                            "extractor": {
                                "field_path": ["result"],
                                "type": "DpathExtractor",
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                                "$parameters": {
                                    "name": "stream_with_custom_requester",
                                    "primary_key": "id",
                                    "url_base": "https://api.sendgrid.com",
                                },
                            },
                            "type": "RecordSelector",
                            "name": "stream_with_custom_requester",
                            "primary_key": "id",
                            "url_base": "https://api.sendgrid.com",
                            "$parameters": {
                                "name": "stream_with_custom_requester",
                                "primary_key": "id",
                                "url_base": "https://api.sendgrid.com",
                            },
                        },
                        "type": "SimpleRetriever",
                        "name": "stream_with_custom_requester",
                        "primary_key": "id",
                        "url_base": "https://api.sendgrid.com",
                        "$parameters": {
                            "name": "stream_with_custom_requester",
                            "primary_key": "id",
                            "url_base": "https://api.sendgrid.com",
                        },
                    },
                    "name": "stream_with_custom_requester",
                    "primary_key": "id",
                    "url_base": "https://api.sendgrid.com",
                    "$parameters": {
                        "name": "stream_with_custom_requester",
                        "primary_key": "id",
                        "url_base": "https://api.sendgrid.com",
                    },
                    "dynamic_stream_name": None,
                },
                {
                    "type": "DeclarativeStream",
                    "name": "parent_1_item_1",
                    "primary_key": [],
                    "schema_loader": {
                        "type": "InlineSchemaLoader",
                        "schema": {
                            "$schema": "http://json-schema.org/schema#",
                            "properties": {"ABC": {"type": "number"}, "AED": {"type": "number"}},
                            "type": "object",
                        },
                    },
                    "retriever": {
                        "type": "SimpleRetriever",
                        "requester": {
                            "type": "HttpRequester",
                            "url_base": "https://api.test.com",
                            "path": "1/1",
                            "http_method": "GET",
                            "authenticator": {
                                "type": "ApiKeyAuthenticator",
                                "header": "apikey",
                                "api_token": "{{ config['api_key'] }}",
                            },
                        },
                        "record_selector": {
                            "type": "RecordSelector",
                            "extractor": {"type": "DpathExtractor", "field_path": []},
                        },
                        "paginator": {"type": "NoPagination"},
                    },
                    "dynamic_stream_name": "TestDynamicStream",
                },
                {
                    "type": "DeclarativeStream",
                    "name": "parent_1_item_2",
                    "primary_key": [],
                    "schema_loader": {
                        "type": "InlineSchemaLoader",
                        "schema": {
                            "$schema": "http://json-schema.org/schema#",
                            "properties": {"ABC": {"type": "number"}, "AED": {"type": "number"}},
                            "type": "object",
                        },
                    },
                    "retriever": {
                        "type": "SimpleRetriever",
                        "requester": {
                            "type": "HttpRequester",
                            "url_base": "https://api.test.com",
                            "path": "1/2",
                            "http_method": "GET",
                            "authenticator": {
                                "type": "ApiKeyAuthenticator",
                                "header": "apikey",
                                "api_token": "{{ config['api_key'] }}",
                            },
                        },
                        "record_selector": {
                            "type": "RecordSelector",
                            "extractor": {"type": "DpathExtractor", "field_path": []},
                        },
                        "paginator": {"type": "NoPagination"},
                    },
                    "dynamic_stream_name": "TestDynamicStream",
                },
            ],
            "check": {"type": "CheckStream", "stream_names": ["lists"]},
            "spec": {
                "connection_specification": {
                    "$schema": "http://json-schema.org/draft-07/schema#",
                    "type": "object",
                    "required": [],
                    "properties": {},
                    "additionalProperties": True,
                },
                "type": "Spec",
            },
            "dynamic_streams": [
                {
                    "type": "DynamicDeclarativeStream",
                    "name": "TestDynamicStream",
                    "stream_template": {
                        "type": "DeclarativeStream",
                        "name": "",
                        "primary_key": [],
                        "schema_loader": {
                            "type": "InlineSchemaLoader",
                            "schema": {
                                "$schema": "http://json-schema.org/schema#",
                                "properties": {"ABC": {"type": "number"}, "AED": {"type": "number"}},
                                "type": "object",
                            },
                        },
                        "retriever": {
                            "type": "SimpleRetriever",
                            "requester": {
                                "type": "HttpRequester",
                                "url_base": "https://api.test.com",
                                "path": "",
                                "http_method": "GET",
                                "authenticator": {
                                    "type": "ApiKeyAuthenticator",
                                    "header": "apikey",
                                    "api_token": "{{ config['api_key'] }}",
                                },
                            },
                            "record_selector": {
                                "type": "RecordSelector",
                                "extractor": {"type": "DpathExtractor", "field_path": []},
                            },
                            "paginator": {"type": "NoPagination"},
                        },
                    },
                    "components_resolver": {
                        "type": "HttpComponentsResolver",
                        "retriever": {
                            "type": "SimpleRetriever",
                            "requester": {
                                "type": "HttpRequester",
                                "url_base": "https://api.test.com",
                                "path": "parent/{{ stream_partition.parent_id }}/items",
                                "http_method": "GET",
                                "authenticator": {
                                    "type": "ApiKeyAuthenticator",
                                    "header": "apikey",
                                    "api_token": "{{ config['api_key'] }}",
                                },
                                "use_cache": True,
                            },
                            "record_selector": {
                                "type": "RecordSelector",
                                "extractor": {"type": "DpathExtractor", "field_path": []},
                            },
                            "paginator": {"type": "NoPagination"},
                            "partition_router": {
                                "type": "SubstreamPartitionRouter",
                                "parent_stream_configs": [
                                    {
                                        "type": "ParentStreamConfig",
                                        "parent_key": "id",
                                        "partition_field": "parent_id",
                                        "stream": {
                                            "type": "DeclarativeStream",
                                            "name": "parent",
                                            "retriever": {
                                                "type": "SimpleRetriever",
                                                "requester": {
                                                    "type": "HttpRequester",
                                                    "url_base": "https://api.test.com",
                                                    "path": "/parents",
                                                    "http_method": "GET",
                                                    "authenticator": {
                                                        "type": "ApiKeyAuthenticator",
                                                        "header": "apikey",
                                                        "api_token": "{{ config['api_key'] }}",
                                                    },
                                                },
                                                "record_selector": {
                                                    "type": "RecordSelector",
                                                    "extractor": {
                                                        "type": "DpathExtractor",
                                                        "field_path": [],
                                                    },
                                                },
                                            },
                                            "schema_loader": {
                                                "type": "InlineSchemaLoader",
                                                "schema": {
                                                    "$schema": "http://json-schema.org/schema#",
                                                    "properties": {"id": {"type": "integer"}},
                                                    "type": "object",
                                                },
                                            },
                                        },
                                    }
                                ],
                            },
                        },
                        "components_mapping": [
                            {
                                "type": "ComponentMappingDefinition",
                                "field_path": ["name"],
                                "value": "parent_{{stream_slice['parent_id']}}_{{components_values['name']}}",
                            },
                            {
                                "type": "ComponentMappingDefinition",
                                "field_path": ["retriever", "requester", "path"],
                                "value": "{{ stream_slice['parent_id'] }}/{{ components_values['id'] }}",
                            },
                        ],
                    },
                }
            ],
            "type": "DeclarativeSource",
        }
>       assert resolved_manifest.record.data["manifest"] == expected_resolved_manifest
E       AttributeError: 'NoneType' object has no attribute 'data'

unit_tests/connector_builder/test_connector_builder_handler.py:1805: AttributeError

Check warning on line 0 in unit_tests.legacy.sources.declarative.test_manifest_declarative_source

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_slice_checkpoint[test_with_pagination_and_partition_router-manifest0-pages0-2] (unit_tests.legacy.sources.declarative.test_manifest_declarative_source) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert 1 == 2
 +  where 1 = len([AirbyteStateMessage(type=<AirbyteStateType.STREAM: 'STREAM'>, stream=AirbyteStreamState(stream_descriptor=StreamDescriptor(name='Rates', namespace=None), stream_state=AirbyteStateBlob()), global_=None, data=None, sourceStats=None, destinationStats=None)])
test_name = 'test_with_pagination_and_partition_router'
manifest = {'check': {'stream_names': ['Rates'], 'type': 'CheckStream'}, 'spec': {'connection_specification': {'$schema': 'http:/...T', 'path': '/exchangerates_data/latest', 'request_body_json': {}, ...}, ...}, ...}], 'type': 'DeclarativeSource', ...}
pages = (<Response [200]>, <Response [200]>, <Response [200]>)
expected_states_qty = 2

    @pytest.mark.parametrize(
        "test_name, manifest, pages, expected_states_qty",
        [
            (
                "test_with_pagination_and_partition_router",
                {
                    "version": "0.34.2",
                    "type": "DeclarativeSource",
                    "check": {"type": "CheckStream", "stream_names": ["Rates"]},
                    "streams": [
                        {
                            "type": "DeclarativeStream",
                            "name": "Rates",
                            "primary_key": [],
                            "schema_loader": {
                                "type": "InlineSchemaLoader",
                                "schema": {
                                    "$schema": "http://json-schema.org/schema#",
                                    "properties": {
                                        "ABC": {"type": "number"},
                                        "AED": {"type": "number"},
                                        "partition": {"type": "number"},
                                    },
                                    "type": "object",
                                },
                            },
                            "retriever": {
                                "type": "SimpleRetriever",
                                "requester": {
                                    "type": "HttpRequester",
                                    "url_base": "https://api.apilayer.com",
                                    "path": "/exchangerates_data/latest",
                                    "http_method": "GET",
                                    "request_parameters": {},
                                    "request_headers": {},
                                    "request_body_json": {},
                                    "authenticator": {
                                        "type": "ApiKeyAuthenticator",
                                        "header": "apikey",
                                        "api_token": "{{ config['api_key'] }}",
                                    },
                                },
                                "partition_router": {
                                    "type": "ListPartitionRouter",
                                    "values": ["0", "1"],
                                    "cursor_field": "partition",
                                },
                                "record_selector": {
                                    "type": "RecordSelector",
                                    "extractor": {"type": "DpathExtractor", "field_path": ["rates"]},
                                },
                                "paginator": {
                                    "type": "DefaultPaginator",
                                    "page_size": 2,
                                    "page_size_option": {
                                        "inject_into": "request_parameter",
                                        "field_name": "page_size",
                                    },
                                    "page_token_option": {"inject_into": "path", "type": "RequestPath"},
                                    "pagination_strategy": {
                                        "type": "CursorPagination",
                                        "cursor_value": "{{ response._metadata.next }}",
                                        "page_size": 2,
                                    },
                                },
                            },
                            "incremental_sync": {
                                "type": "DatetimeBasedCursor",
                                "cursor_datetime_formats": ["%Y-%m-%dT%H:%M:%S.%fZ"],
                                "datetime_format": "%Y-%m-%dT%H:%M:%S.%fZ",
                                "cursor_field": "updated_at",
                                "start_datetime": {
                                    "datetime": "{{ config.get('start_date', '2020-10-16T00:00:00.000Z') }}"
                                },
                            },
                        }
                    ],
                    "spec": {
                        "connection_specification": {
                            "$schema": "http://json-schema.org/draft-07/schema#",
                            "type": "object",
                            "required": ["api_key"],
                            "properties": {
                                "api_key": {
                                    "type": "string",
                                    "title": "API Key",
                                    "airbyte_secret": True,
                                },
                                "start_date": {
                                    "title": "Start Date",
                                    "description": "UTC date and time in the format YYYY-MM-DDTHH:MM:SS.000Z. During incremental sync, any data generated before this date will not be replicated. If left blank, the start date will be set to 2 years before the present date.",
                                    "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$",
                                    "pattern_descriptor": "YYYY-MM-DDTHH:MM:SS.000Z",
                                    "examples": ["2020-11-16T00:00:00.000Z"],
                                    "type": "string",
                                    "format": "date-time",
                                },
                            },
                            "additionalProperties": True,
                        },
                        "documentation_url": "https://example.org",
                        "type": "Spec",
                    },
                },
                (
                    _create_page(
                        {
                            "rates": [
                                {"ABC": 0, "partition": 0, "updated_at": "2020-11-16T00:00:00.000Z"},
                                {"AED": 1, "partition": 0, "updated_at": "2020-11-16T00:00:00.000Z"},
                            ],
                            "_metadata": {"next": "next"},
                        }
                    ),
                    _create_page(
                        {
                            "rates": [
                                {"USD": 3, "partition": 0, "updated_at": "2020-11-16T00:00:00.000Z"}
                            ],
                            "_metadata": {},
                        }
                    ),
                    _create_page(
                        {
                            "rates": [
                                {"ABC": 2, "partition": 1, "updated_at": "2020-11-16T00:00:00.000Z"}
                            ],
                            "_metadata": {},
                        }
                    ),
                ),
                2,
            ),
        ],
    )
    def test_slice_checkpoint(test_name, manifest, pages, expected_states_qty):
        _stream_name = "Rates"
        with patch.object(SimpleRetriever, "_fetch_next_page", side_effect=pages):
            states = [message.state for message in _run_read(manifest, _stream_name) if message.state]
>           assert len(states) == expected_states_qty
E           AssertionError: assert 1 == 2
E            +  where 1 = len([AirbyteStateMessage(type=<AirbyteStateType.STREAM: 'STREAM'>, stream=AirbyteStreamState(stream_descriptor=StreamDescriptor(name='Rates', namespace=None), stream_state=AirbyteStateBlob()), global_=None, data=None, sourceStats=None, destinationStats=None)])

unit_tests/legacy/sources/declarative/test_manifest_declarative_source.py:1969: AssertionError

Check warning on line 0 in unit_tests.legacy.sources.declarative.incremental.test_datetime_based_cursor

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_given_multiple_cursor_datetime_format_then_slice_using_first_format (unit_tests.legacy.sources.declarative.incremental.test_datetime_based_cursor) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert [{'start_time...'1970-01-01'}] == [{'end_time':...'2021-01-01'}]
  At index 0 diff: {'start_time': '1970-01-01', 'end_time': '1970-01-01'} != {'start_time': '2021-01-01', 'end_time': '2023-01-10'}
  Full diff:
  - [{'end_time': '2023-01-10', 'start_time': '2021-01-01'}]
  + [{'start_time': '1970-01-01', 'end_time': '1970-01-01'}]
def test_given_multiple_cursor_datetime_format_then_slice_using_first_format():
        cursor = DatetimeBasedCursor(
            start_datetime=MinMaxDatetime("2021-01-01", parameters={}),
            end_datetime=MinMaxDatetime("2023-01-10", parameters={}),
            cursor_field=InterpolatedString(cursor_field, parameters={}),
            datetime_format="%Y-%m-%d",
            cursor_datetime_formats=["%Y-%m-%dT%H:%M:%S", "%Y-%m-%d"],
            config=config,
            parameters={},
        )
        stream_slices = cursor.stream_slices()
>       assert stream_slices == [{"start_time": "2021-01-01", "end_time": "2023-01-10"}]
E       AssertionError: assert [{'start_time...'1970-01-01'}] == [{'end_time':...'2021-01-01'}]
E         At index 0 diff: {'start_time': '1970-01-01', 'end_time': '1970-01-01'} != {'start_time': '2021-01-01', 'end_time': '2023-01-10'}
E         Full diff:
E         - [{'end_time': '2023-01-10', 'start_time': '2021-01-01'}]
E         + [{'start_time': '1970-01-01', 'end_time': '1970-01-01'}]

unit_tests/legacy/sources/declarative/incremental/test_datetime_based_cursor.py:1109: AssertionError

Check warning on line 0 in unit_tests.legacy.sources.declarative.incremental.test_datetime_based_cursor

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_no_cursor_granularity_and_no_step_then_only_return_one_slice (unit_tests.legacy.sources.declarative.incremental.test_datetime_based_cursor) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert [{'start_time...'1970-01-01'}] == [{'end_time':...'2021-01-01'}]
  At index 0 diff: {'start_time': '1970-01-01', 'end_time': '1970-01-01'} != {'start_time': '2021-01-01', 'end_time': '2023-01-01'}
  Full diff:
  - [{'end_time': '2023-01-01', 'start_time': '2021-01-01'}]
  + [{'start_time': '1970-01-01', 'end_time': '1970-01-01'}]
def test_no_cursor_granularity_and_no_step_then_only_return_one_slice():
        cursor = DatetimeBasedCursor(
            start_datetime=MinMaxDatetime("2021-01-01", parameters={}),
            end_datetime=MinMaxDatetime("2023-01-01", parameters={}),
            cursor_field=InterpolatedString(cursor_field, parameters={}),
            datetime_format="%Y-%m-%d",
            config=config,
            parameters={},
        )
        stream_slices = cursor.stream_slices()
>       assert stream_slices == [{"start_time": "2021-01-01", "end_time": "2023-01-01"}]
E       AssertionError: assert [{'start_time...'1970-01-01'}] == [{'end_time':...'2021-01-01'}]
E         At index 0 diff: {'start_time': '1970-01-01', 'end_time': '1970-01-01'} != {'start_time': '2021-01-01', 'end_time': '2023-01-01'}
E         Full diff:
E         - [{'end_time': '2023-01-01', 'start_time': '2021-01-01'}]
E         + [{'start_time': '1970-01-01', 'end_time': '1970-01-01'}]

unit_tests/legacy/sources/declarative/incremental/test_datetime_based_cursor.py:1122: AssertionError

Check warning on line 0 in unit_tests.legacy.sources.declarative.incremental.test_datetime_based_cursor

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_given_no_state_and_start_before_cursor_value_when_should_be_synced_then_return_true (unit_tests.legacy.sources.declarative.incremental.test_datetime_based_cursor) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert False
 +  where False = <bound method DatetimeBasedCursor.should_be_synced of DatetimeBasedCursor(start_datetime=MinMaxDatetime(datetime=InterpolatedString(string='2021-01-01', default='2021-01-01'), datetime_format='%Y-%m-%d', min_datetime=None, max_datetime=None), cursor_field=InterpolatedString(string='created', default='created'), datetime_format='%Y-%m-%d', config={'start_date': '2021-01-01T00:00:00.000000+0000', 'start_date_ymd': '2021-01-01'}, end_datetime=None, step=None, cursor_granularity=None, start_time_option=None, end_time_option=None, partition_field_start=None, partition_field_end=None, lookback_window=None, message_repository=None, is_compare_strictly=False, cursor_datetime_formats=['%Y-%m-%d'])>({'created': '2022-01-01'})
 +    where <bound method DatetimeBasedCursor.should_be_synced of DatetimeBasedCursor(start_datetime=MinMaxDatetime(datetime=InterpolatedString(string='2021-01-01', default='2021-01-01'), datetime_format='%Y-%m-%d', min_datetime=None, max_datetime=None), cursor_field=InterpolatedString(string='created', default='created'), datetime_format='%Y-%m-%d', config={'start_date': '2021-01-01T00:00:00.000000+0000', 'start_date_ymd': '2021-01-01'}, end_datetime=None, step=None, cursor_granularity=None, start_time_option=None, end_time_option=None, partition_field_start=None, partition_field_end=None, lookback_window=None, message_repository=None, is_compare_strictly=False, cursor_datetime_formats=['%Y-%m-%d'])> = DatetimeBasedCursor(start_datetime=MinMaxDatetime(datetime=InterpolatedString(string='2021-01-01', default='2021-01-01'), datetime_format='%Y-%m-%d', min_datetime=None, max_datetime=None), cursor_field=InterpolatedString(string='created', default='created'), datetime_format='%Y-%m-%d', config={'start_date': '2021-01-01T00:00:00.000000+0000', 'start_date_ymd': '2021-01-01'}, end_datetime=None, step=None, cursor_granularity=None, start_time_option=None, end_time_option=None, partition_field_start=None, partition_field_end=None, lookback_window=None, message_repository=None, is_compare_strictly=False, cursor_datetime_formats=['%Y-%m-%d']).should_be_synced
 +    and   {'created': '2022-01-01'} = Record({'created': '2022-01-01'}, {})
def test_given_no_state_and_start_before_cursor_value_when_should_be_synced_then_return_true():
        cursor = DatetimeBasedCursor(
            start_datetime=MinMaxDatetime("2021-01-01", parameters={}),
            cursor_field=InterpolatedString(cursor_field, parameters={}),
            datetime_format="%Y-%m-%d",
            config=config,
            parameters={},
        )
>       assert cursor.should_be_synced(Record({cursor_field: "2022-01-01"}, ANY_SLICE))
E       AssertionError: assert False
E        +  where False = <bound method DatetimeBasedCursor.should_be_synced of DatetimeBasedCursor(start_datetime=MinMaxDatetime(datetime=InterpolatedString(string='2021-01-01', default='2021-01-01'), datetime_format='%Y-%m-%d', min_datetime=None, max_datetime=None), cursor_field=InterpolatedString(string='created', default='created'), datetime_format='%Y-%m-%d', config={'start_date': '2021-01-01T00:00:00.000000+0000', 'start_date_ymd': '2021-01-01'}, end_datetime=None, step=None, cursor_granularity=None, start_time_option=None, end_time_option=None, partition_field_start=None, partition_field_end=None, lookback_window=None, message_repository=None, is_compare_strictly=False, cursor_datetime_formats=['%Y-%m-%d'])>({'created': '2022-01-01'})
E        +    where <bound method DatetimeBasedCursor.should_be_synced of DatetimeBasedCursor(start_datetime=MinMaxDatetime(datetime=InterpolatedString(string='2021-01-01', default='2021-01-01'), datetime_format='%Y-%m-%d', min_datetime=None, max_datetime=None), cursor_field=InterpolatedString(string='created', default='created'), datetime_format='%Y-%m-%d', config={'start_date': '2021-01-01T00:00:00.000000+0000', 'start_date_ymd': '2021-01-01'}, end_datetime=None, step=None, cursor_granularity=None, start_time_option=None, end_time_option=None, partition_field_start=None, partition_field_end=None, lookback_window=None, message_repository=None, is_compare_strictly=False, cursor_datetime_formats=['%Y-%m-%d'])> = DatetimeBasedCursor(start_datetime=MinMaxDatetime(datetime=InterpolatedString(string='2021-01-01', default='2021-01-01'), datetime_format='%Y-%m-%d', min_datetime=None, max_datetime=None), cursor_field=InterpolatedString(string='created', default='created'), datetime_format='%Y-%m-%d', config={'start_date': '2021-01-01T00:00:00.000000+0000', 'start_date_ymd': '2021-01-01'}, end_datetime=None, step=None, cursor_granularity=None, start_time_option=None, end_time_option=None, partition_field_start=None, partition_field_end=None, lookback_window=None, message_repository=None, is_compare_strictly=False, cursor_datetime_formats=['%Y-%m-%d']).should_be_synced
E        +    and   {'created': '2022-01-01'} = Record({'created': '2022-01-01'}, {})

unit_tests/legacy/sources/declarative/incremental/test_datetime_based_cursor.py:1147: AssertionError

Check warning on line 0 in unit_tests.manifest_server.helpers.test_auth.TestVerifyJwtToken

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_valid_token_passes (unit_tests.manifest_server.helpers.test_auth.TestVerifyJwtToken) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
fastapi.exceptions.HTTPException: 401: Invalid token
credentials = HTTPAuthorizationCredentials(scheme='Bearer', credentials='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODI5NDQ5NjMsImlhdCI6MTc4Mjk0MTM2Mywic3ViIjoidGVzdC11c2VyIn0.CGQYMf0N8EvQp5OEtxV6xQ-a8Vs--vgWdwV8hFy97kI')

    def verify_jwt_token(
        credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
    ) -> None:
        """
        Verify JWT token if AB_JWT_SIGNATURE_SECRET is set, otherwise allow through.
    
        Args:
            credentials: Bearer token credentials from request header
    
        Raises:
            HTTPException: If token is invalid or missing when secret is configured
        """
        jwt_secret = os.getenv("AB_JWT_SIGNATURE_SECRET")
    
        # If no secret is configured, allow all requests through
        if not jwt_secret:
            return
    
        if not credentials:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Bearer token required",
                headers={"WWW-Authenticate": "Bearer"},
            )
    
        try:
>           jwt.decode(credentials.credentials, jwt_secret, algorithms=["HS256"])

airbyte_cdk/manifest_server/helpers/auth.py:37: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/jwt/api_jwt.py:368: in decode
    decoded = self.decode_complete(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/jwt/api_jwt.py:275: in decode_complete
    self._validate_claims(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/jwt/api_jwt.py:402: in _validate_claims
    self._validate_iat(payload, now, leeway)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <jwt.api_jwt.PyJWT object at 0x7fa65f967b00>
payload = {'exp': 1782944963, 'iat': 1782941363, 'sub': 'test-user'}
now = 0.001, leeway = 0

    def _validate_iat(
        self,
        payload: dict[str, Any],
        now: float,
        leeway: float,
    ) -> None:
        try:
            iat = int(payload["iat"])
        except ValueError:
            raise InvalidIssuedAtError(
                "Issued At claim (iat) must be an integer."
            ) from None
        if iat > (now + leeway):
>           raise ImmatureSignatureError("The token is not yet valid (iat)")
E           jwt.exceptions.ImmatureSignatureError: The token is not yet valid (iat)

../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/jwt/api_jwt.py:481: ImmatureSignatureError

During handling of the above exception, another exception occurred:

self = <unit_tests.manifest_server.helpers.test_auth.TestVerifyJwtToken object at 0x7fa6400931a0>

    def test_valid_token_passes(self):
        """Test that valid JWT tokens pass verification."""
        secret = "test-secret-key"
        payload = {
            "exp": datetime.now(timezone.utc) + timedelta(hours=1),
            "iat": datetime.now(timezone.utc),
            "sub": "test-user",
        }
        valid_token = jwt.encode(payload, secret, algorithm="HS256")
    
        with patch.dict(os.environ, {"AB_JWT_SIGNATURE_SECRET": secret}):
            valid_credentials = HTTPAuthorizationCredentials(
                scheme="Bearer", credentials=valid_token
            )
    
            # Should not raise any exception
>           verify_jwt_token(valid_credentials)

unit_tests/manifest_server/helpers/test_auth.py:76: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

credentials = HTTPAuthorizationCredentials(scheme='Bearer', credentials='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODI5NDQ5NjMsImlhdCI6MTc4Mjk0MTM2Mywic3ViIjoidGVzdC11c2VyIn0.CGQYMf0N8EvQp5OEtxV6xQ-a8Vs--vgWdwV8hFy97kI')

    def verify_jwt_token(
        credentials: Optional[HTTPAuthorizationCredentials] = Security(security),
    ) -> None:
        """
        Verify JWT token if AB_JWT_SIGNATURE_SECRET is set, otherwise allow through.
    
        Args:
            credentials: Bearer token credentials from request header
    
        Raises:
            HTTPException: If token is invalid or missing when secret is configured
        """
        jwt_secret = os.getenv("AB_JWT_SIGNATURE_SECRET")
    
        # If no secret is configured, allow all requests through
        if not jwt_secret:
            return
    
        if not credentials:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Bearer token required",
                headers={"WWW-Authenticate": "Bearer"},
            )
    
        try:
            jwt.decode(credentials.credentials, jwt_secret, algorithms=["HS256"])
        except jwt.InvalidTokenError:
>           raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid token",
                headers={"WWW-Authenticate": "Bearer"},
            )
E           fastapi.exceptions.HTTPException: 401: Invalid token

airbyte_cdk/manifest_server/helpers/auth.py:39: HTTPException

Check warning on line 0 in unit_tests.sources.declarative.test_concurrent_declarative_source

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_check (unit_tests.sources.declarative.test_concurrent_declarative_source) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
assert <Status.FAILED: 'FAILED'> == <Status.SUCCEEDED: 'SUCCEEDED'>
 +  where <Status.FAILED: 'FAILED'> = AirbyteConnectionStatus(status=<Status.FAILED: 'FAILED'>, message="'Stream party_members is not available: Cannot attempt to connect to stream party_members - no stream slices were found'").status
 +  and   <Status.SUCCEEDED: 'SUCCEEDED'> = Status.SUCCEEDED
def test_check():
        """
        Verifies that the ConcurrentDeclarativeSource check command is run against synchronous streams
        """
        with HttpMocker() as http_mocker:
            http_mocker.get(
                HttpRequest(
                    "https://persona.metaverse.com/party_members?start=2024-07-01&end=2024-07-15"
                ),
                HttpResponse(
                    json.dumps(
                        {
                            "id": "amamiya",
                            "first_name": "ren",
                            "last_name": "amamiya",
                            "updated_at": "2024-07-10",
                        }
                    )
                ),
            )
            http_mocker.get(
                HttpRequest("https://persona.metaverse.com/palaces"),
                HttpResponse(json.dumps({"id": "palace_1"})),
            )
            http_mocker.get(
                HttpRequest(
                    "https://persona.metaverse.com/locations?m=active&i=1&g=country&start=2024-07-01&end=2024-07-31"
                ),
                HttpResponse(json.dumps({"id": "location_1"})),
            )
            source = ConcurrentDeclarativeSource(
                source_config=_MANIFEST, config=_CONFIG, catalog=None, state=None
            )
    
            connection_status = source.check(logger=source.logger, config=_CONFIG)
    
>       assert connection_status.status == Status.SUCCEEDED
E       assert <Status.FAILED: 'FAILED'> == <Status.SUCCEEDED: 'SUCCEEDED'>
E        +  where <Status.FAILED: 'FAILED'> = AirbyteConnectionStatus(status=<Status.FAILED: 'FAILED'>, message="'Stream party_members is not available: Cannot attempt to connect to stream party_members - no stream slices were found'").status
E        +  and   <Status.SUCCEEDED: 'SUCCEEDED'> = Status.SUCCEEDED

unit_tests/sources/declarative/test_concurrent_declarative_source.py:819: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.test_concurrent_declarative_source

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_read_with_concurrent_and_synchronous_streams_with_concurrent_state (unit_tests.sources.declarative.test_concurrent_declarative_source) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: party_members_skills: NameError("name 'RequestsCookieJar' is not defined")
party_members: NameError("name 'RequestsCookieJar' is not defined")
party_members: NameError("name 'RequestsCookieJar' is not defined")
party_members: NameError("name 'RequestsCookieJar' is not defined")
palaces: NameError("name 'RequestsCookieJar' is not defined")
@freezegun.freeze_time(_NOW)
    @patch(
        "airbyte_cdk.sources.streams.concurrent.state_converters.abstract_stream_state_converter.AbstractStreamStateConverter.__init__",
        mocked_init,
    )
    def test_read_with_concurrent_and_synchronous_streams_with_concurrent_state():
        """
        Verifies that a ConcurrentDeclarativeSource processes concurrent streams correctly using the incoming
        concurrent state format
        """
        state = [
            AirbyteStateMessage(
                type=AirbyteStateType.STREAM,
                stream=AirbyteStreamState(
                    stream_descriptor=StreamDescriptor(name="locations", namespace=None),
                    stream_state=AirbyteStateBlob(
                        state_type="date-range",
                        slices=[{"start": "2024-07-01", "end": "2024-07-31"}],
                    ),
                ),
            ),
            AirbyteStateMessage(
                type=AirbyteStateType.STREAM,
                stream=AirbyteStreamState(
                    stream_descriptor=StreamDescriptor(name="party_members", namespace=None),
                    stream_state=AirbyteStateBlob(
                        state_type="date-range",
                        slices=[
                            {"start": "2024-07-16", "end": "2024-07-30"},
                            {"start": "2024-07-31", "end": "2024-08-14"},
                            {"start": "2024-08-30", "end": "2024-09-09"},
                        ],
                    ),
                ),
            ),
        ]
    
        party_members_slices_and_responses = _NO_STATE_PARTY_MEMBERS_SLICES_AND_RESPONSES + [
            (
                {"start": "2024-09-04", "end": "2024-09-10"},  # considering lookback window
                HttpResponse(
                    json.dumps(
                        [
                            {
                                "id": "yoshizawa",
                                "first_name": "sumire",
                                "last_name": "yoshizawa",
                                "updated_at": "2024-09-10",
                            }
                        ]
                    )
                ),
            )
        ]
        location_slices = [
            {"start": "2024-07-26", "end": "2024-08-25"},
            {"start": "2024-08-26", "end": "2024-09-10"},
        ]
    
        source = ConcurrentDeclarativeSource(
            source_config=_MANIFEST, config=_CONFIG, catalog=_CATALOG, state=state
        )
    
        with HttpMocker() as http_mocker:
            _mock_party_members_requests(http_mocker, party_members_slices_and_responses)
            _mock_locations_requests(http_mocker, location_slices)
            http_mocker.get(HttpRequest("https://persona.metaverse.com/palaces"), _PALACES_RESPONSE)
            _mock_party_members_skills_requests(http_mocker)
    
>           messages = list(
                source.read(logger=source.logger, config=_CONFIG, catalog=_CATALOG, state=state)
            )

unit_tests/sources/declarative/test_concurrent_declarative_source.py:1080: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:388: in read
    yield from self._concurrent_source.read(selected_concurrent_streams)
airbyte_cdk/sources/concurrent_source/concurrent_source.py:131: in read
    yield from self._consume_from_queue(
airbyte_cdk/sources/concurrent_source/concurrent_source.py:159: in _consume_from_queue
    if queue.empty() and concurrent_stream_processor.is_done():
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <airbyte_cdk.sources.concurrent_source.concurrent_read_processor.ConcurrentReadProcessor object at 0x7fa6330ccaa0>

    def is_done(self) -> bool:
        """
        This method is called to check if the sync is done.
        The sync is done when:
        1. There are no more streams generating partitions
        2. There are no more streams to read from
        3. All partitions for all streams are closed
        """
        is_done = all(
            [
                self._is_stream_done(stream_name)
                for stream_name in self._stream_name_to_instance.keys()
            ]
        )
        if is_done and self._stream_instances_to_start_partition_generation:
            stuck_stream_names = [
                s.name for s in self._stream_instances_to_start_partition_generation
            ]
            raise AirbyteTracedException(
                message="Partition generation queue is not empty after all streams completed.",
                internal_message=f"Streams {stuck_stream_names} remained in the partition generation queue after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._active_groups:
            raise AirbyteTracedException(
                message="Active stream groups are not empty after all streams completed.",
                internal_message=f"Groups {dict(self._active_groups)} still active after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._exceptions_per_stream_name:
            error_message = generate_failed_streams_error_message(self._exceptions_per_stream_name)
            self._logger.info(error_message)
            # We still raise at least one exception when a stream raises an exception because the platform currently relies
            # on a non-zero exit code to determine if a sync attempt has failed. We also raise the exception as a config_error
            # type because this combined error isn't actionable, but rather the previously emitted individual errors.
>           raise AirbyteTracedException(
                message=error_message,
                internal_message="Concurrent read failure",
                failure_type=FailureType.config_error,
            )
E           airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: party_members_skills: NameError("name 'RequestsCookieJar' is not defined")
E           party_members: NameError("name 'RequestsCookieJar' is not defined")
E           party_members: NameError("name 'RequestsCookieJar' is not defined")
E           party_members: NameError("name 'RequestsCookieJar' is not defined")
E           palaces: NameError("name 'RequestsCookieJar' is not defined")

airbyte_cdk/sources/concurrent_source/concurrent_read_processor.py:416: AirbyteTracedException

Check warning on line 0 in unit_tests.sources.declarative.test_concurrent_declarative_source

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_read_with_concurrent_and_synchronous_streams_with_sequential_state (unit_tests.sources.declarative.test_concurrent_declarative_source) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: party_members: NameError("name 'RequestsCookieJar' is not defined")
party_members: NameError("name 'RequestsCookieJar' is not defined")
palaces: NameError("name 'RequestsCookieJar' is not defined")
party_members_skills: NameError("name 'RequestsCookieJar' is not defined")
@freezegun.freeze_time(_NOW)
    @patch(
        "airbyte_cdk.sources.streams.concurrent.state_converters.abstract_stream_state_converter.AbstractStreamStateConverter.__init__",
        mocked_init,
    )
    def test_read_with_concurrent_and_synchronous_streams_with_sequential_state():
        """
        Verifies that a ConcurrentDeclarativeSource processes concurrent streams correctly using the incoming
        legacy state format
        """
        state = [
            AirbyteStateMessage(
                type=AirbyteStateType.STREAM,
                stream=AirbyteStreamState(
                    stream_descriptor=StreamDescriptor(name="locations", namespace=None),
                    stream_state=AirbyteStateBlob(updated_at="2024-08-06"),
                ),
            ),
            AirbyteStateMessage(
                type=AirbyteStateType.STREAM,
                stream=AirbyteStreamState(
                    stream_descriptor=StreamDescriptor(name="party_members", namespace=None),
                    stream_state=AirbyteStateBlob(updated_at="2024-08-21"),
                ),
            ),
        ]
    
        source = ConcurrentDeclarativeSource(
            source_config=_MANIFEST, config=_CONFIG, catalog=_CATALOG, state=state
        )
    
        party_members_slices_and_responses = _NO_STATE_PARTY_MEMBERS_SLICES_AND_RESPONSES + [
            (
                {"start": "2024-08-16", "end": "2024-08-30"},
                HttpResponse(
                    json.dumps(
                        [
                            {
                                "id": "nijima",
                                "first_name": "makoto",
                                "last_name": "nijima",
                                "updated_at": "2024-08-10",
                            }
                        ]
                    )
                ),
            ),  # considering lookback window
            (
                {"start": "2024-08-31", "end": "2024-09-10"},
                HttpResponse(
                    json.dumps(
                        [
                            {
                                "id": "yoshizawa",
                                "first_name": "sumire",
                                "last_name": "yoshizawa",
                                "updated_at": "2024-09-10",
                            }
                        ]
                    )
                ),
            ),
        ]
        location_slices = [
            {"start": "2024-08-01", "end": "2024-08-31"},
            {"start": "2024-09-01", "end": "2024-09-10"},
        ]
    
        with HttpMocker() as http_mocker:
            _mock_party_members_requests(http_mocker, party_members_slices_and_responses)
            _mock_locations_requests(http_mocker, location_slices)
            http_mocker.get(HttpRequest("https://persona.metaverse.com/palaces"), _PALACES_RESPONSE)
            _mock_party_members_skills_requests(http_mocker)
    
>           messages = list(
                source.read(logger=source.logger, config=_CONFIG, catalog=_CATALOG, state=state)
            )

unit_tests/sources/declarative/test_concurrent_declarative_source.py:1209: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:388: in read
    yield from self._concurrent_source.read(selected_concurrent_streams)
airbyte_cdk/sources/concurrent_source/concurrent_source.py:131: in read
    yield from self._consume_from_queue(
airbyte_cdk/sources/concurrent_source/concurrent_source.py:159: in _consume_from_queue
    if queue.empty() and concurrent_stream_processor.is_done():
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <airbyte_cdk.sources.concurrent_source.concurrent_read_processor.ConcurrentReadProcessor object at 0x7fa63306d310>

    def is_done(self) -> bool:
        """
        This method is called to check if the sync is done.
        The sync is done when:
        1. There are no more streams generating partitions
        2. There are no more streams to read from
        3. All partitions for all streams are closed
        """
        is_done = all(
            [
                self._is_stream_done(stream_name)
                for stream_name in self._stream_name_to_instance.keys()
            ]
        )
        if is_done and self._stream_instances_to_start_partition_generation:
            stuck_stream_names = [
                s.name for s in self._stream_instances_to_start_partition_generation
            ]
            raise AirbyteTracedException(
                message="Partition generation queue is not empty after all streams completed.",
                internal_message=f"Streams {stuck_stream_names} remained in the partition generation queue after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._active_groups:
            raise AirbyteTracedException(
                message="Active stream groups are not empty after all streams completed.",
                internal_message=f"Groups {dict(self._active_groups)} still active after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._exceptions_per_stream_name:
            error_message = generate_failed_streams_error_message(self._exceptions_per_stream_name)
            self._logger.info(error_message)
            # We still raise at least one exception when a stream raises an exception because the platform currently relies
            # on a non-zero exit code to determine if a sync attempt has failed. We also raise the exception as a config_error
            # type because this combined error isn't actionable, but rather the previously emitted individual errors.
>           raise AirbyteTracedException(
                message=error_message,
                internal_message="Concurrent read failure",
                failure_type=FailureType.config_error,
            )
E           airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: party_members: NameError("name 'RequestsCookieJar' is not defined")
E           party_members: NameError("name 'RequestsCookieJar' is not defined")
E           palaces: NameError("name 'RequestsCookieJar' is not defined")
E           party_members_skills: NameError("name 'RequestsCookieJar' is not defined")

airbyte_cdk/sources/concurrent_source/concurrent_read_processor.py:416: AirbyteTracedException

Check warning on line 0 in unit_tests.sources.declarative.test_concurrent_declarative_source

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_read_concurrent_skip_streams_not_in_catalog (unit_tests.sources.declarative.test_concurrent_declarative_source) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: palaces: NameError("name 'RequestsCookieJar' is not defined")
@freezegun.freeze_time(_NOW)
    @patch(
        "airbyte_cdk.sources.streams.concurrent.state_converters.abstract_stream_state_converter.AbstractStreamStateConverter.__init__",
        mocked_init,
    )
    def test_read_concurrent_skip_streams_not_in_catalog():
        """
        Verifies that the ConcurrentDeclarativeSource only syncs streams that are specified in the incoming ConfiguredCatalog
        """
        with HttpMocker() as http_mocker:
            catalog = ConfiguredAirbyteCatalog(
                streams=[
                    ConfiguredAirbyteStream(
                        stream=AirbyteStream(
                            name="palaces", json_schema={}, supported_sync_modes=[SyncMode.full_refresh]
                        ),
                        sync_mode=SyncMode.full_refresh,
                        destination_sync_mode=DestinationSyncMode.append,
                    ),
                    ConfiguredAirbyteStream(
                        stream=AirbyteStream(
                            name="locations",
                            json_schema={},
                            supported_sync_modes=[SyncMode.incremental],
                        ),
                        sync_mode=SyncMode.incremental,
                        destination_sync_mode=DestinationSyncMode.append,
                    ),
                ]
            )
    
            source = ConcurrentDeclarativeSource(
                source_config=_MANIFEST, config=_CONFIG, catalog=catalog, state=None
            )
            # locations requests
            location_slices = [
                {"start": "2024-07-01", "end": "2024-07-31"},
                {"start": "2024-08-01", "end": "2024-08-31"},
                {"start": "2024-09-01", "end": "2024-09-10"},
            ]
            locations_query_params = list(
                map(lambda _slice: _slice | {"m": "active", "i": "1", "g": "country"}, location_slices)
            )
            _mock_requests(
                http_mocker,
                "https://persona.metaverse.com/locations",
                locations_query_params,
                [_LOCATIONS_RESPONSE] * len(location_slices),
            )
    
            # palaces requests
            http_mocker.get(HttpRequest("https://persona.metaverse.com/palaces"), _PALACES_RESPONSE)
    
>           messages = list(
                source.read(logger=source.logger, config=_CONFIG, catalog=catalog, state=[])
            )

unit_tests/sources/declarative/test_concurrent_declarative_source.py:1528: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:388: in read
    yield from self._concurrent_source.read(selected_concurrent_streams)
airbyte_cdk/sources/concurrent_source/concurrent_source.py:131: in read
    yield from self._consume_from_queue(
airbyte_cdk/sources/concurrent_source/concurrent_source.py:159: in _consume_from_queue
    if queue.empty() and concurrent_stream_processor.is_done():
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <airbyte_cdk.sources.concurrent_source.concurrent_read_processor.ConcurrentReadProcessor object at 0x7fa633165cd0>

    def is_done(self) -> bool:
        """
        This method is called to check if the sync is done.
        The sync is done when:
        1. There are no more streams generating partitions
        2. There are no more streams to read from
        3. All partitions for all streams are closed
        """
        is_done = all(
            [
                self._is_stream_done(stream_name)
                for stream_name in self._stream_name_to_instance.keys()
            ]
        )
        if is_done and self._stream_instances_to_start_partition_generation:
            stuck_stream_names = [
                s.name for s in self._stream_instances_to_start_partition_generation
            ]
            raise AirbyteTracedException(
                message="Partition generation queue is not empty after all streams completed.",
                internal_message=f"Streams {stuck_stream_names} remained in the partition generation queue after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._active_groups:
            raise AirbyteTracedException(
                message="Active stream groups are not empty after all streams completed.",
                internal_message=f"Groups {dict(self._active_groups)} still active after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._exceptions_per_stream_name:
            error_message = generate_failed_streams_error_message(self._exceptions_per_stream_name)
            self._logger.info(error_message)
            # We still raise at least one exception when a stream raises an exception because the platform currently relies
            # on a non-zero exit code to determine if a sync attempt has failed. We also raise the exception as a config_error
            # type because this combined error isn't actionable, but rather the previously emitted individual errors.
>           raise AirbyteTracedException(
                message=error_message,
                internal_message="Concurrent read failure",
                failure_type=FailureType.config_error,
            )
E           airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: palaces: NameError("name 'RequestsCookieJar' is not defined")

airbyte_cdk/sources/concurrent_source/concurrent_read_processor.py:416: AirbyteTracedException

Check warning on line 0 in unit_tests.sources.declarative.test_concurrent_declarative_source

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_slice_checkpoint[test_with_pagination_and_partition_router-manifest0-pages0-2] (unit_tests.sources.declarative.test_concurrent_declarative_source) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert 1 == 2
 +  where 1 = len([AirbyteStateMessage(type=<AirbyteStateType.STREAM: 'STREAM'>, stream=AirbyteStreamState(stream_descriptor=StreamDescriptor(name='Rates', namespace=None), stream_state=AirbyteStateBlob()), global_=None, data=None, sourceStats=None, destinationStats=None)])
test_name = 'test_with_pagination_and_partition_router'
manifest = {'check': {'stream_names': ['Rates'], 'type': 'CheckStream'}, 'spec': {'connection_specification': {'$schema': 'http:/...T', 'path': '/exchangerates_data/latest', 'request_body_json': {}, ...}, ...}, ...}], 'type': 'DeclarativeSource', ...}
pages = (<Response [200]>, <Response [200]>, <Response [200]>)
expected_states_qty = 2

    @pytest.mark.parametrize(
        "test_name, manifest, pages, expected_states_qty",
        [
            (
                "test_with_pagination_and_partition_router",
                {
                    "version": "0.34.2",
                    "type": "DeclarativeSource",
                    "check": {"type": "CheckStream", "stream_names": ["Rates"]},
                    "streams": [
                        {
                            "type": "DeclarativeStream",
                            "name": "Rates",
                            "primary_key": [],
                            "schema_loader": {
                                "type": "InlineSchemaLoader",
                                "schema": {
                                    "$schema": "http://json-schema.org/schema#",
                                    "properties": {
                                        "ABC": {"type": "number"},
                                        "AED": {"type": "number"},
                                        "partition": {"type": "number"},
                                    },
                                    "type": "object",
                                },
                            },
                            "retriever": {
                                "type": "SimpleRetriever",
                                "requester": {
                                    "type": "HttpRequester",
                                    "url_base": "https://api.apilayer.com",
                                    "path": "/exchangerates_data/latest",
                                    "http_method": "GET",
                                    "request_parameters": {},
                                    "request_headers": {},
                                    "request_body_json": {},
                                    "authenticator": {
                                        "type": "ApiKeyAuthenticator",
                                        "header": "apikey",
                                        "api_token": "{{ config['api_key'] }}",
                                    },
                                },
                                "partition_router": {
                                    "type": "ListPartitionRouter",
                                    "values": ["0", "1"],
                                    "cursor_field": "partition",
                                },
                                "record_selector": {
                                    "type": "RecordSelector",
                                    "extractor": {"type": "DpathExtractor", "field_path": ["rates"]},
                                },
                                "paginator": {
                                    "type": "DefaultPaginator",
                                    "page_size": 2,
                                    "page_size_option": {
                                        "inject_into": "request_parameter",
                                        "field_name": "page_size",
                                    },
                                    "page_token_option": {"inject_into": "path", "type": "RequestPath"},
                                    "pagination_strategy": {
                                        "type": "CursorPagination",
                                        "cursor_value": "{{ response._metadata.next }}",
                                        "page_size": 2,
                                    },
                                },
                            },
                            "incremental_sync": {
                                "type": "DatetimeBasedCursor",
                                "cursor_datetime_formats": ["%Y-%m-%dT%H:%M:%S.%fZ"],
                                "datetime_format": "%Y-%m-%dT%H:%M:%S.%fZ",
                                "cursor_field": "updated_at",
                                "start_datetime": {
                                    "datetime": "{{ config.get('start_date', '2020-10-16T00:00:00.000Z') }}"
                                },
                            },
                        }
                    ],
                    "spec": {
                        "connection_specification": {
                            "$schema": "http://json-schema.org/draft-07/schema#",
                            "type": "object",
                            "required": ["api_key"],
                            "properties": {
                                "api_key": {
                                    "type": "string",
                                    "title": "API Key",
                                    "airbyte_secret": True,
                                },
                                "start_date": {
                                    "title": "Start Date",
                                    "description": "UTC date and time in the format YYYY-MM-DDTHH:MM:SS.000Z. During incremental sync, any data generated before this date will not be replicated. If left blank, the start date will be set to 2 years before the present date.",
                                    "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$",
                                    "pattern_descriptor": "YYYY-MM-DDTHH:MM:SS.000Z",
                                    "examples": ["2020-11-16T00:00:00.000Z"],
                                    "type": "string",
                                    "format": "date-time",
                                },
                            },
                            "additionalProperties": True,
                        },
                        "documentation_url": "https://example.org",
                        "type": "Spec",
                    },
                },
                (
                    _create_page(
                        {
                            "rates": [
                                {"ABC": 0, "partition": 0, "updated_at": "2020-11-16T00:00:00.000Z"},
                                {"AED": 1, "partition": 0, "updated_at": "2020-11-16T00:00:00.000Z"},
                            ],
                            "_metadata": {"next": "next"},
                        }
                    ),
                    _create_page(
                        {
                            "rates": [
                                {"USD": 3, "partition": 0, "updated_at": "2020-11-16T00:00:00.000Z"}
                            ],
                            "_metadata": {},
                        }
                    ),
                    _create_page(
                        {
                            "rates": [
                                {"ABC": 2, "partition": 1, "updated_at": "2020-11-16T00:00:00.000Z"}
                            ],
                            "_metadata": {},
                        }
                    ),
                ),
                2,
            ),
        ],
    )
    def test_slice_checkpoint(test_name, manifest, pages, expected_states_qty):
        _stream_name = "Rates"
        with patch.object(SimpleRetriever, "_fetch_next_page", side_effect=pages):
            states = [message.state for message in _run_read(manifest, _stream_name) if message.state]
>           assert len(states) == expected_states_qty
E           AssertionError: assert 1 == 2
E            +  where 1 = len([AirbyteStateMessage(type=<AirbyteStateType.STREAM: 'STREAM'>, stream=AirbyteStreamState(stream_descriptor=StreamDescriptor(name='Rates', namespace=None), stream_state=AirbyteStateBlob()), global_=None, data=None, sourceStats=None, destinationStats=None)])

unit_tests/sources/declarative/test_concurrent_declarative_source.py:4254: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.test_state_delegating_stream

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_parent_state_delegating_stream_retention_falls_back_to_full_refresh (unit_tests.sources.declarative.test_state_delegating_stream) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: ChildStream: NameError("name 'RequestsCookieJar' is not defined")
@freezegun.freeze_time("2024-07-15")
    def test_parent_state_delegating_stream_retention_falls_back_to_full_refresh():
        """When parent StateDelegatingStream has old cursor in child state, retention triggers full refresh for parent."""
        manifest = _create_parent_child_manifest_with_retention_period("P7D")
    
        with HttpMocker() as http_mocker:
            http_mocker.get(
                HttpRequest(url="https://api.test.com/parents"),
                HttpResponse(
                    body=json.dumps([{"id": 1, "name": "parent_1", "updated_at": "2024-07-14"}])
                ),
            )
            http_mocker.get(
                HttpRequest(url="https://api.test.com/children/1"),
                HttpResponse(
                    body=json.dumps([{"id": 10, "name": "child_1", "updated_at": "2024-07-14"}])
                ),
            )
    
            state = [
                AirbyteStateMessage(
                    type=AirbyteStateType.STREAM,
                    stream=AirbyteStreamState(
                        stream_descriptor=StreamDescriptor(name="ChildStream", namespace=None),
                        stream_state=AirbyteStateBlob(
                            use_global_cursor=False,
                            state={"updated_at": "2024-07-14"},
                            states=[],
                            parent_state={"ParentStream": {"updated_at": "2024-06-01"}},
                            lookback_window=0,
                        ),
                    ),
                )
            ]
            source = ConcurrentDeclarativeSource(
                source_config=manifest, config=_CONFIG, catalog=None, state=state
            )
            configured_catalog = create_configured_catalog(source, _CONFIG)
>           records = get_records(source, _CONFIG, configured_catalog, state)

unit_tests/sources/declarative/test_state_delegating_stream.py:853: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
unit_tests/sources/declarative/test_state_delegating_stream.py:185: in get_records
    return [
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:388: in read
    yield from self._concurrent_source.read(selected_concurrent_streams)
airbyte_cdk/sources/concurrent_source/concurrent_source.py:131: in read
    yield from self._consume_from_queue(
airbyte_cdk/sources/concurrent_source/concurrent_source.py:159: in _consume_from_queue
    if queue.empty() and concurrent_stream_processor.is_done():
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <airbyte_cdk.sources.concurrent_source.concurrent_read_processor.ConcurrentReadProcessor object at 0x7fa630cba3c0>

    def is_done(self) -> bool:
        """
        This method is called to check if the sync is done.
        The sync is done when:
        1. There are no more streams generating partitions
        2. There are no more streams to read from
        3. All partitions for all streams are closed
        """
        is_done = all(
            [
                self._is_stream_done(stream_name)
                for stream_name in self._stream_name_to_instance.keys()
            ]
        )
        if is_done and self._stream_instances_to_start_partition_generation:
            stuck_stream_names = [
                s.name for s in self._stream_instances_to_start_partition_generation
            ]
            raise AirbyteTracedException(
                message="Partition generation queue is not empty after all streams completed.",
                internal_message=f"Streams {stuck_stream_names} remained in the partition generation queue after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._active_groups:
            raise AirbyteTracedException(
                message="Active stream groups are not empty after all streams completed.",
                internal_message=f"Groups {dict(self._active_groups)} still active after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._exceptions_per_stream_name:
            error_message = generate_failed_streams_error_message(self._exceptions_per_stream_name)
            self._logger.info(error_message)
            # We still raise at least one exception when a stream raises an exception because the platform currently relies
            # on a non-zero exit code to determine if a sync attempt has failed. We also raise the exception as a config_error
            # type because this combined error isn't actionable, but rather the previously emitted individual errors.
>           raise AirbyteTracedException(
                message=error_message,
                internal_message="Concurrent read failure",
                failure_type=FailureType.config_error,
            )
E           airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: ChildStream: NameError("name 'RequestsCookieJar' is not defined")

airbyte_cdk/sources/concurrent_source/concurrent_read_processor.py:416: AirbyteTracedException

Check warning on line 0 in unit_tests.sources.declarative.test_state_delegating_stream

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_unconfigured_parent_stream_does_not_emit_state_on_retention_fallback (unit_tests.sources.declarative.test_state_delegating_stream) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: ChildStream: NameError("name 'RequestsCookieJar' is not defined")
@freezegun.freeze_time("2024-07-15")
    def test_unconfigured_parent_stream_does_not_emit_state_on_retention_fallback():
        """When a parent StateDelegatingStream has stale cursor state but is NOT in the
        configured catalog (only the child is selected), no state message should be emitted
        for the parent.  Previously this would emit a state message for the parent stream,
        causing the destination to crash with 'Stream not found'."""
        manifest = _create_parent_child_manifest_with_retention_period("P7D")
    
        with HttpMocker() as http_mocker:
            http_mocker.get(
                HttpRequest(url="https://api.test.com/parents"),
                HttpResponse(
                    body=json.dumps([{"id": 1, "name": "parent_1", "updated_at": "2024-07-14"}])
                ),
            )
            http_mocker.get(
                HttpRequest(url="https://api.test.com/children/1"),
                HttpResponse(
                    body=json.dumps([{"id": 10, "name": "child_1", "updated_at": "2024-07-14"}])
                ),
            )
    
            # ParentStream has stale state (older than 7 days) but ParentStream is NOT
            # in the configured catalog — only ChildStream is selected.
            state = [
                AirbyteStateMessage(
                    type=AirbyteStateType.STREAM,
                    stream=AirbyteStreamState(
                        stream_descriptor=StreamDescriptor(name="ParentStream", namespace=None),
                        stream_state=AirbyteStateBlob(updated_at="2024-06-01"),
                    ),
                ),
                AirbyteStateMessage(
                    type=AirbyteStateType.STREAM,
                    stream=AirbyteStreamState(
                        stream_descriptor=StreamDescriptor(name="ChildStream", namespace=None),
                        stream_state=AirbyteStateBlob(
                            use_global_cursor=False,
                            state={"updated_at": "2024-07-14"},
                            states=[],
                            parent_state={"ParentStream": {"updated_at": "2024-06-01"}},
                            lookback_window=0,
                        ),
                    ),
                ),
            ]
            source = ConcurrentDeclarativeSource(
                source_config=manifest, config=_CONFIG, catalog=None, state=state
            )
            configured_catalog = create_configured_catalog(source, _CONFIG)
    
>           all_messages = list(
                source.read(logger=MagicMock(), config=_CONFIG, catalog=configured_catalog, state=state)
            )

unit_tests/sources/declarative/test_state_delegating_stream.py:908: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:388: in read
    yield from self._concurrent_source.read(selected_concurrent_streams)
airbyte_cdk/sources/concurrent_source/concurrent_source.py:131: in read
    yield from self._consume_from_queue(
airbyte_cdk/sources/concurrent_source/concurrent_source.py:159: in _consume_from_queue
    if queue.empty() and concurrent_stream_processor.is_done():
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <airbyte_cdk.sources.concurrent_source.concurrent_read_processor.ConcurrentReadProcessor object at 0x7fa630ad2c30>

    def is_done(self) -> bool:
        """
        This method is called to check if the sync is done.
        The sync is done when:
        1. There are no more streams generating partitions
        2. There are no more streams to read from
        3. All partitions for all streams are closed
        """
        is_done = all(
            [
                self._is_stream_done(stream_name)
                for stream_name in self._stream_name_to_instance.keys()
            ]
        )
        if is_done and self._stream_instances_to_start_partition_generation:
            stuck_stream_names = [
                s.name for s in self._stream_instances_to_start_partition_generation
            ]
            raise AirbyteTracedException(
                message="Partition generation queue is not empty after all streams completed.",
                internal_message=f"Streams {stuck_stream_names} remained in the partition generation queue after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._active_groups:
            raise AirbyteTracedException(
                message="Active stream groups are not empty after all streams completed.",
                internal_message=f"Groups {dict(self._active_groups)} still active after all streams were marked done.",
                failure_type=FailureType.system_error,
            )
        if is_done and self._exceptions_per_stream_name:
            error_message = generate_failed_streams_error_message(self._exceptions_per_stream_name)
            self._logger.info(error_message)
            # We still raise at least one exception when a stream raises an exception because the platform currently relies
            # on a non-zero exit code to determine if a sync attempt has failed. We also raise the exception as a config_error
            # type because this combined error isn't actionable, but rather the previously emitted individual errors.
>           raise AirbyteTracedException(
                message=error_message,
                internal_message="Concurrent read failure",
                failure_type=FailureType.config_error,
            )
E           airbyte_cdk.utils.traced_exception.AirbyteTracedException: During the sync, the following streams did not sync successfully: ChildStream: NameError("name 'RequestsCookieJar' is not defined")

airbyte_cdk/sources/concurrent_source/concurrent_read_processor.py:416: AirbyteTracedException

Check warning on line 0 in unit_tests.sources.declarative.async_job.test_job

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_given_timer_is_out_when_status_then_return_timed_out (unit_tests.sources.declarative.async_job.test_job) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert <AsyncJobStatus.RUNNING: ('RUNNING', False)> == <AsyncJobStatus.TIMED_OUT: ('TIMED_OUT', True)>
 +  where <AsyncJobStatus.RUNNING: ('RUNNING', False)> = <bound method AsyncJob.status of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)>()
 +    where <bound method AsyncJob.status of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)> = AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING).status
 +  and   <AsyncJobStatus.TIMED_OUT: ('TIMED_OUT', True)> = AsyncJobStatus.TIMED_OUT
def test_given_timer_is_out_when_status_then_return_timed_out() -> None:
        job = AsyncJob(_AN_API_JOB_ID, _ANY_STREAM_SLICE, _IMMEDIATELY_TIMED_OUT)
        time.sleep(0.001)
>       assert job.status() == AsyncJobStatus.TIMED_OUT
E       AssertionError: assert <AsyncJobStatus.RUNNING: ('RUNNING', False)> == <AsyncJobStatus.TIMED_OUT: ('TIMED_OUT', True)>
E        +  where <AsyncJobStatus.RUNNING: ('RUNNING', False)> = <bound method AsyncJob.status of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)>()
E        +    where <bound method AsyncJob.status of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)> = AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING).status
E        +  and   <AsyncJobStatus.TIMED_OUT: ('TIMED_OUT', True)> = AsyncJobStatus.TIMED_OUT

unit_tests/sources/declarative/async_job/test_job.py:27: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.async_job.test_job

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_retry_after[retry_after_in_past] (unit_tests.sources.declarative.async_job.test_job) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
assert False == True
 +  where False = <bound method AsyncJob.ready_to_retry of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)>()
 +    where <bound method AsyncJob.ready_to_retry of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)> = AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING).ready_to_retry
retry_after_offset = datetime.timedelta(days=-1, seconds=86399)
expected_deferred = True, expected_ready = True

    @pytest.mark.parametrize(
        "retry_after_offset,expected_deferred,expected_ready",
        [
            pytest.param(None, False, True, id="no_retry_after_set"),
            pytest.param(timedelta(hours=1), True, False, id="retry_after_in_future"),
            pytest.param(-timedelta(seconds=1), True, True, id="retry_after_in_past"),
        ],
    )
    def test_retry_after(
        retry_after_offset: Optional[timedelta], expected_deferred: bool, expected_ready: bool
    ) -> None:
        job = AsyncJob(_AN_API_JOB_ID, _ANY_STREAM_SLICE, _A_VERY_BIG_TIMEOUT)
        if retry_after_offset is not None:
            job.set_retry_after(datetime.now(tz=timezone.utc) + retry_after_offset)
        assert job.retry_deferred() == expected_deferred
>       assert job.ready_to_retry() == expected_ready
E       assert False == True
E        +  where False = <bound method AsyncJob.ready_to_retry of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)>()
E        +    where <bound method AsyncJob.ready_to_retry of AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING)> = AsyncJob(api_job_id=an api job id, job_parameters={}, status=AsyncJobStatus.RUNNING).ready_to_retry

unit_tests/sources/declarative/async_job/test_job.py:45: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.async_job.test_job_orchestrator.AsyncJobOrchestratorTest

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_given_failed_retry_wait_time_when_job_fails_then_defers_retry (unit_tests.sources.declarative.async_job.test_job_orchestrator.AsyncJobOrchestratorTest) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: Expected 'start' to have been called once. Called 0 times.
self = <Mock name='mock.start' id='140351748529216'>

    def assert_called_once(self):
        """assert that the mock was called only once.
        """
        if not self.call_count == 1:
            msg = ("Expected '%s' to have been called once. Called %s times.%s"
                   % (self._mock_name or 'mock',
                      self.call_count,
                      self._calls_repr()))
>           raise AssertionError(msg)
E           AssertionError: Expected 'start' to have been called once. Called 0 times.

/usr/lib/python3.12/unittest/mock.py:923: AssertionError

During handling of the above exception, another exception occurred:

self = <unit_tests.sources.declarative.async_job.test_job_orchestrator.AsyncJobOrchestratorTest testMethod=test_given_failed_retry_wait_time_when_job_fails_then_defers_retry>
mock_sleep = <MagicMock name='sleep' id='140351748536368'>

    @mock.patch(sleep_mock_target)
    def test_given_failed_retry_wait_time_when_job_fails_then_defers_retry(
        self, mock_sleep: MagicMock
    ) -> None:
        """When failed_retry_wait_time_in_seconds is set and a job fails, the retry should
        be deferred: first call sets retry_after timestamp and skips, subsequent calls skip
        until cooldown elapses, then the job is replaced."""
        job_tracker = JobTracker(_NO_JOB_LIMIT)
        job = self._an_async_job("deferred-job", _A_STREAM_SLICE)
        job_tracker._jobs.add("deferred-job")
        partition = AsyncPartition([job], _A_STREAM_SLICE)
        orchestrator = AsyncJobOrchestrator(
            self._job_repository,
            [],
            job_tracker,
            self._message_repository,
            failed_retry_wait_time_in_seconds=1800,
        )
    
        job.update_status(AsyncJobStatus.FAILED)
    
        # First call: should set retry_after and NOT replace
        orchestrator._replace_failed_jobs(partition)
        assert job.retry_deferred()
        assert not job.ready_to_retry()
        self._job_repository.start.assert_not_called()
    
        # Second call while cooldown hasn't elapsed: should still skip
        orchestrator._replace_failed_jobs(partition)
        self._job_repository.start.assert_not_called()
    
        # Simulate cooldown elapsed by setting retry_after to the past
        job.set_retry_after(datetime.now(tz=timezone.utc) - timedelta(seconds=1))
        replacement_job = self._an_async_job("replacement-job", _A_STREAM_SLICE)
        self._job_repository.start.return_value = replacement_job
    
        # Third call after cooldown: should replace the job
        orchestrator._replace_failed_jobs(partition)
>       self._job_repository.start.assert_called_once()
E       AssertionError: Expected 'start' to have been called once. Called 0 times.

unit_tests/sources/declarative/async_job/test_job_orchestrator.py:458: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.async_job.test_job_orchestrator.AsyncJobOrchestratorTest

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_given_real_failed_then_cooldown_elapses_then_start_returns_creation_failure_then_no_rearm (unit_tests.sources.declarative.async_job.test_job_orchestrator.AsyncJobOrchestratorTest) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: Expected 'start' to have been called once. Called 0 times.
self = <Mock name='mock.start' id='140351750889376'>

    def assert_called_once(self):
        """assert that the mock was called only once.
        """
        if not self.call_count == 1:
            msg = ("Expected '%s' to have been called once. Called %s times.%s"
                   % (self._mock_name or 'mock',
                      self.call_count,
                      self._calls_repr()))
>           raise AssertionError(msg)
E           AssertionError: Expected 'start' to have been called once. Called 0 times.

/usr/lib/python3.12/unittest/mock.py:923: AssertionError

During handling of the above exception, another exception occurred:

self = <unit_tests.sources.declarative.async_job.test_job_orchestrator.AsyncJobOrchestratorTest testMethod=test_given_real_failed_then_cooldown_elapses_then_start_returns_creation_failure_then_no_rearm>
mock_sleep = <MagicMock name='sleep' id='140351748948288'>

    @mock.patch(sleep_mock_target)
    def test_given_real_failed_then_cooldown_elapses_then_start_returns_creation_failure_then_no_rearm(
        self, mock_sleep: MagicMock
    ) -> None:
        """Regression test for the original bug: real FAILED -> arm cooldown -> cooldown
        elapses -> _start_job returns a creation-failure job (API still rejects) -> the
        replacement must NOT re-arm cooldown; it should be replaced immediately on the
        next tick."""
        job_tracker = JobTracker(_NO_JOB_LIMIT)
        real_job = self._an_async_job("real-job", _A_STREAM_SLICE)
        job_tracker._jobs.add("real-job")
        partition = AsyncPartition([real_job], _A_STREAM_SLICE)
        orchestrator = AsyncJobOrchestrator(
            self._job_repository,
            [],
            job_tracker,
            self._message_repository,
            failed_retry_wait_time_in_seconds=1800,
        )
    
        real_job.update_status(AsyncJobStatus.FAILED)
    
        # Tick 1: arms cooldown on the real FAILED job
        orchestrator._replace_failed_jobs(partition)
        assert real_job.retry_deferred()
        self._job_repository.start.assert_not_called()
    
        # Simulate cooldown elapsed
        real_job.set_retry_after(datetime.now(tz=timezone.utc) - timedelta(seconds=1))
    
        # _start_job returns a creation-failure job (API still rejects with 429)
        creation_failure_replacement = AsyncJob(
            "creation-failure-replacement", _A_STREAM_SLICE, is_creation_failure=True
        )
        creation_failure_replacement.update_status(AsyncJobStatus.FAILED)
        self._job_repository.start.return_value = creation_failure_replacement
        job_tracker._jobs.add("creation-failure-replacement")
    
        # Tick 2: cooldown elapsed, replaces with creation-failure job
        orchestrator._replace_failed_jobs(partition)
>       self._job_repository.start.assert_called_once()
E       AssertionError: Expected 'start' to have been called once. Called 0 times.

unit_tests/sources/declarative/async_job/test_job_orchestrator.py:577: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.auth.test_jwt.TestJwtAuthenticator

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_get_jwt_payload[test_iss-test_sub-test_aud-additional_jwt_payload0-expected0] (unit_tests.sources.declarative.auth.test_jwt.TestJwtAuthenticator) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert {'aud': 'test...est_iss', ...} == {'aud': 'test...est_iss', ...}
  Omitting 4 identical items, use -vv to show
  Differing items:
  {'iat': 1640995200} != {'iat': 1782941539}
  {'exp': 1640996200} != {'exp': 1782942539}
  {'nbf': 1640995200} != {'nbf': 1782941539}
  Full diff:
    {
     'aud': 'test_aud',
  -  'exp': 1782942539,
  -  'iat': 1782941539,
  +  'exp': 1640996200,
  +  'iat': 1640995200,
     'iss': 'test_iss',
  -  'nbf': 1782941539,
  +  'nbf': 1640995200,
     'sub': 'test_sub',
     'test': 'test',
    }
self = <unit_tests.sources.declarative.auth.test_jwt.TestJwtAuthenticator object at 0x7fa64029ec30>
iss = 'test_iss', sub = 'test_sub', aud = 'test_aud'
additional_jwt_payload = {'test': 'test'}
expected = {'aud': 'test_aud', 'exp': 1782942539, 'iat': 1782941539, 'iss': 'test_iss', ...}

    @pytest.mark.parametrize(
        "iss, sub, aud, additional_jwt_payload, expected",
        [
            (
                "test_iss",
                "test_sub",
                "test_aud",
                {"test": "test"},
                {"iss": "test_iss", "sub": "test_sub", "aud": "test_aud", "test": "test"},
            ),
            (None, None, None, None, {}),
        ],
    )
    def test_get_jwt_payload(self, iss, sub, aud, additional_jwt_payload, expected):
        authenticator = JwtAuthenticator(
            config={},
            parameters={},
            algorithm="ALGORITHM",
            secret_key="test_key",
            token_duration=1000,
            iss=iss,
            sub=sub,
            aud=aud,
            additional_jwt_payload=additional_jwt_payload,
        )
        with freezegun.freeze_time("2022-01-01 00:00:00"):
            expected["iat"] = int(datetime.now().timestamp())
            expected["exp"] = expected["iat"] + 1000
            expected["nbf"] = expected["iat"]
>           assert authenticator._get_jwt_payload() == expected
E           AssertionError: assert {'aud': 'test...est_iss', ...} == {'aud': 'test...est_iss', ...}
E             Omitting 4 identical items, use -vv to show
E             Differing items:
E             {'iat': 1640995200} != {'iat': 1782941539}
E             {'exp': 1640996200} != {'exp': 1782942539}
E             {'nbf': 1640995200} != {'nbf': 1782941539}
E             Full diff:
E               {
E                'aud': 'test_aud',
E             -  'exp': 1782942539,
E             -  'iat': 1782941539,
E             +  'exp': 1640996200,
E             +  'iat': 1640995200,
E                'iss': 'test_iss',
E             -  'nbf': 1782941539,
E             +  'nbf': 1640995200,
E                'sub': 'test_sub',
E                'test': 'test',
E               }

unit_tests/sources/declarative/auth/test_jwt.py:104: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.auth.test_jwt.TestJwtAuthenticator

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_get_jwt_payload[None-None-None-None-expected1] (unit_tests.sources.declarative.auth.test_jwt.TestJwtAuthenticator) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
AssertionError: assert {'exp': 16409...': 1640995200} == {'exp': 17829...': 1782941539}
  Differing items:
  {'iat': 1640995200} != {'iat': 1782941539}
  {'exp': 1640996200} != {'exp': 1782942539}
  {'nbf': 1640995200} != {'nbf': 1782941539}
  Full diff:
  - {'exp': 1782942539, 'iat': 1782941539, 'nbf': 1782941539}
  + {'exp': 1640996200, 'iat': 1640995200, 'nbf': 1640995200}
self = <unit_tests.sources.declarative.auth.test_jwt.TestJwtAuthenticator object at 0x7fa64029d9a0>
iss = None, sub = None, aud = None, additional_jwt_payload = None
expected = {'exp': 1782942539, 'iat': 1782941539, 'nbf': 1782941539}

    @pytest.mark.parametrize(
        "iss, sub, aud, additional_jwt_payload, expected",
        [
            (
                "test_iss",
                "test_sub",
                "test_aud",
                {"test": "test"},
                {"iss": "test_iss", "sub": "test_sub", "aud": "test_aud", "test": "test"},
            ),
            (None, None, None, None, {}),
        ],
    )
    def test_get_jwt_payload(self, iss, sub, aud, additional_jwt_payload, expected):
        authenticator = JwtAuthenticator(
            config={},
            parameters={},
            algorithm="ALGORITHM",
            secret_key="test_key",
            token_duration=1000,
            iss=iss,
            sub=sub,
            aud=aud,
            additional_jwt_payload=additional_jwt_payload,
        )
        with freezegun.freeze_time("2022-01-01 00:00:00"):
            expected["iat"] = int(datetime.now().timestamp())
            expected["exp"] = expected["iat"] + 1000
            expected["nbf"] = expected["iat"]
>           assert authenticator._get_jwt_payload() == expected
E           AssertionError: assert {'exp': 16409...': 1640995200} == {'exp': 17829...': 1782941539}
E             Differing items:
E             {'iat': 1640995200} != {'iat': 1782941539}
E             {'exp': 1640996200} != {'exp': 1782942539}
E             {'nbf': 1640995200} != {'nbf': 1782941539}
E             Full diff:
E             - {'exp': 1782942539, 'iat': 1782941539, 'nbf': 1782941539}
E             + {'exp': 1640996200, 'iat': 1640995200, 'nbf': 1640995200}

unit_tests/sources/declarative/auth/test_jwt.py:104: AssertionError

Check warning on line 0 in unit_tests.sources.declarative.checks.test_check_dynamic_stream

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_check_dynamic_stream[test_stream_unavailable_unhandled_error] (unit_tests.sources.declarative.checks.test_check_dynamic_stream) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
NameError: name 'RequestsCookieJar' is not defined
response_code = 404, available_expectation = <Status.FAILED: 'FAILED'>
use_check_availability = True
expected_messages = ['Not found. The requested resource was not found on the server.']

    @pytest.mark.parametrize(
        "response_code, available_expectation, use_check_availability, expected_messages",
        [
            pytest.param(
                404,
                Status.FAILED,
                True,
                ["Not found. The requested resource was not found on the server."],
                id="test_stream_unavailable_unhandled_error",
            ),
            pytest.param(
                403,
                Status.FAILED,
                True,
                ["Forbidden. You don't have permission to access this resource."],
                id="test_stream_unavailable_handled_error",
            ),
            pytest.param(200, Status.SUCCEEDED, True, [], id="test_stream_available"),
            pytest.param(200, Status.SUCCEEDED, False, [], id="test_stream_available"),
            pytest.param(
                401,
                Status.FAILED,
                True,
                ["Unauthorized. Please ensure you are authenticated correctly."],
                id="test_stream_unauthorized_error",
            ),
        ],
    )
    def test_check_dynamic_stream(
        response_code, available_expectation, use_check_availability, expected_messages
    ):
        manifest = deepcopy(_MANIFEST)
    
        with HttpMocker() as http_mocker:
            items_request = HttpRequest(url="https://api.test.com/items")
            items_response = HttpResponse(
                body=json.dumps([{"id": 1, "name": "item_1"}, {"id": 2, "name": "item_2"}])
            )
            http_mocker.get(items_request, items_response)
    
            item_request = HttpRequest(url="https://api.test.com/items/1")
            item_response = HttpResponse(body=json.dumps(expected_messages), status_code=response_code)
            item_request_count = 1
            http_mocker.get(item_request, item_response)
    
            if not use_check_availability:
                manifest["check"]["use_check_availability"] = False
                item_request_count = 0  # stream only created and data request not called
    
            source = ConcurrentDeclarativeSource(
                source_config=manifest,
                config=_CONFIG,
                catalog=None,
                state=None,
            )
    
>           connection_status = source.check(logger, _CONFIG)

unit_tests/sources/declarative/checks/test_check_dynamic_stream.py:164: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:586: in check
    check_succeeded, error = connection_checker.check_connection(self, logger, self._config)
airbyte_cdk/sources/declarative/checks/check_dynamic_stream.py:41: in check_connection
    streams: List[Union[Stream, AbstractStream]] = source.streams(config=config)  # type: ignore  # this is a migration step and we expect the declarative CDK to migrate off of ConnectionChecker
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:413: in streams
    stream_configs = self._stream_configs(self._source_config) + self.dynamic_streams
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:593: in dynamic_streams
    return self._dynamic_stream_configs(
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:668: in _dynamic_stream_configs
    for dynamic_stream in components_resolver.resolve_components(
airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py:95: in resolve_components
    for components_values in self.retriever.read_records(
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:460: in read_records
    yield from self._read_pages(record_generator, _slice)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:398: in _read_pages
    response = self._fetch_next_page(stream_slice, next_page_token)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:315: in _fetch_next_page
    return self.requester.send_request(
airbyte_cdk/sources/declarative/requesters/http_requester.py:458: in send_request
    request, response = self._http_client.send_request(
airbyte_cdk/sources/streams/http/http_client.py:611: in send_request
    response: requests.Response = self._send_with_retry(
airbyte_cdk/sources/streams/http/http_client.py:292: in _send_with_retry
    response = backoff_handler(rate_limit_backoff_handler(user_backoff_handler))(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
airbyte_cdk/sources/streams/http/http_client.py:348: in _send
    response = self._session.send(request, **request_kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:230: in send
    response = self._send_and_cache(request, actions, cached_response, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:258: in _send_and_cache
    self.cache.save_response(response, actions.cache_key, actions.expires)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:100: in save_response
    self.responses[cache_key] = cached_response
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:327: in __setitem__
    self._write(key, value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:347: in _write
    value = self.serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:397: in serialize
    value = super().serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:343: in serialize
    return self.serializer.dumps(value) if self.serializer else value
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/pipeline.py:56: in dumps
    value = step(value)
/usr/lib/python3.12/functools.py:946: in _method
    return method.__get__(obj, cls)(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/cattrs.py:74: in _
    response_dict = self.converter.unstructure(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:324: in unstructure
    return self._unstructure_func.dispatch(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:133: in dispatch_without_caching
    res = self._function_dispatch.dispatch(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:76: in dispatch
    return handler(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:1266: in gen_unstructure_attrs_fromdict
    resolve_types(origin or cl)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/attr/_funcs.py:487: in resolve_types
    hints = typing.get_type_hints(cls, **kwargs)
/usr/lib/python3.12/typing.py:2244: in get_type_hints
    value = _eval_type(value, base_globals, base_locals)
/usr/lib/python3.12/typing.py:414: in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
/usr/lib/python3.12/typing.py:924: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   NameError: name 'RequestsCookieJar' is not defined

<string>:1: NameError

Check warning on line 0 in unit_tests.sources.declarative.checks.test_check_dynamic_stream

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_check_dynamic_stream[test_stream_unavailable_handled_error] (unit_tests.sources.declarative.checks.test_check_dynamic_stream) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
NameError: name 'RequestsCookieJar' is not defined
response_code = 403, available_expectation = <Status.FAILED: 'FAILED'>
use_check_availability = True
expected_messages = ["Forbidden. You don't have permission to access this resource."]

    @pytest.mark.parametrize(
        "response_code, available_expectation, use_check_availability, expected_messages",
        [
            pytest.param(
                404,
                Status.FAILED,
                True,
                ["Not found. The requested resource was not found on the server."],
                id="test_stream_unavailable_unhandled_error",
            ),
            pytest.param(
                403,
                Status.FAILED,
                True,
                ["Forbidden. You don't have permission to access this resource."],
                id="test_stream_unavailable_handled_error",
            ),
            pytest.param(200, Status.SUCCEEDED, True, [], id="test_stream_available"),
            pytest.param(200, Status.SUCCEEDED, False, [], id="test_stream_available"),
            pytest.param(
                401,
                Status.FAILED,
                True,
                ["Unauthorized. Please ensure you are authenticated correctly."],
                id="test_stream_unauthorized_error",
            ),
        ],
    )
    def test_check_dynamic_stream(
        response_code, available_expectation, use_check_availability, expected_messages
    ):
        manifest = deepcopy(_MANIFEST)
    
        with HttpMocker() as http_mocker:
            items_request = HttpRequest(url="https://api.test.com/items")
            items_response = HttpResponse(
                body=json.dumps([{"id": 1, "name": "item_1"}, {"id": 2, "name": "item_2"}])
            )
            http_mocker.get(items_request, items_response)
    
            item_request = HttpRequest(url="https://api.test.com/items/1")
            item_response = HttpResponse(body=json.dumps(expected_messages), status_code=response_code)
            item_request_count = 1
            http_mocker.get(item_request, item_response)
    
            if not use_check_availability:
                manifest["check"]["use_check_availability"] = False
                item_request_count = 0  # stream only created and data request not called
    
            source = ConcurrentDeclarativeSource(
                source_config=manifest,
                config=_CONFIG,
                catalog=None,
                state=None,
            )
    
>           connection_status = source.check(logger, _CONFIG)

unit_tests/sources/declarative/checks/test_check_dynamic_stream.py:164: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:586: in check
    check_succeeded, error = connection_checker.check_connection(self, logger, self._config)
airbyte_cdk/sources/declarative/checks/check_dynamic_stream.py:41: in check_connection
    streams: List[Union[Stream, AbstractStream]] = source.streams(config=config)  # type: ignore  # this is a migration step and we expect the declarative CDK to migrate off of ConnectionChecker
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:413: in streams
    stream_configs = self._stream_configs(self._source_config) + self.dynamic_streams
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:593: in dynamic_streams
    return self._dynamic_stream_configs(
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:668: in _dynamic_stream_configs
    for dynamic_stream in components_resolver.resolve_components(
airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py:95: in resolve_components
    for components_values in self.retriever.read_records(
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:460: in read_records
    yield from self._read_pages(record_generator, _slice)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:398: in _read_pages
    response = self._fetch_next_page(stream_slice, next_page_token)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:315: in _fetch_next_page
    return self.requester.send_request(
airbyte_cdk/sources/declarative/requesters/http_requester.py:458: in send_request
    request, response = self._http_client.send_request(
airbyte_cdk/sources/streams/http/http_client.py:611: in send_request
    response: requests.Response = self._send_with_retry(
airbyte_cdk/sources/streams/http/http_client.py:292: in _send_with_retry
    response = backoff_handler(rate_limit_backoff_handler(user_backoff_handler))(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
airbyte_cdk/sources/streams/http/http_client.py:348: in _send
    response = self._session.send(request, **request_kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:230: in send
    response = self._send_and_cache(request, actions, cached_response, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:258: in _send_and_cache
    self.cache.save_response(response, actions.cache_key, actions.expires)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:100: in save_response
    self.responses[cache_key] = cached_response
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:327: in __setitem__
    self._write(key, value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:347: in _write
    value = self.serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:397: in serialize
    value = super().serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:343: in serialize
    return self.serializer.dumps(value) if self.serializer else value
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/pipeline.py:56: in dumps
    value = step(value)
/usr/lib/python3.12/functools.py:946: in _method
    return method.__get__(obj, cls)(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/cattrs.py:74: in _
    response_dict = self.converter.unstructure(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:324: in unstructure
    return self._unstructure_func.dispatch(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:133: in dispatch_without_caching
    res = self._function_dispatch.dispatch(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:76: in dispatch
    return handler(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:1266: in gen_unstructure_attrs_fromdict
    resolve_types(origin or cl)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/attr/_funcs.py:487: in resolve_types
    hints = typing.get_type_hints(cls, **kwargs)
/usr/lib/python3.12/typing.py:2244: in get_type_hints
    value = _eval_type(value, base_globals, base_locals)
/usr/lib/python3.12/typing.py:414: in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
/usr/lib/python3.12/typing.py:924: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   NameError: name 'RequestsCookieJar' is not defined

<string>:1: NameError

Check warning on line 0 in unit_tests.sources.declarative.checks.test_check_dynamic_stream

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_check_dynamic_stream[test_stream_available0] (unit_tests.sources.declarative.checks.test_check_dynamic_stream) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
NameError: name 'RequestsCookieJar' is not defined
response_code = 200, available_expectation = <Status.SUCCEEDED: 'SUCCEEDED'>
use_check_availability = True, expected_messages = []

    @pytest.mark.parametrize(
        "response_code, available_expectation, use_check_availability, expected_messages",
        [
            pytest.param(
                404,
                Status.FAILED,
                True,
                ["Not found. The requested resource was not found on the server."],
                id="test_stream_unavailable_unhandled_error",
            ),
            pytest.param(
                403,
                Status.FAILED,
                True,
                ["Forbidden. You don't have permission to access this resource."],
                id="test_stream_unavailable_handled_error",
            ),
            pytest.param(200, Status.SUCCEEDED, True, [], id="test_stream_available"),
            pytest.param(200, Status.SUCCEEDED, False, [], id="test_stream_available"),
            pytest.param(
                401,
                Status.FAILED,
                True,
                ["Unauthorized. Please ensure you are authenticated correctly."],
                id="test_stream_unauthorized_error",
            ),
        ],
    )
    def test_check_dynamic_stream(
        response_code, available_expectation, use_check_availability, expected_messages
    ):
        manifest = deepcopy(_MANIFEST)
    
        with HttpMocker() as http_mocker:
            items_request = HttpRequest(url="https://api.test.com/items")
            items_response = HttpResponse(
                body=json.dumps([{"id": 1, "name": "item_1"}, {"id": 2, "name": "item_2"}])
            )
            http_mocker.get(items_request, items_response)
    
            item_request = HttpRequest(url="https://api.test.com/items/1")
            item_response = HttpResponse(body=json.dumps(expected_messages), status_code=response_code)
            item_request_count = 1
            http_mocker.get(item_request, item_response)
    
            if not use_check_availability:
                manifest["check"]["use_check_availability"] = False
                item_request_count = 0  # stream only created and data request not called
    
            source = ConcurrentDeclarativeSource(
                source_config=manifest,
                config=_CONFIG,
                catalog=None,
                state=None,
            )
    
>           connection_status = source.check(logger, _CONFIG)

unit_tests/sources/declarative/checks/test_check_dynamic_stream.py:164: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:586: in check
    check_succeeded, error = connection_checker.check_connection(self, logger, self._config)
airbyte_cdk/sources/declarative/checks/check_dynamic_stream.py:41: in check_connection
    streams: List[Union[Stream, AbstractStream]] = source.streams(config=config)  # type: ignore  # this is a migration step and we expect the declarative CDK to migrate off of ConnectionChecker
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:413: in streams
    stream_configs = self._stream_configs(self._source_config) + self.dynamic_streams
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:593: in dynamic_streams
    return self._dynamic_stream_configs(
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:668: in _dynamic_stream_configs
    for dynamic_stream in components_resolver.resolve_components(
airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py:95: in resolve_components
    for components_values in self.retriever.read_records(
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:460: in read_records
    yield from self._read_pages(record_generator, _slice)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:398: in _read_pages
    response = self._fetch_next_page(stream_slice, next_page_token)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:315: in _fetch_next_page
    return self.requester.send_request(
airbyte_cdk/sources/declarative/requesters/http_requester.py:458: in send_request
    request, response = self._http_client.send_request(
airbyte_cdk/sources/streams/http/http_client.py:611: in send_request
    response: requests.Response = self._send_with_retry(
airbyte_cdk/sources/streams/http/http_client.py:292: in _send_with_retry
    response = backoff_handler(rate_limit_backoff_handler(user_backoff_handler))(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
airbyte_cdk/sources/streams/http/http_client.py:348: in _send
    response = self._session.send(request, **request_kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:230: in send
    response = self._send_and_cache(request, actions, cached_response, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:258: in _send_and_cache
    self.cache.save_response(response, actions.cache_key, actions.expires)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:100: in save_response
    self.responses[cache_key] = cached_response
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:327: in __setitem__
    self._write(key, value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:347: in _write
    value = self.serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:397: in serialize
    value = super().serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:343: in serialize
    return self.serializer.dumps(value) if self.serializer else value
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/pipeline.py:56: in dumps
    value = step(value)
/usr/lib/python3.12/functools.py:946: in _method
    return method.__get__(obj, cls)(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/cattrs.py:74: in _
    response_dict = self.converter.unstructure(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:324: in unstructure
    return self._unstructure_func.dispatch(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:133: in dispatch_without_caching
    res = self._function_dispatch.dispatch(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:76: in dispatch
    return handler(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:1266: in gen_unstructure_attrs_fromdict
    resolve_types(origin or cl)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/attr/_funcs.py:487: in resolve_types
    hints = typing.get_type_hints(cls, **kwargs)
/usr/lib/python3.12/typing.py:2244: in get_type_hints
    value = _eval_type(value, base_globals, base_locals)
/usr/lib/python3.12/typing.py:414: in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
/usr/lib/python3.12/typing.py:924: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   NameError: name 'RequestsCookieJar' is not defined

<string>:1: NameError

Check warning on line 0 in unit_tests.sources.declarative.checks.test_check_dynamic_stream

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_check_dynamic_stream[test_stream_available1] (unit_tests.sources.declarative.checks.test_check_dynamic_stream) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
NameError: name 'RequestsCookieJar' is not defined
response_code = 200, available_expectation = <Status.SUCCEEDED: 'SUCCEEDED'>
use_check_availability = False, expected_messages = []

    @pytest.mark.parametrize(
        "response_code, available_expectation, use_check_availability, expected_messages",
        [
            pytest.param(
                404,
                Status.FAILED,
                True,
                ["Not found. The requested resource was not found on the server."],
                id="test_stream_unavailable_unhandled_error",
            ),
            pytest.param(
                403,
                Status.FAILED,
                True,
                ["Forbidden. You don't have permission to access this resource."],
                id="test_stream_unavailable_handled_error",
            ),
            pytest.param(200, Status.SUCCEEDED, True, [], id="test_stream_available"),
            pytest.param(200, Status.SUCCEEDED, False, [], id="test_stream_available"),
            pytest.param(
                401,
                Status.FAILED,
                True,
                ["Unauthorized. Please ensure you are authenticated correctly."],
                id="test_stream_unauthorized_error",
            ),
        ],
    )
    def test_check_dynamic_stream(
        response_code, available_expectation, use_check_availability, expected_messages
    ):
        manifest = deepcopy(_MANIFEST)
    
        with HttpMocker() as http_mocker:
            items_request = HttpRequest(url="https://api.test.com/items")
            items_response = HttpResponse(
                body=json.dumps([{"id": 1, "name": "item_1"}, {"id": 2, "name": "item_2"}])
            )
            http_mocker.get(items_request, items_response)
    
            item_request = HttpRequest(url="https://api.test.com/items/1")
            item_response = HttpResponse(body=json.dumps(expected_messages), status_code=response_code)
            item_request_count = 1
            http_mocker.get(item_request, item_response)
    
            if not use_check_availability:
                manifest["check"]["use_check_availability"] = False
                item_request_count = 0  # stream only created and data request not called
    
            source = ConcurrentDeclarativeSource(
                source_config=manifest,
                config=_CONFIG,
                catalog=None,
                state=None,
            )
    
>           connection_status = source.check(logger, _CONFIG)

unit_tests/sources/declarative/checks/test_check_dynamic_stream.py:164: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:586: in check
    check_succeeded, error = connection_checker.check_connection(self, logger, self._config)
airbyte_cdk/sources/declarative/checks/check_dynamic_stream.py:41: in check_connection
    streams: List[Union[Stream, AbstractStream]] = source.streams(config=config)  # type: ignore  # this is a migration step and we expect the declarative CDK to migrate off of ConnectionChecker
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:413: in streams
    stream_configs = self._stream_configs(self._source_config) + self.dynamic_streams
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:593: in dynamic_streams
    return self._dynamic_stream_configs(
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:668: in _dynamic_stream_configs
    for dynamic_stream in components_resolver.resolve_components(
airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py:95: in resolve_components
    for components_values in self.retriever.read_records(
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:460: in read_records
    yield from self._read_pages(record_generator, _slice)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:398: in _read_pages
    response = self._fetch_next_page(stream_slice, next_page_token)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:315: in _fetch_next_page
    return self.requester.send_request(
airbyte_cdk/sources/declarative/requesters/http_requester.py:458: in send_request
    request, response = self._http_client.send_request(
airbyte_cdk/sources/streams/http/http_client.py:611: in send_request
    response: requests.Response = self._send_with_retry(
airbyte_cdk/sources/streams/http/http_client.py:292: in _send_with_retry
    response = backoff_handler(rate_limit_backoff_handler(user_backoff_handler))(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
airbyte_cdk/sources/streams/http/http_client.py:348: in _send
    response = self._session.send(request, **request_kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:230: in send
    response = self._send_and_cache(request, actions, cached_response, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:258: in _send_and_cache
    self.cache.save_response(response, actions.cache_key, actions.expires)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:100: in save_response
    self.responses[cache_key] = cached_response
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:327: in __setitem__
    self._write(key, value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:347: in _write
    value = self.serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:397: in serialize
    value = super().serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:343: in serialize
    return self.serializer.dumps(value) if self.serializer else value
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/pipeline.py:56: in dumps
    value = step(value)
/usr/lib/python3.12/functools.py:946: in _method
    return method.__get__(obj, cls)(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/cattrs.py:74: in _
    response_dict = self.converter.unstructure(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:324: in unstructure
    return self._unstructure_func.dispatch(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:133: in dispatch_without_caching
    res = self._function_dispatch.dispatch(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:76: in dispatch
    return handler(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:1266: in gen_unstructure_attrs_fromdict
    resolve_types(origin or cl)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/attr/_funcs.py:487: in resolve_types
    hints = typing.get_type_hints(cls, **kwargs)
/usr/lib/python3.12/typing.py:2244: in get_type_hints
    value = _eval_type(value, base_globals, base_locals)
/usr/lib/python3.12/typing.py:414: in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
/usr/lib/python3.12/typing.py:924: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   NameError: name 'RequestsCookieJar' is not defined

<string>:1: NameError

Check warning on line 0 in unit_tests.sources.declarative.checks.test_check_dynamic_stream

See this annotation in the file changed.

@github-actions github-actions / PyTest Results (Full)

test_check_dynamic_stream[test_stream_unauthorized_error] (unit_tests.sources.declarative.checks.test_check_dynamic_stream) failed

build/test-results/pytest-results.xml [took 0s]
Raw output
NameError: name 'RequestsCookieJar' is not defined
response_code = 401, available_expectation = <Status.FAILED: 'FAILED'>
use_check_availability = True
expected_messages = ['Unauthorized. Please ensure you are authenticated correctly.']

    @pytest.mark.parametrize(
        "response_code, available_expectation, use_check_availability, expected_messages",
        [
            pytest.param(
                404,
                Status.FAILED,
                True,
                ["Not found. The requested resource was not found on the server."],
                id="test_stream_unavailable_unhandled_error",
            ),
            pytest.param(
                403,
                Status.FAILED,
                True,
                ["Forbidden. You don't have permission to access this resource."],
                id="test_stream_unavailable_handled_error",
            ),
            pytest.param(200, Status.SUCCEEDED, True, [], id="test_stream_available"),
            pytest.param(200, Status.SUCCEEDED, False, [], id="test_stream_available"),
            pytest.param(
                401,
                Status.FAILED,
                True,
                ["Unauthorized. Please ensure you are authenticated correctly."],
                id="test_stream_unauthorized_error",
            ),
        ],
    )
    def test_check_dynamic_stream(
        response_code, available_expectation, use_check_availability, expected_messages
    ):
        manifest = deepcopy(_MANIFEST)
    
        with HttpMocker() as http_mocker:
            items_request = HttpRequest(url="https://api.test.com/items")
            items_response = HttpResponse(
                body=json.dumps([{"id": 1, "name": "item_1"}, {"id": 2, "name": "item_2"}])
            )
            http_mocker.get(items_request, items_response)
    
            item_request = HttpRequest(url="https://api.test.com/items/1")
            item_response = HttpResponse(body=json.dumps(expected_messages), status_code=response_code)
            item_request_count = 1
            http_mocker.get(item_request, item_response)
    
            if not use_check_availability:
                manifest["check"]["use_check_availability"] = False
                item_request_count = 0  # stream only created and data request not called
    
            source = ConcurrentDeclarativeSource(
                source_config=manifest,
                config=_CONFIG,
                catalog=None,
                state=None,
            )
    
>           connection_status = source.check(logger, _CONFIG)

unit_tests/sources/declarative/checks/test_check_dynamic_stream.py:164: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:586: in check
    check_succeeded, error = connection_checker.check_connection(self, logger, self._config)
airbyte_cdk/sources/declarative/checks/check_dynamic_stream.py:41: in check_connection
    streams: List[Union[Stream, AbstractStream]] = source.streams(config=config)  # type: ignore  # this is a migration step and we expect the declarative CDK to migrate off of ConnectionChecker
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:413: in streams
    stream_configs = self._stream_configs(self._source_config) + self.dynamic_streams
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:593: in dynamic_streams
    return self._dynamic_stream_configs(
airbyte_cdk/sources/declarative/concurrent_declarative_source.py:668: in _dynamic_stream_configs
    for dynamic_stream in components_resolver.resolve_components(
airbyte_cdk/sources/declarative/resolvers/http_components_resolver.py:95: in resolve_components
    for components_values in self.retriever.read_records(
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:460: in read_records
    yield from self._read_pages(record_generator, _slice)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:398: in _read_pages
    response = self._fetch_next_page(stream_slice, next_page_token)
airbyte_cdk/sources/declarative/retrievers/simple_retriever.py:315: in _fetch_next_page
    return self.requester.send_request(
airbyte_cdk/sources/declarative/requesters/http_requester.py:458: in send_request
    request, response = self._http_client.send_request(
airbyte_cdk/sources/streams/http/http_client.py:611: in send_request
    response: requests.Response = self._send_with_retry(
airbyte_cdk/sources/streams/http/http_client.py:292: in _send_with_retry
    response = backoff_handler(rate_limit_backoff_handler(user_backoff_handler))(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/backoff/_sync.py:105: in retry
    ret = target(*args, **kwargs)
airbyte_cdk/sources/streams/http/http_client.py:348: in _send
    response = self._session.send(request, **request_kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:230: in send
    response = self._send_and_cache(request, actions, cached_response, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/session.py:258: in _send_and_cache
    self.cache.save_response(response, actions.cache_key, actions.expires)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:100: in save_response
    self.responses[cache_key] = cached_response
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:327: in __setitem__
    self._write(key, value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:347: in _write
    value = self.serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/sqlite.py:397: in serialize
    value = super().serialize(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/backends/base.py:343: in serialize
    return self.serializer.dumps(value) if self.serializer else value
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/pipeline.py:56: in dumps
    value = step(value)
/usr/lib/python3.12/functools.py:946: in _method
    return method.__get__(obj, cls)(*args, **kwargs)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/requests_cache/serializers/cattrs.py:74: in _
    response_dict = self.converter.unstructure(value)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:324: in unstructure
    return self._unstructure_func.dispatch(
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:133: in dispatch_without_caching
    res = self._function_dispatch.dispatch(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/dispatch.py:76: in dispatch
    return handler(typ)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/cattrs/converters.py:1266: in gen_unstructure_attrs_fromdict
    resolve_types(origin or cl)
../../../.cache/pypoetry/virtualenvs/airbyte-cdk-LAWzOSa7-py3.11/lib/python3.12/site-packages/attr/_funcs.py:487: in resolve_types
    hints = typing.get_type_hints(cls, **kwargs)
/usr/lib/python3.12/typing.py:2244: in get_type_hints
    value = _eval_type(value, base_globals, base_locals)
/usr/lib/python3.12/typing.py:414: in _eval_type
    return t._evaluate(globalns, localns, recursive_guard)
/usr/lib/python3.12/typing.py:924: in _evaluate
    eval(self.__forward_code__, globalns, localns),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

>   ???
E   NameError: name 'RequestsCookieJar' is not defined

<string>:1: NameError