Skip to content

Commit 46f0685

Browse files
authored
chore: remove placeholders (#110)
* chore: remove placeholders * chore: remove placeholders * fix: update docstring * fix: use AuthHeaders, cleanup others (#113) * fix: use AuthHeaders, cleanup others * chore: run 'pre-commit autoupdate' * fix: place import at top (PEP 8 style)
1 parent 5e4c796 commit 46f0685

File tree

9 files changed

+49
-152
lines changed

9 files changed

+49
-152
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ repos:
3434

3535
- repo: https://github.com/astral-sh/ruff-pre-commit
3636
# Ruff version.
37-
rev: v0.13.1
37+
rev: v0.13.3
3838
hooks:
3939
# Run the linter.
4040
- id: ruff-check

src/otdf_python/auth_headers.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class AuthHeaders:
1010
"""
1111

1212
auth_header: str
13-
dpop_header: str
13+
dpop_header: str = ""
1414

1515
def get_auth_header(self) -> str:
1616
"""Returns the authorization header."""
@@ -19,3 +19,15 @@ def get_auth_header(self) -> str:
1919
def get_dpop_header(self) -> str:
2020
"""Returns the DPoP header."""
2121
return self.dpop_header
22+
23+
def to_dict(self) -> dict[str, str]:
24+
"""
25+
Convert authentication headers to a dictionary for use with HTTP clients.
26+
27+
Returns:
28+
Dictionary with 'Authorization' header and optionally 'DPoP' header
29+
"""
30+
headers = {"Authorization": self.auth_header}
31+
if self.dpop_header:
32+
headers["DPoP"] = self.dpop_header
33+
return headers

src/otdf_python/kas_connect_rpc_client.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
from otdf_python_proto.kas import kas_pb2
1010
from otdf_python_proto.kas.kas_pb2_connect import AccessServiceClient
1111

12+
from otdf_python.auth_headers import AuthHeaders
13+
1214
from .sdk_exceptions import SDKException
1315

1416

@@ -69,7 +71,11 @@ def _prepare_auth_headers(self, access_token):
6971
Dictionary with authentication headers or None
7072
"""
7173
if access_token:
72-
return {"Authorization": f"Bearer {access_token}"}
74+
auth_headers = AuthHeaders(
75+
auth_header=f"Bearer {access_token}",
76+
dpop_header="", # Empty for now, ready for future DPoP support
77+
)
78+
return auth_headers.to_dict()
7379
return None
7480

7581
def get_public_key(self, normalized_kas_url, kas_info, access_token=None):

src/otdf_python/sdk.py

Lines changed: 6 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,12 @@
66
from io import BytesIO
77
from typing import Any, BinaryIO
88

9-
from otdf_python.config import NanoTDFConfig, TDFConfig
9+
from otdf_python.config import KASInfo, NanoTDFConfig, TDFConfig
1010
from otdf_python.nanotdf import NanoTDF
1111
from otdf_python.sdk_exceptions import SDKException
1212
from otdf_python.tdf import TDF, TDFReader, TDFReaderConfig
1313

1414

15-
# Stubs for service client interfaces (to be implemented)
16-
class AttributesServiceClientInterface: ...
17-
18-
19-
class NamespaceServiceClientInterface: ...
20-
21-
22-
class SubjectMappingServiceClientInterface: ...
23-
24-
25-
class ResourceMappingServiceClientInterface: ...
26-
27-
28-
class AuthorizationServiceClientInterface: ...
29-
30-
31-
class KeyAccessServerRegistryServiceClientInterface: ...
32-
33-
34-
# Placeholder for ProtocolClient and Interceptor
35-
class ProtocolClient: ...
36-
37-
38-
class Interceptor: ... # Can be dict in Python implementation
39-
40-
41-
# Placeholder for TrustManager
42-
class TrustManager: ...
43-
44-
4515
class KAS(AbstractContextManager):
4616
"""
4717
KAS (Key Access Service) interface to define methods related to key access and management.
@@ -71,7 +41,6 @@ def __init__(
7141
token_source=None,
7242
sdk_ssl_verify=True,
7343
use_plaintext=False,
74-
auth_headers: dict | None = None,
7544
):
7645
"""
7746
Initialize the KAS client
@@ -81,7 +50,6 @@ def __init__(
8150
token_source: Function that returns an authentication token
8251
sdk_ssl_verify: Whether to verify SSL certificates
8352
use_plaintext: Whether to use plaintext HTTP connections instead of HTTPS
84-
auth_headers: Dictionary of authentication headers to include in requests
8553
"""
8654
from .kas_client import KASClient
8755

@@ -94,7 +62,6 @@ def __init__(
9462
# Store the parameters for potential use
9563
self._sdk_ssl_verify = sdk_ssl_verify
9664
self._use_plaintext = use_plaintext
97-
self._auth_headers = auth_headers
9865

9966
def get_ec_public_key(self, kas_info: Any, curve: Any) -> Any:
10067
"""
@@ -179,12 +146,14 @@ def __exit__(self, exc_type, exc_val, exc_tb):
179146

180147
class SDK(AbstractContextManager):
181148
def new_tdf_config(
182-
self, attributes: list[str] | None = None, **kwargs
149+
self,
150+
attributes: list[str] | None = None,
151+
kas_info_list: list[KASInfo] | None = None,
152+
**kwargs,
183153
) -> TDFConfig:
184154
"""
185155
Create a TDFConfig with default kas_info_list from the SDK's platform_url.
186156
"""
187-
from otdf_python.config import KASInfo
188157

189158
if self.platform_url is None:
190159
raise SDKException("Cannot create TDFConfig: SDK platform_url is not set.")
@@ -232,10 +201,8 @@ def new_tdf_config(
232201
# Use existing port with the determined scheme
233202
kas_url = f"{scheme}://{parsed_url.hostname}:{parsed_url.port}{parsed_url.path.rstrip('/')}/kas"
234203

235-
kas_info = KASInfo(url=kas_url, default=True)
236-
# Accept user override for kas_info_list if provided
237-
kas_info_list = kwargs.pop("kas_info_list", None)
238204
if kas_info_list is None:
205+
kas_info = KASInfo(url=kas_url, default=True)
239206
kas_info_list = [kas_info]
240207
return TDFConfig(
241208
kas_info_list=kas_info_list, attributes=attributes or [], **kwargs
@@ -251,30 +218,6 @@ class Services(AbstractContextManager):
251218
The Services interface provides access to various platform service clients and KAS.
252219
"""
253220

254-
def attributes(self) -> AttributesServiceClientInterface:
255-
"""Returns the attributes service client"""
256-
raise NotImplementedError
257-
258-
def namespaces(self) -> NamespaceServiceClientInterface:
259-
"""Returns the namespaces service client"""
260-
raise NotImplementedError
261-
262-
def subject_mappings(self) -> SubjectMappingServiceClientInterface:
263-
"""Returns the subject mappings service client"""
264-
raise NotImplementedError
265-
266-
def resource_mappings(self) -> ResourceMappingServiceClientInterface:
267-
"""Returns the resource mappings service client"""
268-
raise NotImplementedError
269-
270-
def authorization(self) -> AuthorizationServiceClientInterface:
271-
"""Returns the authorization service client"""
272-
raise NotImplementedError
273-
274-
def kas_registry(self) -> KeyAccessServerRegistryServiceClientInterface:
275-
"""Returns the KAS registry service client"""
276-
raise NotImplementedError
277-
278221
def kas(self) -> KAS:
279222
"""
280223
Returns the KAS client for key access operations.
@@ -292,9 +235,6 @@ def __exit__(self, exc_type, exc_val, exc_tb):
292235
def __init__(
293236
self,
294237
services: "SDK.Services",
295-
trust_manager: TrustManager | None = None,
296-
auth_interceptor: Interceptor | dict[str, str] | None = None,
297-
platform_services_client: ProtocolClient | None = None,
298238
platform_url: str | None = None,
299239
ssl_verify: bool = True,
300240
use_plaintext: bool = False,
@@ -304,17 +244,11 @@ def __init__(
304244
305245
Args:
306246
services: The services interface implementation
307-
trust_manager: Optional trust manager for SSL validation
308-
auth_interceptor: Optional auth interceptor for API requests
309-
platform_services_client: Optional client for platform services
310247
platform_url: Optional platform base URL
311248
ssl_verify: Whether to verify SSL certificates (default: True)
312249
use_plaintext: Whether to use HTTP instead of HTTPS (default: False)
313250
"""
314251
self.services = services
315-
self.trust_manager = trust_manager
316-
self.auth_interceptor = auth_interceptor
317-
self.platform_services_client = platform_services_client
318252
self.platform_url = platform_url
319253
self.ssl_verify = ssl_verify
320254
self._use_plaintext = use_plaintext
@@ -332,18 +266,6 @@ def get_services(self) -> "SDK.Services":
332266
"""Returns the services interface"""
333267
return self.services
334268

335-
def get_trust_manager(self) -> TrustManager | None:
336-
"""Returns the trust manager if set"""
337-
return self.trust_manager
338-
339-
def get_auth_interceptor(self) -> Interceptor | dict[str, str] | None:
340-
"""Returns the auth interceptor if set"""
341-
return self.auth_interceptor
342-
343-
def get_platform_services_client(self) -> ProtocolClient | None:
344-
"""Returns the platform services client if set"""
345-
return self.platform_services_client
346-
347269
def get_platform_url(self) -> str | None:
348270
"""Returns the platform URL if set"""
349271
return self.platform_url

src/otdf_python/sdk_builder.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import ssl
88
from dataclasses import dataclass
99
from pathlib import Path
10-
from typing import Any
1110

1211
import httpx
1312

@@ -344,32 +343,6 @@ def _get_token_from_client_credentials(self) -> str:
344343
except Exception as e:
345344
raise AutoConfigureException(f"Error during token acquisition: {e!s}")
346345

347-
def _create_auth_interceptor(self) -> Any:
348-
"""
349-
Creates an authentication interceptor for API requests (httpx).
350-
Returns:
351-
Any: An auth interceptor object
352-
Raises:
353-
AutoConfigureException: If auth configuration fails
354-
"""
355-
# For now, this is just a placeholder returning a dict with auth headers
356-
# In a real implementation, this would create a proper interceptor object
357-
# that injects auth headers into httpx requests
358-
359-
token = None
360-
361-
if self.auth_token:
362-
# Use provided token
363-
token = self.auth_token
364-
elif self.oauth_config:
365-
# Get token from OAuth
366-
token = self._get_token_from_client_credentials()
367-
368-
if token:
369-
return {"Authorization": f"Bearer {token}"}
370-
371-
return None
372-
373346
def _create_services(self) -> SDK.Services:
374347
"""
375348
Creates service client instances.
@@ -383,13 +356,11 @@ def _create_services(self) -> SDK.Services:
383356
# connecting to the platform endpoints
384357

385358
ssl_verify = not self.insecure_skip_verify
386-
auth_interceptor = self._create_auth_interceptor()
387359

388360
class ServicesImpl(SDK.Services):
389361
def __init__(self, builder_instance):
390362
self.closed = False
391363
self._ssl_verify = ssl_verify
392-
self._auth_headers = auth_interceptor if auth_interceptor else {}
393364
self._builder = builder_instance
394365

395366
def kas(self) -> KAS:
@@ -433,16 +404,12 @@ def build(self) -> SDK:
433404
if not self.platform_endpoint:
434405
raise AutoConfigureException("Platform endpoint is not set")
435406

436-
# Create the auth interceptor
437-
auth_interceptor = self._create_auth_interceptor()
438-
439407
# Create services
440408
services = self._create_services()
441409

442410
# Return the SDK instance, platform_url is set for new_tdf_config
443411
return SDK(
444412
services=services,
445-
auth_interceptor=auth_interceptor,
446413
platform_url=self.platform_endpoint,
447414
ssl_verify=not self.insecure_skip_verify,
448415
use_plaintext=getattr(self, "use_plaintext", False),

tests/test_inner_classes.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,27 @@ def test_auth_headers(self):
1313
self.assertEqual(headers.get_auth_header(), "Bearer token123")
1414
self.assertEqual(headers.get_dpop_header(), "dpop456")
1515

16+
def test_auth_headers_to_dict_with_dpop(self):
17+
headers = AuthHeaders("Bearer token123", "dpop456")
18+
headers_dict = headers.to_dict()
19+
self.assertEqual(headers_dict["Authorization"], "Bearer token123")
20+
self.assertEqual(headers_dict["DPoP"], "dpop456")
21+
self.assertEqual(len(headers_dict), 2)
22+
23+
def test_auth_headers_to_dict_without_dpop(self):
24+
headers = AuthHeaders("Bearer token123", "")
25+
headers_dict = headers.to_dict()
26+
self.assertEqual(headers_dict["Authorization"], "Bearer token123")
27+
self.assertNotIn("DPoP", headers_dict)
28+
self.assertEqual(len(headers_dict), 1)
29+
30+
def test_auth_headers_default_dpop(self):
31+
headers = AuthHeaders("Bearer token123")
32+
self.assertEqual(headers.dpop_header, "")
33+
headers_dict = headers.to_dict()
34+
self.assertEqual(headers_dict["Authorization"], "Bearer token123")
35+
self.assertNotIn("DPoP", headers_dict)
36+
1637

1738
class TestKASInfo(unittest.TestCase):
1839
def test_kas_info_clone(self):

tests/test_sdk.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@ def test_sdk_init_and_close():
1717
services = DummyServices()
1818
sdk = SDK(services)
1919
assert sdk.get_services() is services
20-
assert sdk.get_trust_manager() is None
21-
assert sdk.get_auth_interceptor() is None
22-
assert sdk.get_platform_services_client() is None
2320
assert sdk.get_platform_url() is None
2421
# Test context manager exit calls close
2522
with SDK(services):

tests/test_sdk_builder.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,4 @@ def test_build_success():
211211
# Verify the SDK was created correctly
212212
assert isinstance(sdk, SDK)
213213
assert sdk.platform_url == "https://example.com"
214-
assert sdk.auth_interceptor == {"Authorization": "Bearer test-token"}
215214
assert sdk.get_services() is mock_services

tests/test_sdk_mock.py

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
1-
from otdf_python.sdk import (
2-
KAS,
3-
SDK,
4-
AttributesServiceClientInterface,
5-
AuthorizationServiceClientInterface,
6-
KeyAccessServerRegistryServiceClientInterface,
7-
NamespaceServiceClientInterface,
8-
ResourceMappingServiceClientInterface,
9-
SubjectMappingServiceClientInterface,
10-
)
1+
from otdf_python.sdk import KAS, SDK
112

123

134
class MockKAS(KAS):
@@ -28,24 +19,6 @@ def get_key_cache(self):
2819

2920

3021
class MockServices(SDK.Services):
31-
def attributes(self):
32-
return AttributesServiceClientInterface()
33-
34-
def namespaces(self):
35-
return NamespaceServiceClientInterface()
36-
37-
def subject_mappings(self):
38-
return SubjectMappingServiceClientInterface()
39-
40-
def resource_mappings(self):
41-
return ResourceMappingServiceClientInterface()
42-
43-
def authorization(self):
44-
return AuthorizationServiceClientInterface()
45-
46-
def kas_registry(self):
47-
return KeyAccessServerRegistryServiceClientInterface()
48-
4922
def kas(self):
5023
return MockKAS()
5124

0 commit comments

Comments
 (0)