Skip to content

Commit

Permalink
refactor: Deprecated singer_sdk.authenticators.BasicAuthenticator i…
Browse files Browse the repository at this point in the history
…n favor of `requests.auth.HTTPBasicAuth` (#2220)

* refactor: `Deprecate singer_sdk.authenticators.BasicAuthenticator` in favor of `requests.auth.HTTPBasicAuth`

Closes #2040

* Emit deprecation warning
  • Loading branch information
edgarrmondragon committed Mar 6, 2024
1 parent ee21bd5 commit b37e8f8
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from singer_sdk.streams import {{ cookiecutter.stream_type }}Stream

{% elif cookiecutter.auth_method == "Basic Auth" -%}
from singer_sdk.authenticators import BasicAuthenticator
from requests.auth import HTTPBasicAuth
from singer_sdk.helpers.jsonpath import extract_jsonpath
from singer_sdk.pagination import BaseAPIPaginator # noqa: TCH002
from singer_sdk.streams import {{ cookiecutter.stream_type }}Stream
Expand Down Expand Up @@ -110,14 +110,13 @@ def authenticator(self) -> BearerTokenAuthenticator:
{%- elif cookiecutter.auth_method == "Basic Auth" %}

@property
def authenticator(self) -> BasicAuthenticator:
def authenticator(self) -> HTTPBasicAuth:
"""Return a new authenticator object.
Returns:
An authenticator instance.
"""
return BasicAuthenticator.create_for_stream(
self,
return HTTPBasicAuth(
username=self.config.get("username", ""),
password=self.config.get("password", ""),
)
Expand Down
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ jsonl = "singer_sdk.contrib.batch_encoder_jsonl:JSONLinesBatcher"
parquet = "singer_sdk.contrib.batch_encoder_parquet:ParquetBatcher"

[tool.ruff]
extend-exclude = [
"cookiecutter/*",
"*simpleeval*",
]
line-length = 88
src = ["samples", "singer_sdk", "tests"]
target-version = "py38"
Expand All @@ -257,10 +261,6 @@ target-version = "py38"
docstring-code-format = true

[tool.ruff.lint]
exclude = [
"cookiecutter/*",
"*simpleeval*",
]
ignore = [
"ANN101", # Missing type annotation for `self` in method
"ANN102", # Missing type annotation for `cls` in class method
Expand Down
13 changes: 12 additions & 1 deletion singer_sdk/authenticators.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import base64
import math
import typing as t
import warnings
from datetime import timedelta
from types import MappingProxyType
from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit
Expand Down Expand Up @@ -296,7 +297,10 @@ def create_for_stream(
class BasicAuthenticator(APIAuthenticatorBase):
"""Implements basic authentication for REST Streams.
This Authenticator implements basic authentication by concatinating a
.. deprecated:: 0.36.0
Use :class:`requests.auth.HTTPBasicAuth` instead.
This Authenticator implements basic authentication by concatenating a
username and password then base64 encoding the string. The resulting
token will be merged with any HTTP headers specified on the stream.
"""
Expand All @@ -315,6 +319,13 @@ def __init__(
password: API password.
"""
super().__init__(stream=stream)
warnings.warn(
"BasicAuthenticator is deprecated. Use "
"requests.auth.HTTPBasicAuth instead.",
DeprecationWarning,
stacklevel=2,
)

credentials = f"{username}:{password}".encode()
auth_token = base64.b64encode(credentials).decode("ascii")
auth_credentials = {"Authorization": f"Basic {auth_token}"}
Expand Down
2 changes: 1 addition & 1 deletion singer_sdk/helpers/_flattening.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def get_flattening_options(
Returns:
A new FlatteningOptions object or None if flattening is disabled.
"""
if plugin_config.get("flattening_enabled"):
if plugin_config.get("flattening_enabled", False):
return FlatteningOptions(max_level=int(plugin_config["flattening_max_depth"]))

return None
Expand Down
16 changes: 15 additions & 1 deletion tests/core/rest/test_authenticators.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
)
from requests.auth import HTTPProxyAuth, _basic_auth_str

from singer_sdk.authenticators import OAuthAuthenticator, OAuthJWTAuthenticator
from singer_sdk.authenticators import (
BasicAuthenticator,
OAuthAuthenticator,
OAuthJWTAuthenticator,
)

if t.TYPE_CHECKING:
import requests_mock
Expand Down Expand Up @@ -218,3 +222,13 @@ def test_requests_library_auth(rest_tap: Tap):

assert isinstance(stream.authenticator, HTTPProxyAuth)
assert r.headers["Proxy-Authorization"] == _basic_auth_str("username", "password")


def test_basic_auth_deprecation_warning(rest_tap: Tap):
"""Validate that a warning is emitted when using BasicAuthenticator."""
stream: RESTStream = rest_tap.streams["some_stream"]
with pytest.deprecated_call(match="BasicAuthenticator is deprecated") as recorder:
BasicAuthenticator(stream=stream, username="username", password="password") # noqa: S106

assert len(recorder.list) == 1
assert recorder.list[0].filename.endswith("test_authenticators.py")

0 comments on commit b37e8f8

Please sign in to comment.