From 861c21e9ddd6ccff0b4decfc550f94ebaf5efd0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Rami=CC=81rez=20Mondrago=CC=81n?= Date: Mon, 24 Oct 2022 21:29:40 -0500 Subject: [PATCH 1/2] feat: Support `requests.auth` authenticators --- docs/_templates/class.rst | 2 +- docs/classes/singer_sdk.BatchSink.rst | 2 +- docs/classes/singer_sdk.GraphQLStream.rst | 2 +- docs/classes/singer_sdk.InlineMapper.rst | 2 +- docs/classes/singer_sdk.RESTStream.rst | 2 +- docs/classes/singer_sdk.RecordSink.rst | 2 +- docs/classes/singer_sdk.SQLConnector.rst | 2 +- docs/classes/singer_sdk.SQLSink.rst | 2 +- docs/classes/singer_sdk.SQLStream.rst | 2 +- docs/classes/singer_sdk.SQLTap.rst | 2 +- docs/classes/singer_sdk.SQLTarget.rst | 2 +- docs/classes/singer_sdk.Sink.rst | 2 +- docs/classes/singer_sdk.Stream.rst | 2 +- docs/classes/singer_sdk.Tap.rst | 2 +- docs/classes/singer_sdk.Target.rst | 2 +- ...dk.authenticators.APIAuthenticatorBase.rst | 2 +- ...sdk.authenticators.APIKeyAuthenticator.rst | 2 +- ..._sdk.authenticators.BasicAuthenticator.rst | 2 +- ...uthenticators.BearerTokenAuthenticator.rst | 2 +- ..._sdk.authenticators.OAuthAuthenticator.rst | 2 +- ...k.authenticators.OAuthJWTAuthenticator.rst | 2 +- ...sdk.authenticators.SimpleAuthenticator.rst | 2 +- ...r_sdk.exceptions.ConfigValidationError.rst | 2 +- .../singer_sdk.exceptions.FatalAPIError.rst | 2 +- ....exceptions.InvalidStreamSortException.rst | 2 +- ...nger_sdk.exceptions.MapExpressionError.rst | 2 +- ...dk.exceptions.MaxRecordsLimitException.rst | 2 +- ...ceptions.RecordsWithoutSchemaException.rst | 2 +- ...inger_sdk.exceptions.RetriableAPIError.rst | 2 +- ...er_sdk.exceptions.StreamMapConfigError.rst | 2 +- ....exceptions.TapStreamConnectionFailure.rst | 2 +- ...sdk.exceptions.TooManyRecordsException.rst | 2 +- ...singer_sdk.pagination.BaseAPIPaginator.rst | 2 +- ...er_sdk.pagination.BaseHATEOASPaginator.rst | 2 +- ...ger_sdk.pagination.BaseOffsetPaginator.rst | 2 +- ...sdk.pagination.BasePageNumberPaginator.rst | 2 +- ...ger_sdk.pagination.HeaderLinkPaginator.rst | 2 +- ...inger_sdk.pagination.JSONPathPaginator.rst | 2 +- ...gination.LegacyPaginatedStreamProtocol.rst | 2 +- ...r_sdk.pagination.LegacyStreamPaginator.rst | 2 +- ...r_sdk.pagination.SimpleHeaderPaginator.rst | 2 +- ...ger_sdk.pagination.SinglePagePaginator.rst | 2 +- poetry.lock | 100 ++++++------------ singer_sdk/authenticators.py | 59 ++++++++++- singer_sdk/streams/rest.py | 17 +-- tests/core/rest/conftest.py | 11 ++ tests/core/rest/test_authenticators.py | 10 ++ 47 files changed, 162 insertions(+), 119 deletions(-) diff --git a/docs/_templates/class.rst b/docs/_templates/class.rst index f1b00ed50..4ebc9be04 100644 --- a/docs/_templates/class.rst +++ b/docs/_templates/class.rst @@ -5,4 +5,4 @@ .. autoclass:: {{ name }} :members: - :special-members: __init__ + :special-members: __init__, __call__ diff --git a/docs/classes/singer_sdk.BatchSink.rst b/docs/classes/singer_sdk.BatchSink.rst index 22933fcab..ea6f276fb 100644 --- a/docs/classes/singer_sdk.BatchSink.rst +++ b/docs/classes/singer_sdk.BatchSink.rst @@ -5,4 +5,4 @@ .. autoclass:: BatchSink :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.GraphQLStream.rst b/docs/classes/singer_sdk.GraphQLStream.rst index 8dc8d1062..41953196f 100644 --- a/docs/classes/singer_sdk.GraphQLStream.rst +++ b/docs/classes/singer_sdk.GraphQLStream.rst @@ -5,4 +5,4 @@ .. autoclass:: GraphQLStream :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.InlineMapper.rst b/docs/classes/singer_sdk.InlineMapper.rst index a6e8b5e7b..1ebc3744d 100644 --- a/docs/classes/singer_sdk.InlineMapper.rst +++ b/docs/classes/singer_sdk.InlineMapper.rst @@ -7,4 +7,4 @@ :members: :show-inheritance: :inherited-members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ diff --git a/docs/classes/singer_sdk.RESTStream.rst b/docs/classes/singer_sdk.RESTStream.rst index 3486f5cc9..9710c6303 100644 --- a/docs/classes/singer_sdk.RESTStream.rst +++ b/docs/classes/singer_sdk.RESTStream.rst @@ -5,4 +5,4 @@ .. autoclass:: RESTStream :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.RecordSink.rst b/docs/classes/singer_sdk.RecordSink.rst index b1767cf83..1f087079e 100644 --- a/docs/classes/singer_sdk.RecordSink.rst +++ b/docs/classes/singer_sdk.RecordSink.rst @@ -5,4 +5,4 @@ .. autoclass:: RecordSink :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.SQLConnector.rst b/docs/classes/singer_sdk.SQLConnector.rst index 76fe26721..d4d097f8f 100644 --- a/docs/classes/singer_sdk.SQLConnector.rst +++ b/docs/classes/singer_sdk.SQLConnector.rst @@ -5,4 +5,4 @@ .. autoclass:: SQLConnector :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.SQLSink.rst b/docs/classes/singer_sdk.SQLSink.rst index 53a2ac4a1..60b8b14a4 100644 --- a/docs/classes/singer_sdk.SQLSink.rst +++ b/docs/classes/singer_sdk.SQLSink.rst @@ -5,4 +5,4 @@ .. autoclass:: SQLSink :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.SQLStream.rst b/docs/classes/singer_sdk.SQLStream.rst index d178a0ed9..f72894088 100644 --- a/docs/classes/singer_sdk.SQLStream.rst +++ b/docs/classes/singer_sdk.SQLStream.rst @@ -5,4 +5,4 @@ .. autoclass:: SQLStream :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.SQLTap.rst b/docs/classes/singer_sdk.SQLTap.rst index 84433750f..c2d9d4cff 100644 --- a/docs/classes/singer_sdk.SQLTap.rst +++ b/docs/classes/singer_sdk.SQLTap.rst @@ -7,4 +7,4 @@ :members: :show-inheritance: :inherited-members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ diff --git a/docs/classes/singer_sdk.SQLTarget.rst b/docs/classes/singer_sdk.SQLTarget.rst index 5c16f3f3f..e685855d3 100644 --- a/docs/classes/singer_sdk.SQLTarget.rst +++ b/docs/classes/singer_sdk.SQLTarget.rst @@ -7,4 +7,4 @@ :members: :show-inheritance: :inherited-members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ diff --git a/docs/classes/singer_sdk.Sink.rst b/docs/classes/singer_sdk.Sink.rst index 0f1c6c78e..79062c29e 100644 --- a/docs/classes/singer_sdk.Sink.rst +++ b/docs/classes/singer_sdk.Sink.rst @@ -5,4 +5,4 @@ .. autoclass:: Sink :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.Stream.rst b/docs/classes/singer_sdk.Stream.rst index b56744ba9..db028a912 100644 --- a/docs/classes/singer_sdk.Stream.rst +++ b/docs/classes/singer_sdk.Stream.rst @@ -5,4 +5,4 @@ .. autoclass:: Stream :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.Tap.rst b/docs/classes/singer_sdk.Tap.rst index cd6702fb5..da3536585 100644 --- a/docs/classes/singer_sdk.Tap.rst +++ b/docs/classes/singer_sdk.Tap.rst @@ -7,4 +7,4 @@ :members: :show-inheritance: :inherited-members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ diff --git a/docs/classes/singer_sdk.Target.rst b/docs/classes/singer_sdk.Target.rst index 153479355..a1b1456de 100644 --- a/docs/classes/singer_sdk.Target.rst +++ b/docs/classes/singer_sdk.Target.rst @@ -7,4 +7,4 @@ :members: :show-inheritance: :inherited-members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ diff --git a/docs/classes/singer_sdk.authenticators.APIAuthenticatorBase.rst b/docs/classes/singer_sdk.authenticators.APIAuthenticatorBase.rst index e88561e46..1b3b608c5 100644 --- a/docs/classes/singer_sdk.authenticators.APIAuthenticatorBase.rst +++ b/docs/classes/singer_sdk.authenticators.APIAuthenticatorBase.rst @@ -5,4 +5,4 @@ .. autoclass:: APIAuthenticatorBase :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.authenticators.APIKeyAuthenticator.rst b/docs/classes/singer_sdk.authenticators.APIKeyAuthenticator.rst index ca48e5d44..28b0d7954 100644 --- a/docs/classes/singer_sdk.authenticators.APIKeyAuthenticator.rst +++ b/docs/classes/singer_sdk.authenticators.APIKeyAuthenticator.rst @@ -5,4 +5,4 @@ .. autoclass:: APIKeyAuthenticator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.authenticators.BasicAuthenticator.rst b/docs/classes/singer_sdk.authenticators.BasicAuthenticator.rst index 1c803715e..e944212a7 100644 --- a/docs/classes/singer_sdk.authenticators.BasicAuthenticator.rst +++ b/docs/classes/singer_sdk.authenticators.BasicAuthenticator.rst @@ -5,4 +5,4 @@ .. autoclass:: BasicAuthenticator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.authenticators.BearerTokenAuthenticator.rst b/docs/classes/singer_sdk.authenticators.BearerTokenAuthenticator.rst index 5475fa2b2..add92a271 100644 --- a/docs/classes/singer_sdk.authenticators.BearerTokenAuthenticator.rst +++ b/docs/classes/singer_sdk.authenticators.BearerTokenAuthenticator.rst @@ -5,4 +5,4 @@ .. autoclass:: BearerTokenAuthenticator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.authenticators.OAuthAuthenticator.rst b/docs/classes/singer_sdk.authenticators.OAuthAuthenticator.rst index 1f3b9bff6..7600d45dc 100644 --- a/docs/classes/singer_sdk.authenticators.OAuthAuthenticator.rst +++ b/docs/classes/singer_sdk.authenticators.OAuthAuthenticator.rst @@ -5,4 +5,4 @@ .. autoclass:: OAuthAuthenticator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.authenticators.OAuthJWTAuthenticator.rst b/docs/classes/singer_sdk.authenticators.OAuthJWTAuthenticator.rst index 883cf01ac..4fa2d3ea7 100644 --- a/docs/classes/singer_sdk.authenticators.OAuthJWTAuthenticator.rst +++ b/docs/classes/singer_sdk.authenticators.OAuthJWTAuthenticator.rst @@ -5,4 +5,4 @@ .. autoclass:: OAuthJWTAuthenticator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.authenticators.SimpleAuthenticator.rst b/docs/classes/singer_sdk.authenticators.SimpleAuthenticator.rst index 40b2859df..e83ef6fa1 100644 --- a/docs/classes/singer_sdk.authenticators.SimpleAuthenticator.rst +++ b/docs/classes/singer_sdk.authenticators.SimpleAuthenticator.rst @@ -5,4 +5,4 @@ .. autoclass:: SimpleAuthenticator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.ConfigValidationError.rst b/docs/classes/singer_sdk.exceptions.ConfigValidationError.rst index db945cdde..79f316f90 100644 --- a/docs/classes/singer_sdk.exceptions.ConfigValidationError.rst +++ b/docs/classes/singer_sdk.exceptions.ConfigValidationError.rst @@ -5,4 +5,4 @@ .. autoclass:: ConfigValidationError :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.FatalAPIError.rst b/docs/classes/singer_sdk.exceptions.FatalAPIError.rst index 764ff0bb5..954b42f95 100644 --- a/docs/classes/singer_sdk.exceptions.FatalAPIError.rst +++ b/docs/classes/singer_sdk.exceptions.FatalAPIError.rst @@ -5,4 +5,4 @@ .. autoclass:: FatalAPIError :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.InvalidStreamSortException.rst b/docs/classes/singer_sdk.exceptions.InvalidStreamSortException.rst index 86a87f256..e9bac24af 100644 --- a/docs/classes/singer_sdk.exceptions.InvalidStreamSortException.rst +++ b/docs/classes/singer_sdk.exceptions.InvalidStreamSortException.rst @@ -5,4 +5,4 @@ .. autoclass:: InvalidStreamSortException :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.MapExpressionError.rst b/docs/classes/singer_sdk.exceptions.MapExpressionError.rst index 0b82e5c47..21e543480 100644 --- a/docs/classes/singer_sdk.exceptions.MapExpressionError.rst +++ b/docs/classes/singer_sdk.exceptions.MapExpressionError.rst @@ -5,4 +5,4 @@ .. autoclass:: MapExpressionError :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.MaxRecordsLimitException.rst b/docs/classes/singer_sdk.exceptions.MaxRecordsLimitException.rst index c05322484..8492707f6 100644 --- a/docs/classes/singer_sdk.exceptions.MaxRecordsLimitException.rst +++ b/docs/classes/singer_sdk.exceptions.MaxRecordsLimitException.rst @@ -5,4 +5,4 @@ .. autoclass:: MaxRecordsLimitException :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.RecordsWithoutSchemaException.rst b/docs/classes/singer_sdk.exceptions.RecordsWithoutSchemaException.rst index 4948ee12c..10d11cef4 100644 --- a/docs/classes/singer_sdk.exceptions.RecordsWithoutSchemaException.rst +++ b/docs/classes/singer_sdk.exceptions.RecordsWithoutSchemaException.rst @@ -5,4 +5,4 @@ .. autoclass:: RecordsWithoutSchemaException :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.RetriableAPIError.rst b/docs/classes/singer_sdk.exceptions.RetriableAPIError.rst index 5a0e7f2eb..38f5c18e5 100644 --- a/docs/classes/singer_sdk.exceptions.RetriableAPIError.rst +++ b/docs/classes/singer_sdk.exceptions.RetriableAPIError.rst @@ -5,4 +5,4 @@ .. autoclass:: RetriableAPIError :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.StreamMapConfigError.rst b/docs/classes/singer_sdk.exceptions.StreamMapConfigError.rst index 52f436a01..fc27ddec4 100644 --- a/docs/classes/singer_sdk.exceptions.StreamMapConfigError.rst +++ b/docs/classes/singer_sdk.exceptions.StreamMapConfigError.rst @@ -5,4 +5,4 @@ .. autoclass:: StreamMapConfigError :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.TapStreamConnectionFailure.rst b/docs/classes/singer_sdk.exceptions.TapStreamConnectionFailure.rst index c172787d2..4876e5018 100644 --- a/docs/classes/singer_sdk.exceptions.TapStreamConnectionFailure.rst +++ b/docs/classes/singer_sdk.exceptions.TapStreamConnectionFailure.rst @@ -5,4 +5,4 @@ .. autoclass:: TapStreamConnectionFailure :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.exceptions.TooManyRecordsException.rst b/docs/classes/singer_sdk.exceptions.TooManyRecordsException.rst index 3ebbb8d98..ab9ddeb82 100644 --- a/docs/classes/singer_sdk.exceptions.TooManyRecordsException.rst +++ b/docs/classes/singer_sdk.exceptions.TooManyRecordsException.rst @@ -5,4 +5,4 @@ .. autoclass:: TooManyRecordsException :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.BaseAPIPaginator.rst b/docs/classes/singer_sdk.pagination.BaseAPIPaginator.rst index 38af9ca94..dfbfbc421 100644 --- a/docs/classes/singer_sdk.pagination.BaseAPIPaginator.rst +++ b/docs/classes/singer_sdk.pagination.BaseAPIPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: BaseAPIPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.BaseHATEOASPaginator.rst b/docs/classes/singer_sdk.pagination.BaseHATEOASPaginator.rst index a8247e938..1581fb722 100644 --- a/docs/classes/singer_sdk.pagination.BaseHATEOASPaginator.rst +++ b/docs/classes/singer_sdk.pagination.BaseHATEOASPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: BaseHATEOASPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.BaseOffsetPaginator.rst b/docs/classes/singer_sdk.pagination.BaseOffsetPaginator.rst index 5e05fb807..1321997c8 100644 --- a/docs/classes/singer_sdk.pagination.BaseOffsetPaginator.rst +++ b/docs/classes/singer_sdk.pagination.BaseOffsetPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: BaseOffsetPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.BasePageNumberPaginator.rst b/docs/classes/singer_sdk.pagination.BasePageNumberPaginator.rst index 10c522756..15821f06f 100644 --- a/docs/classes/singer_sdk.pagination.BasePageNumberPaginator.rst +++ b/docs/classes/singer_sdk.pagination.BasePageNumberPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: BasePageNumberPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.HeaderLinkPaginator.rst b/docs/classes/singer_sdk.pagination.HeaderLinkPaginator.rst index b6c5599e0..8820562b9 100644 --- a/docs/classes/singer_sdk.pagination.HeaderLinkPaginator.rst +++ b/docs/classes/singer_sdk.pagination.HeaderLinkPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: HeaderLinkPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.JSONPathPaginator.rst b/docs/classes/singer_sdk.pagination.JSONPathPaginator.rst index 1491ebd91..ded926d7f 100644 --- a/docs/classes/singer_sdk.pagination.JSONPathPaginator.rst +++ b/docs/classes/singer_sdk.pagination.JSONPathPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: JSONPathPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.LegacyPaginatedStreamProtocol.rst b/docs/classes/singer_sdk.pagination.LegacyPaginatedStreamProtocol.rst index 82054de50..153d83481 100644 --- a/docs/classes/singer_sdk.pagination.LegacyPaginatedStreamProtocol.rst +++ b/docs/classes/singer_sdk.pagination.LegacyPaginatedStreamProtocol.rst @@ -5,4 +5,4 @@ .. autoclass:: LegacyPaginatedStreamProtocol :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.LegacyStreamPaginator.rst b/docs/classes/singer_sdk.pagination.LegacyStreamPaginator.rst index 4be63ca65..3510a4852 100644 --- a/docs/classes/singer_sdk.pagination.LegacyStreamPaginator.rst +++ b/docs/classes/singer_sdk.pagination.LegacyStreamPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: LegacyStreamPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.SimpleHeaderPaginator.rst b/docs/classes/singer_sdk.pagination.SimpleHeaderPaginator.rst index 487c6a16b..494b92aac 100644 --- a/docs/classes/singer_sdk.pagination.SimpleHeaderPaginator.rst +++ b/docs/classes/singer_sdk.pagination.SimpleHeaderPaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: SimpleHeaderPaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/docs/classes/singer_sdk.pagination.SinglePagePaginator.rst b/docs/classes/singer_sdk.pagination.SinglePagePaginator.rst index 5f9b50114..332e86de2 100644 --- a/docs/classes/singer_sdk.pagination.SinglePagePaginator.rst +++ b/docs/classes/singer_sdk.pagination.SinglePagePaginator.rst @@ -5,4 +5,4 @@ .. autoclass:: SinglePagePaginator :members: - :special-members: __init__ \ No newline at end of file + :special-members: __init__, __call__ \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 2db30e7d3..de91c8ac9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -95,14 +95,14 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.26.11" +version = "1.26.26" description = "The AWS SDK for Python" category = "main" optional = true python-versions = ">= 3.7" [package.dependencies] -botocore = ">=1.29.11,<1.30.0" +botocore = ">=1.29.26,<1.30.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.6.0,<0.7.0" @@ -111,7 +111,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.29.11" +version = "1.29.26" description = "Low-level, data-driven core of boto 3." category = "main" optional = true @@ -123,7 +123,7 @@ python-dateutil = ">=2.1,<3.0.0" urllib3 = ">=1.25.4,<1.27" [package.extras] -crt = ["awscrt (==0.14.0)"] +crt = ["awscrt (==0.15.3)"] [[package]] name = "certifi" @@ -146,11 +146,11 @@ pycparser = "*" [[package]] name = "chardet" -version = "5.0.0" +version = "5.1.0" description = "Universal encoding detector for Python 3" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "charset-normalizer" @@ -582,7 +582,7 @@ python-versions = "*" [[package]] name = "mdit-py-plugins" -version = "0.3.1" +version = "0.3.3" description = "Collection of plugins for markdown-it-py" category = "main" optional = true @@ -681,14 +681,11 @@ python-versions = ">=3.6" [[package]] name = "packaging" -version = "21.3" +version = "22.0" description = "Core utilities for Python packages" category = "main" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" [[package]] name = "pathspec" @@ -720,7 +717,7 @@ python-versions = ">=3.6" [[package]] name = "platformdirs" -version = "2.5.4" +version = "2.6.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false @@ -859,17 +856,6 @@ cffi = ">=1.4.1" docs = ["sphinx (>=1.6.5)", "sphinx_rtd_theme"] tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - [[package]] name = "pyrsistent" version = "0.19.2" @@ -934,11 +920,11 @@ cli = ["click (>=5.0)"] [[package]] name = "python-slugify" -version = "6.1.2" +version = "7.0.0" description = "A Python slugify application that also handles Unicode" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" [package.dependencies] text-unidecode = ">=1.3" @@ -1020,7 +1006,7 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] [[package]] name = "setuptools" -version = "65.5.1" +version = "65.6.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "main" optional = false @@ -1341,11 +1327,11 @@ python-versions = ">=3.7" [[package]] name = "urllib3" -version = "1.26.12" +version = "1.26.13" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] @@ -1449,35 +1435,26 @@ binaryornot = [ {file = "binaryornot-0.4.4.tar.gz", hash = "sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061"}, ] black = [ - {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, - {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, - {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, - {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, - {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, - {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, - {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, - {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, - {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, ] boto3 = [ - {file = "boto3-1.26.11-py3-none-any.whl", hash = "sha256:3309d04e47490a1b46aa8ae7bcf4845a8dae2ed419a505c770895773ba7455dc"}, - {file = "boto3-1.26.11.tar.gz", hash = "sha256:f8f7268afe62e3b34b7d0e1b4d8a804148e713f35b0e6dbc736346b28b3c6549"}, + {file = "boto3-1.26.26-py3-none-any.whl", hash = "sha256:b1d2521bd2239c4d2d8ee2a79d932bc64bf4779521ecc60c1074ae8a5d88adaa"}, + {file = "boto3-1.26.26.tar.gz", hash = "sha256:a2349d436db6f6aa1e0def5501e4884572eb6f008f35063a359a6fa8ba3539b7"}, ] botocore = [ - {file = "botocore-1.29.11-py3-none-any.whl", hash = "sha256:a86d7e558074e849933983bc2c4cc6ae6bbed3aef3f5fb4d4689cd19331e4399"}, - {file = "botocore-1.29.11.tar.gz", hash = "sha256:97532c8a571017891ad4afee7951bea95c9f0bfe96a6f38fdca9062cd6067ec1"}, + {file = "botocore-1.29.26-py3-none-any.whl", hash = "sha256:2ca26983156fe0846a87b9325205af6bc56268fb99b8b4b9decccf50203ff3b4"}, + {file = "botocore-1.29.26.tar.gz", hash = "sha256:f71220fe5a5d393c391ed81a291c0d0985f147568c56da236453043f93727a34"}, ] certifi = [ {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, @@ -1550,8 +1527,8 @@ cffi = [ {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, ] chardet = [ - {file = "chardet-5.0.0-py3-none-any.whl", hash = "sha256:d3e64f022d254183001eccc5db4040520c0f23b1a3f33d6413e099eb7f126557"}, - {file = "chardet-5.0.0.tar.gz", hash = "sha256:0368df2bfd78b5fc20572bb4e9bb7fb53e2c094f60ae9993339e8671d0afb8aa"}, + {file = "chardet-5.1.0-py3-none-any.whl", hash = "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9"}, + {file = "chardet-5.1.0.tar.gz", hash = "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5"}, ] charset-normalizer = [ {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, @@ -1859,8 +1836,8 @@ mccabe = [ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, ] mdit-py-plugins = [ - {file = "mdit-py-plugins-0.3.1.tar.gz", hash = "sha256:3fc13298497d6e04fe96efdd41281bfe7622152f9caa1815ea99b5c893de9441"}, - {file = "mdit_py_plugins-0.3.1-py3-none-any.whl", hash = "sha256:606a7f29cf56dbdfaf914acb21709b8f8ee29d857e8f29dcc33d8cb84c57bfa1"}, + {file = "mdit-py-plugins-0.3.3.tar.gz", hash = "sha256:5cfd7e7ac582a594e23ba6546a2f406e94e42eb33ae596d0734781261c251260"}, + {file = "mdit_py_plugins-0.3.3-py3-none-any.whl", hash = "sha256:36d08a29def19ec43acdcd8ba471d3ebab132e7879d442760d963f19913e04b9"}, ] mdurl = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, @@ -1947,8 +1924,8 @@ objprint = [ {file = "objprint-0.2.2.tar.gz", hash = "sha256:90f2f3c19dfda1b5eb50d87d82ccbc20511ca4f02c4878553c56edc711e39689"}, ] packaging = [ - {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, - {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, + {file = "packaging-22.0-py3-none-any.whl", hash = "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"}, + {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"}, ] pathspec = [ {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, @@ -1982,8 +1959,8 @@ pkgutil-resolve-name = [ {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, ] platformdirs = [ - {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, - {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, + {file = "platformdirs-2.6.0-py3-none-any.whl", hash = "sha256:1a89a12377800c81983db6be069ec068eee989748799b946cce2a6e80dcc54ca"}, + {file = "platformdirs-2.6.0.tar.gz", hash = "sha256:b46ffafa316e6b83b47489d240ce17173f123a9b9c83282141c3daf26ad9ac2e"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, @@ -2060,10 +2037,6 @@ pynacl = [ {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, ] -pyparsing = [ - {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, - {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, -] pyrsistent = [ {file = "pyrsistent-0.19.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d6982b5a0237e1b7d876b60265564648a69b14017f3b5f908c5be2de3f9abb7a"}, {file = "pyrsistent-0.19.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:187d5730b0507d9285a96fca9716310d572e5464cadd19f22b63a6976254d77a"}, @@ -2105,8 +2078,8 @@ python-dotenv = [ {file = "python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"}, ] python-slugify = [ - {file = "python-slugify-6.1.2.tar.gz", hash = "sha256:272d106cb31ab99b3496ba085e3fea0e9e76dcde967b5e9992500d1f785ce4e1"}, - {file = "python_slugify-6.1.2-py2.py3-none-any.whl", hash = "sha256:7b2c274c308b62f4269a9ba701aa69a797e9bca41aeee5b3a9e79e36b6656927"}, + {file = "python-slugify-7.0.0.tar.gz", hash = "sha256:7a0f21a39fa6c1c4bf2e5984c9b9ae944483fd10b54804cb0e23a3ccd4954f0b"}, + {file = "python_slugify-7.0.0-py2.py3-none-any.whl", hash = "sha256:003aee64f9fd955d111549f96c4b58a3f40b9319383c70fad6277a4974bbf570"}, ] pytz = [ {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, @@ -2124,13 +2097,6 @@ pyyaml = [ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, @@ -2171,8 +2137,8 @@ s3transfer = [ {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, ] setuptools = [ - {file = "setuptools-65.5.1-py3-none-any.whl", hash = "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31"}, - {file = "setuptools-65.5.1.tar.gz", hash = "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f"}, + {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"}, + {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"}, ] simplejson = [ {file = "simplejson-3.18.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:17dbc7f71fa5b7e4a2acef38cf0be30461ae6659456a978ce7eeebeb5bdf9e1a"}, @@ -2408,8 +2374,8 @@ typing-extensions = [ {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, ] urllib3 = [ - {file = "urllib3-1.26.12-py2.py3-none-any.whl", hash = "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997"}, - {file = "urllib3-1.26.12.tar.gz", hash = "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e"}, + {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, + {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, ] viztracer = [ {file = "viztracer-0.15.6-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:73fbd8e6f7ebe7e1eb78dd6bedbec7b8a217aa9d4910d880268de26ec8089590"}, diff --git a/singer_sdk/authenticators.py b/singer_sdk/authenticators.py index f6bac0642..09c0d36f0 100644 --- a/singer_sdk/authenticators.py +++ b/singer_sdk/authenticators.py @@ -8,6 +8,7 @@ from datetime import datetime, timedelta from types import MappingProxyType from typing import Any, Mapping +from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit import jwt import requests @@ -18,6 +19,30 @@ from singer_sdk.streams import Stream as RESTStreamBase +def _add_parameters(initial_url: str, extra_parameters: dict) -> str: + """Add parameters to an URL and return the new URL. + + Args: + initial_url: The URL to add parameters to. + extra_parameters: The parameters to add. + + Returns: + The new URL with the parameters added. + """ + scheme, netloc, path, query_string, fragment = urlsplit(initial_url) + query_params = parse_qs(query_string) + query_params.update( + { + parameter_name: [parameter_value] + for parameter_name, parameter_value in extra_parameters.items() + } + ) + + new_query_string = urlencode(query_params, doseq=True) + + return urlunsplit((scheme, netloc, path, new_query_string, fragment)) + + class SingletonMeta(type): """A general purpose singleton metaclass.""" @@ -94,17 +119,45 @@ def auth_params(self) -> dict: """ return self._auth_params or {} - def authenticate_request(self, request: requests.Request) -> None: + def authenticate_request( + self, + request: requests.PreparedRequest, + ) -> requests.PreparedRequest: """Authenticate a request. Args: request: A `request object`_. + Returns: + The authenticated request object. + .. _request object: - https://requests.readthedocs.io/en/latest/api/#requests.Request + https://requests.readthedocs.io/en/latest/api/#requests.PreparedRequest """ request.headers.update(self.auth_headers) - request.params.update(self.auth_params) + + if request.url: + request.url = _add_parameters(request.url, self.auth_params) + + return request + + def __call__(self, r: requests.PreparedRequest) -> requests.PreparedRequest: + """Authenticate a request. + + Calls + :meth:`~singer_sdk.authenticators.APIAuthenticatorBase.authenticate_request` + and returns the result. + + Args: + r: A `request object`_. + + Returns: + The authenticated request object. + + .. _request object: + https://requests.readthedocs.io/en/latest/api/#requests.PreparedRequest + """ + return self.authenticate_request(r) class SimpleAuthenticator(APIAuthenticatorBase): diff --git a/singer_sdk/streams/rest.py b/singer_sdk/streams/rest.py index db2f33d6f..ee0a0c471 100644 --- a/singer_sdk/streams/rest.py +++ b/singer_sdk/streams/rest.py @@ -5,6 +5,7 @@ import abc import copy import logging +import sys from datetime import datetime from typing import TYPE_CHECKING, Any, Callable, Generator, Generic, Iterable, TypeVar from urllib.parse import urlparse @@ -15,7 +16,7 @@ from singer_sdk import metrics from singer_sdk._singerlib import Schema -from singer_sdk.authenticators import APIAuthenticatorBase, SimpleAuthenticator +from singer_sdk.authenticators import SimpleAuthenticator from singer_sdk.exceptions import FatalAPIError, RetriableAPIError from singer_sdk.helpers.jsonpath import extract_jsonpath from singer_sdk.pagination import ( @@ -27,6 +28,11 @@ from singer_sdk.plugin_base import PluginBase as TapBaseClass from singer_sdk.streams.core import Stream +if sys.version_info >= (3, 10): + from typing import TypeAlias +else: + from typing_extensions import TypeAlias + if TYPE_CHECKING: from backoff.types import Details @@ -34,6 +40,7 @@ DEFAULT_REQUEST_TIMEOUT = 300 # 5 minutes _TToken = TypeVar("_TToken") +_Auth: TypeAlias = Callable[[requests.PreparedRequest], requests.PreparedRequest] class RESTStream(Stream, Generic[_TToken], metaclass=abc.ABCMeta): @@ -294,11 +301,7 @@ def build_prepared_request( https://requests.readthedocs.io/en/latest/api/#requests.Request """ request = requests.Request(*args, **kwargs) - - if self.authenticator: - authenticator = self.authenticator - authenticator.authenticate_request(request) - + self.requests_session.auth = self.authenticator return self.requests_session.prepare_request(request) def prepare_request( @@ -559,7 +562,7 @@ def parse_response(self, response: requests.Response) -> Iterable[dict]: # Abstract methods: @property - def authenticator(self) -> APIAuthenticatorBase | None: + def authenticator(self) -> _Auth: """Return or set the authenticator for managing HTTP auth headers. If an authenticator is not specified, REST-based taps will simply pass diff --git a/tests/core/rest/conftest.py b/tests/core/rest/conftest.py index 0ee924f3f..8a09e302e 100644 --- a/tests/core/rest/conftest.py +++ b/tests/core/rest/conftest.py @@ -2,6 +2,7 @@ import pytest from memoization.memoization import cached +from requests.auth import HTTPProxyAuth from singer_sdk.authenticators import APIAuthenticatorBase, SingletonMeta from singer_sdk.streams import RESTStream @@ -51,6 +52,15 @@ def authenticator(self) -> NaiveAuthenticator: return NaiveAuthenticator(stream=self) +class ProxyAuthStream(SimpleRESTStream): + """A stream with digest authentication.""" + + @property + def authenticator(self): + """Stream authenticator.""" + return HTTPProxyAuth("username", "password") + + class SimpleTap(Tap): """A REST tap for testing.""" @@ -65,6 +75,7 @@ def discover_streams(self): SingletonAuthStream(self, name="reused_single_auth_stream"), CachedAuthStream(self, name="cached_auth_stream"), CachedAuthStream(self, name="other_cached_auth_stream"), + ProxyAuthStream(self, name="proxy_auth_stream"), ] diff --git a/tests/core/rest/test_authenticators.py b/tests/core/rest/test_authenticators.py index 9d18a7728..3ca038614 100644 --- a/tests/core/rest/test_authenticators.py +++ b/tests/core/rest/test_authenticators.py @@ -16,6 +16,7 @@ PrivateFormat, PublicFormat, ) +from requests.auth import HTTPProxyAuth, _basic_auth_str from singer_sdk.authenticators import OAuthAuthenticator, OAuthJWTAuthenticator from singer_sdk.streams import RESTStream @@ -182,3 +183,12 @@ class _FakeOAuthJWTAuthenticator(OAuthJWTAuthenticator): token = payload["assertion"] assert jwt.decode(token, public_key_string, algorithms=["RS256"]) == body + + +def test_requests_library_auth(rest_tap: Tap): + """Validate that a requests.auth object can be used as an authenticator.""" + stream: RESTStream = rest_tap.streams["proxy_auth_stream"] + r = stream.prepare_request(None, None) + + assert isinstance(stream.authenticator, HTTPProxyAuth) + assert r.headers["Proxy-Authorization"] == _basic_auth_str("username", "password") From c6caacc946517eb8152c327353e177ce387a3478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Rami=CC=81rez=20Mondrago=CC=81n?= Date: Fri, 3 Feb 2023 12:17:05 -0600 Subject: [PATCH 2/2] docs: Add `requests.auth` code sample --- docs/code_samples.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/code_samples.md b/docs/code_samples.md index e76db4d46..90d9682e8 100644 --- a/docs/code_samples.md +++ b/docs/code_samples.md @@ -255,6 +255,34 @@ class CachedAuthStream(RESTStream): return APIAuthenticatorBase(stream=self) ``` +### Use one of `requests`'s built-in authenticators + +```python +from requests.auth import HTTPDigestAuth +from singer_sdk.streams import RESTStream + +class DigestAuthStream(RESTStream): + """A stream with digest authentication.""" + + @property + def authenticator(self) -> HTTPDigestAuth: + """Stream authenticator.""" + return HTTPDigestAuth( + username=self.config["username"], + password=self.config["password"], + ) +``` + +[`HTTPBasicAuth`](https://requests.readthedocs.io/en/latest/api/#requests.auth.HTTPBasicAuth) and +[`HTTPProxyAuth`](https://requests.readthedocs.io/en/latest/api/#requests.auth.HTTPProxyAuth) +are also available in `requests.auth`. In addition to `requests.auth` classes, the community +has published a few packages with custom authenticator classes, which are compatible with the SDK. +For example: + +- [`requests-aws4auth`](https://github.com/tedder/requests-aws4auth): AWS v4 authentication +- [`requests_auth`](https://github.com/Colin-b/requests_auth): A collection of authenticators + for various services and protocols including Azure, Okta and NTLM. + ### Custom response validation Some APIs deviate from HTTP status codes to report failures. For those cases,