Skip to content

Commit

Permalink
Merge branch 'main' into lazebnyi/add-use-check-availability-flag-to-…
Browse files Browse the repository at this point in the history
…dynamic-check
  • Loading branch information
lazebnyi authored Jan 29, 2025
2 parents 7b148ce + 3af96dc commit 202b0d0
Show file tree
Hide file tree
Showing 49 changed files with 2,148 additions and 2,000,357 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/autofix-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pdoc_preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pdoc_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/poetry-lock-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ jobs:
with:
pr: ${{ github.event.inputs.pr }}

- name: Check for blank or missing poetry.lock
run: |
if [ ! -s "poetry.lock" ]; then
echo "poetry.lock missing or blank. Fetching from main branch..."
git fetch origin main
git checkout origin/main -- poetry.lock
echo "Lock file restored from main."
else
echo "poetry.lock found. Proceeding."
fi
- name: Get PR info
id: pr-info
run: |
Expand Down Expand Up @@ -72,7 +83,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pytest_fast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"

- name: Check Poetry lock file is current
run: poetry check
Expand All @@ -44,7 +44,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pytest_matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
python-version: [
"3.10",
"3.11",
#'3.12', # Currently blocked by Pendulum
"3.12",
]
os: [
Ubuntu,
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
uses: Gr1N/setup-poetry@v9
if: steps.changes.outputs.src == 'true'
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
if: steps.changes.outputs.src == 'true'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python_lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
34 changes: 33 additions & 1 deletion .github/workflows/slash_command_dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ jobs:
steps:
- name: Slash Command Dispatch
id: dispatch
uses: peter-evans/slash-command-dispatch@v4
# TODO: Revert to `peter-evans/slash-command-dispatch@v4` after PR merges:
# - https://github.com/peter-evans/slash-command-dispatch/pull/372/files
uses: aaronsteers/slash-command-dispatch@aj/fix/add-dispatched-bool-output
with:
repository: ${{ github.repository }}
token: ${{ secrets.GH_PAT_MAINTENANCE_OCTAVIA }}
Expand All @@ -36,3 +38,33 @@ jobs:
comment-id: ${{ github.event.comment.id }}
body: |
> Error: ${{ steps.dispatch.outputs.error-message }}
- name: Generate help text
id: help
if: >
startsWith(github.event.comment.body, '/') &&
!steps.dispatch.outputs.dispatched
run: |
HELP_TEXT="The following slash commands are available:
- \`/autofix\` - Corrects any linting or formatting issues
- \`/test\` - Runs the test suite
- \`/poetry-lock\` - Re-locks dependencies and updates the poetry.lock file
- \`/help\` - Shows this help message"
if [[ "${{ github.event.comment.body }}" == "/help" ]]; then
echo "body=$HELP_TEXT" >> $GITHUB_OUTPUT
else
echo "body=It looks like you are trying to enter a slash command. Either the slash command is unrecognized or you don't have access to call it.
$HELP_TEXT" >> $GITHUB_OUTPUT
fi
- name: Post help message
if: >
startsWith(github.event.comment.body, '/') &&
!steps.dispatch.outputs.dispatched
uses: peter-evans/create-or-update-comment@v4
with:
comment-id: ${{ github.event.comment.id }}
body: ${{ steps.help.outputs.body }}
2 changes: 1 addition & 1 deletion .github/workflows/test-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
- name: Set up Poetry
uses: Gr1N/setup-poetry@v9
with:
poetry-version: "1.8.4"
poetry-version: "2.0.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
Expand Down
63 changes: 63 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: |
(?x)(
# Python/system files
^.*/__init__\.py$|
^.*?/\.venv/.*$|
^.*?/node_modules/.*$|
# Generated/test files
^.*?/\.pytest_cache/.*$|
^.*?/__pycache__/.*$|
^.*?/\.mypy_cache/.*$|
^.*?/\.ruff_cache/.*$
# Package management
^.*?/poetry\.lock$|
^.*?/package-lock\.json$|
^.*?/pnpm-lock\.yaml$|
# Build and test artifacts
^.*?/build/.*$|
^.*?/dist/.*$|
^.*?/\.coverage$|
^.*?/coverage\.xml$|
)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: check-toml

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.3
hooks:
# Run the linter with repo-defined settings
- id: ruff
args: [--fix]

# Run the formatter with repo-defined settings
- id: ruff-format

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
hooks:
- id: prettier
types_or: [json, yaml]
additional_dependencies:
- [email protected]

- repo: local
hooks:
- id: addlicense
name: Add license headers
entry: addlicense -c "Airbyte, Inc." -l apache -v -f LICENSE_SHORT
language: golang
additional_dependencies: [github.com/google/[email protected]]
files: \.py$
1 change: 1 addition & 0 deletions LICENSE_SHORT
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Copyright (c) 2025 Airbyte, Inc., all rights reserved.
6 changes: 3 additions & 3 deletions airbyte_cdk/cli/source_declarative_manifest/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import sys
import traceback
from collections.abc import Mapping
from datetime import datetime
from pathlib import Path
from typing import Any, cast

Expand All @@ -44,6 +43,7 @@
)
from airbyte_cdk.sources.declarative.yaml_declarative_source import YamlDeclarativeSource
from airbyte_cdk.sources.source import TState
from airbyte_cdk.utils.datetime_helpers import ab_datetime_now


class SourceLocalYaml(YamlDeclarativeSource):
Expand Down Expand Up @@ -101,7 +101,7 @@ def _get_local_yaml_source(args: list[str]) -> SourceLocalYaml:
type=Type.TRACE,
trace=AirbyteTraceMessage(
type=TraceType.ERROR,
emitted_at=int(datetime.now().timestamp() * 1000),
emitted_at=ab_datetime_now().to_epoch_millis(),
error=AirbyteErrorTraceMessage(
message=f"Error starting the sync. This could be due to an invalid configuration or catalog. Please contact Support for assistance. Error: {error}",
stack_trace=traceback.format_exc(),
Expand Down Expand Up @@ -191,7 +191,7 @@ def create_declarative_source(
type=Type.TRACE,
trace=AirbyteTraceMessage(
type=TraceType.ERROR,
emitted_at=int(datetime.now().timestamp() * 1000),
emitted_at=ab_datetime_now().to_epoch_millis(),
error=AirbyteErrorTraceMessage(
message=f"Error starting the sync. This could be due to an invalid configuration or catalog. Please contact Support for assistance. Error: {error}",
stack_trace=traceback.format_exc(),
Expand Down
4 changes: 2 additions & 2 deletions airbyte_cdk/connector_builder/connector_builder_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#

import dataclasses
from datetime import datetime
from typing import Any, List, Mapping

from airbyte_cdk.connector_builder.message_grouper import MessageGrouper
Expand All @@ -21,6 +20,7 @@
ModelToComponentFactory,
)
from airbyte_cdk.utils.airbyte_secrets_utils import filter_secrets
from airbyte_cdk.utils.datetime_helpers import ab_datetime_now
from airbyte_cdk.utils.traced_exception import AirbyteTracedException

DEFAULT_MAXIMUM_NUMBER_OF_PAGES_PER_SLICE = 5
Expand Down Expand Up @@ -114,4 +114,4 @@ def resolve_manifest(source: ManifestDeclarativeSource) -> AirbyteMessage:


def _emitted_at() -> int:
return int(datetime.now().timestamp()) * 1000
return ab_datetime_now().to_epoch_millis()
35 changes: 22 additions & 13 deletions airbyte_cdk/sources/declarative/auth/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
#

from dataclasses import InitVar, dataclass, field
from datetime import timedelta
from typing import Any, List, Mapping, MutableMapping, Optional, Union

import pendulum

from airbyte_cdk.sources.declarative.auth.declarative_authenticator import DeclarativeAuthenticator
from airbyte_cdk.sources.declarative.interpolation.interpolated_boolean import InterpolatedBoolean
from airbyte_cdk.sources.declarative.interpolation.interpolated_mapping import InterpolatedMapping
Expand All @@ -18,6 +17,7 @@
from airbyte_cdk.sources.streams.http.requests_native_auth.oauth import (
SingleUseRefreshTokenOauth2Authenticator,
)
from airbyte_cdk.utils.datetime_helpers import AirbyteDateTime, ab_datetime_now, ab_datetime_parse


@dataclass
Expand Down Expand Up @@ -53,7 +53,7 @@ class DeclarativeOauth2Authenticator(AbstractOauth2Authenticator, DeclarativeAut
refresh_token: Optional[Union[InterpolatedString, str]] = None
scopes: Optional[List[str]] = None
token_expiry_date: Optional[Union[InterpolatedString, str]] = None
_token_expiry_date: Optional[pendulum.DateTime] = field(init=False, repr=False, default=None)
_token_expiry_date: Optional[AirbyteDateTime] = field(init=False, repr=False, default=None)
token_expiry_date_format: Optional[str] = None
token_expiry_is_time_of_expiration: bool = False
access_token_name: Union[InterpolatedString, str] = "access_token"
Expand Down Expand Up @@ -122,15 +122,24 @@ def __post_init__(self, parameters: Mapping[str, Any]) -> None:
self._refresh_request_headers = InterpolatedMapping(
self.refresh_request_headers or {}, parameters=parameters
)
self._token_expiry_date: pendulum.DateTime = (
pendulum.parse(
InterpolatedString.create(self.token_expiry_date, parameters=parameters).eval(
self.config
try:
if (
isinstance(self.token_expiry_date, (int, str))
and str(self.token_expiry_date).isdigit()
):
self._token_expiry_date = ab_datetime_parse(self.token_expiry_date)
else:
self._token_expiry_date = (
ab_datetime_parse(
InterpolatedString.create(
self.token_expiry_date, parameters=parameters
).eval(self.config)
)
if self.token_expiry_date
else ab_datetime_now() - timedelta(days=1)
)
) # type: ignore # pendulum.parse returns a datetime in this context
if self.token_expiry_date
else pendulum.now().subtract(days=1) # type: ignore # substract does not have type hints
)
except ValueError as e:
raise ValueError(f"Invalid token expiry date format: {e}")
self.use_profile_assertion = (
InterpolatedBoolean(self.use_profile_assertion, parameters=parameters)
if isinstance(self.use_profile_assertion, str)
Expand Down Expand Up @@ -222,8 +231,8 @@ def get_refresh_request_body(self) -> Mapping[str, Any]:
def get_refresh_request_headers(self) -> Mapping[str, Any]:
return self._refresh_request_headers.eval(self.config)

def get_token_expiry_date(self) -> pendulum.DateTime:
return self._token_expiry_date # type: ignore # _token_expiry_date is a pendulum.DateTime. It is never None despite what mypy thinks
def get_token_expiry_date(self) -> AirbyteDateTime:
return self._token_expiry_date # type: ignore # _token_expiry_date is an AirbyteDateTime. It is never None despite what mypy thinks

def set_token_expiry_date(self, value: Union[str, int]) -> None:
self._token_expiry_date = self._parse_token_expiration_date(value)
Expand Down
9 changes: 4 additions & 5 deletions airbyte_cdk/sources/declarative/auth/token_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
from typing import Any, List, Mapping, Optional, Union

import dpath
import pendulum
from isodate import Duration
from pendulum import DateTime

from airbyte_cdk.sources.declarative.decoders.decoder import Decoder
from airbyte_cdk.sources.declarative.decoders.json_decoder import JsonDecoder
Expand All @@ -21,6 +19,7 @@
from airbyte_cdk.sources.http_logger import format_http_message
from airbyte_cdk.sources.message import MessageRepository, NoopMessageRepository
from airbyte_cdk.sources.types import Config
from airbyte_cdk.utils.datetime_helpers import AirbyteDateTime, ab_datetime_now


class TokenProvider:
Expand All @@ -38,7 +37,7 @@ class SessionTokenProvider(TokenProvider):
message_repository: MessageRepository = NoopMessageRepository()
decoder: Decoder = field(default_factory=lambda: JsonDecoder(parameters={}))

_next_expiration_time: Optional[DateTime] = None
_next_expiration_time: Optional[AirbyteDateTime] = None
_token: Optional[str] = None

def get_token(self) -> str:
Expand All @@ -48,7 +47,7 @@ def get_token(self) -> str:
return self._token

def _refresh_if_necessary(self) -> None:
if self._next_expiration_time is None or self._next_expiration_time < pendulum.now():
if self._next_expiration_time is None or self._next_expiration_time < ab_datetime_now():
self._refresh()

def _refresh(self) -> None:
Expand All @@ -65,7 +64,7 @@ def _refresh(self) -> None:
raise ReadException("Failed to get session token, response got ignored by requester")
session_token = dpath.get(next(self.decoder.decode(response)), self.session_token_path)
if self.expiration_duration is not None:
self._next_expiration_time = pendulum.now() + self.expiration_duration
self._next_expiration_time = ab_datetime_now() + self.expiration_duration
self._token = session_token # type: ignore # Returned decoded response will be Mapping and therefore session_token will be str or None


Expand Down
Loading

0 comments on commit 202b0d0

Please sign in to comment.