Skip to content

Commit

Permalink
refactor: Limit internal usage of pendulum
Browse files Browse the repository at this point in the history
  • Loading branch information
edgarrmondragon committed Jan 19, 2024
1 parent 596323b commit 8d9e33e
Show file tree
Hide file tree
Showing 10 changed files with 36 additions and 228 deletions.
187 changes: 1 addition & 186 deletions poetry.lock

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ jsonschema = [
]
memoization = { version = ">=0.3.2,<0.5.0", python = "<4" }
packaging = ">=23.1"
pendulum = [
{ version = ">=2.1.0,<3", python = "<3.8" },
{ version = ">=2.1.0,<4", python = ">=3.8" },
]
PyJWT = "~=2.4"
python-dateutil = ">=2.8.2"
python-dotenv = ">=0.20"
Expand Down Expand Up @@ -344,6 +340,9 @@ typing = "t"
fixture-parentheses = false
parametrize-names-type = "csv"

[tool.ruff.lint.flake8-tidy-imports.banned-api]
"pendulum".msg = "BAN002: pendulum is banned"

[tool.ruff.lint.isort]
known-first-party = ["singer_sdk", "samples", "tests"]
required-imports = ["from __future__ import annotations"]
Expand Down
5 changes: 2 additions & 3 deletions singer_sdk/authenticators.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
from singer_sdk.helpers._util import utc_now

if t.TYPE_CHECKING:
import datetime
import logging

from pendulum import DateTime

from singer_sdk.streams.rest import RESTStream


Expand Down Expand Up @@ -380,7 +379,7 @@ def __init__(
# Initialize internal tracking attributes
self.access_token: str | None = None
self.refresh_token: str | None = None
self.last_refreshed: DateTime | None = None
self.last_refreshed: datetime.datetime | None = None
self.expires_in: int | None = None

@property
Expand Down
14 changes: 5 additions & 9 deletions singer_sdk/helpers/_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
from enum import Enum
from functools import lru_cache

import pendulum

_MAX_TIMESTAMP = "9999-12-31 23:59:59.999999"
_MAX_TIME = "23:59:59.999999"
JSONSCHEMA_ANNOTATION_SECRET = "secret" # noqa: S105
Expand Down Expand Up @@ -40,12 +38,10 @@ def __init__(self, *args: object) -> None:


def to_json_compatible(val: t.Any) -> t.Any: # noqa: ANN401
"""Return as string if datetime. JSON does not support proper datetime types.
If given a naive datetime object, pendulum automatically makes it utc
"""
if isinstance(val, (datetime.datetime, pendulum.DateTime)):
return pendulum.instance(val).isoformat("T")
"""Return as string if datetime. JSON does not support proper datetime types."""
if isinstance(val, (datetime.datetime,)):
# Make naive datetimes UTC
return (val.replace(tzinfo=UTC) if val.tzinfo is None else val).isoformat("T")
return val


Expand Down Expand Up @@ -474,7 +470,7 @@ def _conform_primitive_property( # noqa: PLR0911
property_schema: dict,
) -> t.Any: # noqa: ANN401
"""Converts a primitive (i.e. not object or array) to a json compatible type."""
if isinstance(elem, (datetime.datetime, pendulum.DateTime)):
if isinstance(elem, (datetime.datetime,)):
return to_json_compatible(elem)
if isinstance(elem, datetime.date):
return f"{elem.isoformat()}T00:00:00+00:00"
Expand Down
7 changes: 3 additions & 4 deletions singer_sdk/helpers/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

from __future__ import annotations

import datetime
import json
import typing as t
from pathlib import Path, PurePath

import pendulum


def read_json_file(path: PurePath | str) -> dict[str, t.Any]:
"""Read json file, throwing an error if missing."""
Expand All @@ -25,6 +24,6 @@ def read_json_file(path: PurePath | str) -> dict[str, t.Any]:
return t.cast(dict, json.loads(Path(path).read_text()))


def utc_now() -> pendulum.DateTime:
def utc_now() -> datetime.datetime:
"""Return current time in UTC."""
return pendulum.now(tz="UTC")
return datetime.datetime.now(datetime.timezone.utc)
4 changes: 2 additions & 2 deletions singer_sdk/sinks/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
from textwrap import dedent

import sqlalchemy as sa
from pendulum import now
from sqlalchemy.sql.expression import bindparam

from singer_sdk.connectors import SQLConnector
from singer_sdk.exceptions import ConformedNameClashException
from singer_sdk.helpers._conformers import replace_leading_digit
from singer_sdk.helpers._util import utc_now
from singer_sdk.sinks.batch import BatchSink

if t.TYPE_CHECKING:
Expand Down Expand Up @@ -366,7 +366,7 @@ def activate_version(self, new_version: int) -> None:
if not self.connector.table_exists(self.full_table_name):
return

deleted_at = now()
deleted_at = utc_now()

if not self.connector.column_exists(
full_table_name=self.full_table_name,
Expand Down
9 changes: 4 additions & 5 deletions singer_sdk/streams/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
from pathlib import Path
from types import MappingProxyType

import pendulum

import singer_sdk._singerlib as singer
from singer_sdk import metrics
from singer_sdk.batch import Batcher
Expand All @@ -29,7 +27,7 @@
SDKBatchMessage,
)
from singer_sdk.helpers._catalog import pop_deselected_record_properties
from singer_sdk.helpers._compat import final
from singer_sdk.helpers._compat import datetime_fromisoformat, final
from singer_sdk.helpers._flattening import get_flattening_options
from singer_sdk.helpers._state import (
finalize_state_progress_markers,
Expand Down Expand Up @@ -282,7 +280,8 @@ def get_starting_timestamp(self, context: dict | None) -> datetime.datetime | No
msg = f"The replication key {self.replication_key} is not of timestamp type"
raise ValueError(msg)

return t.cast(datetime.datetime, pendulum.parse(value))
result = datetime_fromisoformat(value)
return result if result.tzinfo else result.replace(tzinfo=datetime.timezone.utc)

@property
def selected(self) -> bool:
Expand Down Expand Up @@ -368,7 +367,7 @@ def compare_start_date(self, value: str, start_date_value: str) -> str:
The most recent value between the bookmark and start date.
"""
if self.is_timestamp_replication_key:
return max(value, start_date_value, key=pendulum.parse)
return max(value, start_date_value, key=datetime_fromisoformat)

return value

Expand Down
4 changes: 2 additions & 2 deletions tests/core/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
import typing as t
from contextlib import contextmanager

import pendulum
import pytest
from typing_extensions import override

from singer_sdk import Stream, Tap
from singer_sdk.helpers._compat import datetime_fromisoformat
from singer_sdk.typing import (
DateTimeType,
IntegerType,
Expand Down Expand Up @@ -70,7 +70,7 @@ class UnixTimestampIncrementalStream2(UnixTimestampIncrementalStream):
def compare_start_date(self, value: str, start_date_value: str) -> str:
"""Compare a value to a start date value."""

start_timestamp = pendulum.parse(start_date_value).format("X")
start_timestamp = datetime_fromisoformat(start_date_value).timestamp()
return max(value, start_timestamp, key=float)


Expand Down
12 changes: 6 additions & 6 deletions tests/core/test_record_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import typing as t
from datetime import datetime

import pendulum
import pytest

from singer_sdk.helpers._compat import datetime_fromisoformat as parse
from singer_sdk.helpers._typing import (
TypeConformanceLevel,
conform_record_data_types,
Expand All @@ -21,19 +21,19 @@
"record,schema,expected_row,ignore_props_message",
[
(
{"updatedAt": pendulum.parse("2021-08-25T20:05:28+00:00")},
{"updatedAt": parse("2021-08-25T20:05:28+00:00")},
{"properties": {"updatedAt": True}},
{"updatedAt": "2021-08-25T20:05:28+00:00"},
None,
),
(
{"updatedAt": pendulum.parse("2021-08-25T20:05:28Z")},
{"updatedAt": parse("2021-08-25T20:05:28Z")},
{"properties": {"updatedAt": True}},
{"updatedAt": "2021-08-25T20:05:28+00:00"},
None,
),
(
{"updatedAt": pendulum.parse("2021-08-25T20:05:28")},
{"updatedAt": parse("2021-08-25T20:05:28")},
{"properties": {"updatedAt": True}},
{"updatedAt": "2021-08-25T20:05:28+00:00"},
None,
Expand Down Expand Up @@ -84,8 +84,8 @@ def test_conform_record_data_types(
@pytest.mark.parametrize(
"datetime_val,expected",
[
(pendulum.parse("2021-08-25T20:05:28+00:00"), "2021-08-25T20:05:28+00:00"),
(pendulum.parse("2021-08-25T20:05:28+07:00"), "2021-08-25T20:05:28+07:00"),
(parse("2021-08-25T20:05:28+00:00"), "2021-08-25T20:05:28+00:00"),
(parse("2021-08-25T20:05:28+07:00"), "2021-08-25T20:05:28+07:00"),
(
datetime.strptime( # noqa: DTZ007
"2021-08-25T20:05:28",
Expand Down
15 changes: 8 additions & 7 deletions tests/core/test_streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

from __future__ import annotations

import datetime
import logging
import typing as t

import pendulum
import pytest
import requests

Expand All @@ -14,6 +14,7 @@
InvalidReplicationKeyException,
)
from singer_sdk.helpers._classproperty import classproperty
from singer_sdk.helpers._compat import datetime_fromisoformat as parse
from singer_sdk.helpers.jsonpath import _compile_jsonpath, extract_jsonpath
from singer_sdk.pagination import first
from singer_sdk.streams.core import REPLICATION_FULL_TABLE, REPLICATION_INCREMENTAL
Expand All @@ -22,12 +23,12 @@
from singer_sdk.typing import IntegerType, PropertiesList, Property, StringType
from tests.core.conftest import SimpleTestStream

CONFIG_START_DATE = "2021-01-01"

if t.TYPE_CHECKING:
from singer_sdk import Stream, Tap
from tests.core.conftest import SimpleTestTap

CONFIG_START_DATE = "2021-01-01"


class RestTestStream(RESTStream):
"""Test RESTful stream class."""
Expand Down Expand Up @@ -116,14 +117,14 @@ def test_stream_apply_catalog(stream: Stream):
"test",
None,
None,
pendulum.parse(CONFIG_START_DATE),
parse(CONFIG_START_DATE).replace(tzinfo=datetime.timezone.utc),
id="datetime-repl-key-no-state",
),
pytest.param(
"test",
None,
"2021-02-01",
pendulum.datetime(2021, 2, 1),
datetime.datetime(2021, 2, 1, tzinfo=datetime.timezone.utc),
id="datetime-repl-key-recent-bookmark",
),
pytest.param(
Expand All @@ -137,7 +138,7 @@ def test_stream_apply_catalog(stream: Stream):
"test",
None,
"2020-01-01",
pendulum.parse(CONFIG_START_DATE),
parse(CONFIG_START_DATE).replace(tzinfo=datetime.timezone.utc),
id="datetime-repl-key-old-bookmark",
),
pytest.param(
Expand Down Expand Up @@ -179,7 +180,7 @@ def test_stream_apply_catalog(stream: Stream):
"unix_ts_override",
None,
"1577858400",
pendulum.parse(CONFIG_START_DATE).format("X"),
parse(CONFIG_START_DATE).timestamp(),
id="unix-ts-repl-key-old-bookmark",
),
],
Expand Down

0 comments on commit 8d9e33e

Please sign in to comment.