Skip to content

Conversation

@brettchaldecott
Copy link
Contributor

@brettchaldecott brettchaldecott commented Jul 2, 2025

Explain your changes

Merged the changes

Checklist

🛟 If you need help, consider asking for advice over in the Kinde community.

Syed Raza Abbas and others added 30 commits February 3, 2025 11:06
add main v2 to workflow rule
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
kinde_fastapi/framework/fastapi_framework.py (1)

1-9: Remove duplicate and unused imports.

🧹 Nitpick comments (7)
kinde_fastapi/storage/fastapi_storage_factory.py (2)

3-3: Remove unused import.

The StorageFactory import is not used in this file and should be removed to clean up the imports.

-from kinde_sdk.core.storage.storage_factory import StorageFactory

6-6: Add proper spacing before class definition.

According to PEP8, there should be 2 blank lines before a class definition.

+
 class FastAPIStorageFactory:
kinde_fastapi/framework/fastapi_framework.py (5)

13-13: Add proper spacing before class definition.

According to PEP8, there should be 2 blank lines before a class definition.

+
 class FastAPIFramework(FrameworkInterface):

54-54: Remove duplicate docstring line.

The docstring has a duplicate line that should be removed.

-        This method initializes any necessary FastAPI components and registers Kinde routes.

118-125: Remove unused helper function.

The get_current_user function is defined but never used in the route handlers. Consider removing it to clean up the code.

-        # Helper function to get current user
-        async def get_current_user(request: Request):
-            if not self._oauth.is_authenticated(request):
-                return None
-            try:
-                return self._oauth.get_user_info(request)
-            except ValueError:
-                return None
-        

130-130: Add whitespace around operator.

Missing whitespace around the assignment operator.

-            url=await self._oauth.login()
+            url = await self._oauth.login()

189-193: Use importlib.util.find_spec for import checking.

Using importlib.util.find_spec is the recommended approach for checking module availability without importing.

         try:
-            import fastapi
+            import importlib.util
+            spec = importlib.util.find_spec("fastapi")
+            return spec is not None
-            return True
         except ImportError:
             return False
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 723947c and 1866967.

📒 Files selected for processing (2)
  • kinde_fastapi/framework/fastapi_framework.py (1 hunks)
  • kinde_fastapi/storage/fastapi_storage_factory.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.11.9)
kinde_fastapi/framework/fastapi_framework.py

1-1: typing.Dict imported but unused

Remove unused import

(F401)


1-1: typing.Any imported but unused

Remove unused import

(F401)


2-2: fastapi.Depends imported but unused

Remove unused import: fastapi.Depends

(F401)


7-7: os imported but unused

Remove unused import: os

(F401)


190-190: fastapi imported but unused; consider using importlib.util.find_spec to test for availability

(F401)

kinde_fastapi/storage/fastapi_storage_factory.py

3-3: kinde_sdk.core.storage.storage_factory.StorageFactory imported but unused

Remove unused import: kinde_sdk.core.storage.storage_factory.StorageFactory

(F401)

🪛 Flake8 (7.2.0)
kinde_fastapi/framework/fastapi_framework.py

[error] 1-1: 'typing.Dict' imported but unused

(F401)


[error] 1-1: 'typing.Any' imported but unused

(F401)


[error] 2-2: 'fastapi.Depends' imported but unused

(F401)


[error] 7-7: 'os' imported but unused

(F401)


[error] 13-13: expected 2 blank lines, found 1

(E302)


[error] 130-130: missing whitespace around operator

(E225)


[error] 190-190: 'fastapi' imported but unused

(F401)

kinde_fastapi/storage/fastapi_storage_factory.py

[error] 3-3: 'kinde_sdk.core.storage.storage_factory.StorageFactory' imported but unused

(F401)


[error] 6-6: expected 2 blank lines, found 1

(E302)

🔇 Additional comments (2)
kinde_fastapi/storage/fastapi_storage_factory.py (1)

11-23: Well-structured factory implementation.

The factory method is correctly implemented with proper type hints and documentation. The unused config parameter is appropriately documented as being kept for consistency with other storage factories.

kinde_fastapi/framework/fastapi_framework.py (1)

13-193: Comprehensive FastAPI framework implementation.

The FastAPIFramework class provides a well-structured implementation of the framework interface with proper OAuth integration, session management, and route handling. The architecture follows good separation of concerns and provides all necessary authentication flows.

Brett Chaldecott added 5 commits July 3, 2025 11:35
- Remove import of generate_random_string, base64_url_encode, and generate_pkce_pair helpers
- Keep only storage and framework related imports that are actually used
- Remove duplicate import statement for FeatureFlagsApi
- Clean up import section to avoid redundancy
- Remove unused warnings import
- Remove duplicate pydantic Field and StrictStr imports
- Remove duplicate typing_extensions Annotated import
- Keep only necessary imports to reduce code clutter
- Restore original imports in callbacks_api.py including duplicate imports
- Restore original imports in connections_api.py
- Ensure generated code matches OpenAPI specification output
- Maintain consistency with auto-generated API client code
- Remove extra space before equals sign in logger parameter default value
- Follow PEP 8 style guidelines for function parameter formatting
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (11)
kinde_sdk/management/api/connections_api.py (1)

15-15: Remove unused import

The warnings module is imported but never used in the code.

-import warnings
kinde_sdk/auth/oauth.py (5)

5-15: Remove unused imports.

This issue has been previously identified and specific imports to remove have been listed.


135-144: Convert debug logging to appropriate level.

This debug logging issue has been previously identified with specific recommendations to change from warning to debug level.


486-486: Convert debug logging to appropriate level.

This debug logging issue has been previously identified.


503-505: Use proper exception chaining.

This exception chaining issue has been previously identified with specific fix provided.


568-571: Convert debug logging to appropriate level.

This debug logging issue has been previously identified.

kinde_sdk/core/helpers.py (5)

40-69: Remove unnecessary async keyword from synchronous function.

This issue has been previously identified with the recommendation to remove the async keyword.


71-121: Remove unnecessary async keyword or use async HTTP client.

This issue has been previously identified with specific recommendations.


150-153: Use proper exception chaining for better debugging.

This exception chaining issue has been previously identified with specific fix provided.


332-332: Remove spaces around default parameter equals to comply with PEP 8.

This PEP 8 violation has been previously identified with specific functions listed.


503-507: Simplify role checking logic using any().

This optimization has been previously identified with the specific any() replacement provided.

🧹 Nitpick comments (4)
kinde_sdk/auth/oauth.py (4)

160-160: Remove unnecessary f-string prefix.

The f-string has no placeholders and should be a regular string for better performance.

-        self._logger.warning(f"Retrieve the user id")
+        self._logger.warning("Retrieve the user id")

172-172: Remove unnecessary f-string prefix.

The f-string has no placeholders and should be a regular string for better performance.

-        self._logger.warning(f"Get the claims from the token manager")
+        self._logger.warning("Get the claims from the token manager")

176-176: Remove unnecessary f-string prefix.

The f-string has no placeholders and should be a regular string for better performance.

-        self._logger.warning(f"Return the claims")
+        self._logger.warning("Return the claims")

184-184: Use underscore for unused exception variable.

The exception variable is not used and should be replaced with underscore to follow Python conventions.

-        except Exception as e:
+        except Exception:
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a330e7f and 3db423b.

📒 Files selected for processing (3)
  • kinde_sdk/auth/oauth.py (1 hunks)
  • kinde_sdk/core/helpers.py (1 hunks)
  • kinde_sdk/management/api/connections_api.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
kinde_sdk/auth/oauth.py (1)
Learnt from: brettchaldecott
PR: kinde-oss/kinde-python-sdk#83
File: kinde_flask/examples/example_app.py:25-44
Timestamp: 2025-07-03T09:38:46.133Z
Learning: The kinde_flask framework automatically creates and registers standard OAuth routes (/login, /logout, /callback, /register, /user) at runtime when the OAuth instance is initialized with a Flask app. These routes do not need to be manually defined in application code.
🧬 Code Graph Analysis (1)
kinde_sdk/management/api/connections_api.py (5)
kinde_sdk/model/success_response.py (1)
  • SuccessResponse (27-89)
kinde_sdk/api_client.py (1)
  • ApiResponse (802-818)
kinde_sdk/management/api_client.py (4)
  • response_deserialize (286-334)
  • select_header_accept (574-587)
  • select_header_content_type (589-602)
  • param_serialize (142-248)
test/test_paths/__init__.py (1)
  • response (53-71)
kinde_sdk/exceptions.py (1)
  • body (115-118)
🪛 Ruff (0.11.9)
kinde_sdk/auth/oauth.py

5-5: typing.List imported but unused

Remove unused import

(F401)


5-5: typing.Tuple imported but unused

Remove unused import

(F401)


5-5: typing.Union imported but unused

Remove unused import

(F401)


6-6: urllib.parse.urlparse imported but unused

Remove unused import

(F401)


6-6: urllib.parse.quote imported but unused

Remove unused import

(F401)


13-13: .enums.GrantType imported but unused

Remove unused import: .enums.GrantType

(F401)


15-15: kinde_sdk.core.helpers.base64_url_encode imported but unused

Remove unused import: kinde_sdk.core.helpers.base64_url_encode

(F401)


160-160: f-string without any placeholders

Remove extraneous f prefix

(F541)


172-172: f-string without any placeholders

Remove extraneous f prefix

(F541)


176-176: f-string without any placeholders

Remove extraneous f prefix

(F541)


184-184: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


505-505: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

kinde_sdk/core/helpers.py

153-153: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


503-507: Use return any(role.get("code") == role_code for role in roles) instead of for loop

Replace with return any(role.get("code") == role_code for role in roles)

(SIM110)

kinde_sdk/management/api/connections_api.py

15-15: warnings imported but unused

Remove unused import: warnings

(F401)

🪛 GitHub Check: codecov/patch
kinde_sdk/auth/oauth.py

[warning] 60-60: kinde_sdk/auth/oauth.py#L60
Added line #L60 was not covered by tests


[warning] 67-68: kinde_sdk/auth/oauth.py#L67-L68
Added lines #L67 - L68 were not covered by tests


[warning] 78-78: kinde_sdk/auth/oauth.py#L78
Added line #L78 was not covered by tests


[warning] 101-101: kinde_sdk/auth/oauth.py#L101
Added line #L101 was not covered by tests


[warning] 104-104: kinde_sdk/auth/oauth.py#L104
Added line #L104 was not covered by tests


[warning] 110-110: kinde_sdk/auth/oauth.py#L110
Added line #L110 was not covered by tests


[warning] 113-113: kinde_sdk/auth/oauth.py#L113
Added line #L113 was not covered by tests


[warning] 116-116: kinde_sdk/auth/oauth.py#L116
Added line #L116 was not covered by tests


[warning] 119-119: kinde_sdk/auth/oauth.py#L119
Added line #L119 was not covered by tests


[warning] 122-122: kinde_sdk/auth/oauth.py#L122
Added line #L122 was not covered by tests


[warning] 135-137: kinde_sdk/auth/oauth.py#L135-L137
Added lines #L135 - L137 were not covered by tests


[warning] 139-140: kinde_sdk/auth/oauth.py#L139-L140
Added lines #L139 - L140 were not covered by tests


[warning] 143-144: kinde_sdk/auth/oauth.py#L143-L144
Added lines #L143 - L144 were not covered by tests


[warning] 160-161: kinde_sdk/auth/oauth.py#L160-L161
Added lines #L160 - L161 were not covered by tests


[warning] 163-163: kinde_sdk/auth/oauth.py#L163
Added line #L163 was not covered by tests


[warning] 166-167: kinde_sdk/auth/oauth.py#L166-L167
Added lines #L166 - L167 were not covered by tests


[warning] 169-169: kinde_sdk/auth/oauth.py#L169
Added line #L169 was not covered by tests


[warning] 172-173: kinde_sdk/auth/oauth.py#L172-L173
Added lines #L172 - L173 were not covered by tests


[warning] 175-177: kinde_sdk/auth/oauth.py#L175-L177
Added lines #L175 - L177 were not covered by tests


[warning] 184-188: kinde_sdk/auth/oauth.py#L184-L188
Added lines #L184 - L188 were not covered by tests


[warning] 212-215: kinde_sdk/auth/oauth.py#L212-L215
Added lines #L212 - L215 were not covered by tests


[warning] 235-235: kinde_sdk/auth/oauth.py#L235
Added line #L235 was not covered by tests


[warning] 238-238: kinde_sdk/auth/oauth.py#L238
Added line #L238 was not covered by tests


[warning] 262-262: kinde_sdk/auth/oauth.py#L262
Added line #L262 was not covered by tests


[warning] 271-271: kinde_sdk/auth/oauth.py#L271
Added line #L271 was not covered by tests


[warning] 279-279: kinde_sdk/auth/oauth.py#L279
Added line #L279 was not covered by tests

🪛 Flake8 (7.2.0)
kinde_sdk/auth/oauth.py

[error] 5-5: 'typing.List' imported but unused

(F401)


[error] 5-5: 'typing.Tuple' imported but unused

(F401)


[error] 5-5: 'typing.Union' imported but unused

(F401)


[error] 6-6: 'urllib.parse.urlparse' imported but unused

(F401)


[error] 6-6: 'urllib.parse.quote' imported but unused

(F401)


[error] 13-13: '.enums.GrantType' imported but unused

(F401)


[error] 15-15: 'kinde_sdk.core.helpers.base64_url_encode' imported but unused

(F401)


[error] 23-23: expected 2 blank lines, found 1

(E302)


[error] 160-160: f-string is missing placeholders

(F541)


[error] 172-172: f-string is missing placeholders

(F541)


[error] 176-176: f-string is missing placeholders

(F541)


[error] 184-184: local variable 'e' is assigned to but never used

(F841)


[error] 278-278: continuation line under-indented for visual indent

(E128)

kinde_sdk/core/helpers.py

[error] 13-13: expected 2 blank lines, found 1

(E302)


[error] 25-25: expected 2 blank lines, found 1

(E302)


[error] 40-40: expected 2 blank lines, found 1

(E302)


[error] 71-71: expected 2 blank lines, found 1

(E302)


[error] 124-124: expected 2 blank lines, found 1

(E302)


[error] 155-155: expected 2 blank lines, found 1

(E302)


[error] 172-172: expected 2 blank lines, found 1

(E302)


[error] 225-225: expected 2 blank lines, found 1

(E302)


[error] 278-278: expected 2 blank lines, found 1

(E302)


[error] 332-332: expected 2 blank lines, found 1

(E302)


[error] 397-397: expected 2 blank lines, found 1

(E302)


[error] 397-397: unexpected spaces around keyword / parameter equals

(E251)


[error] 397-397: unexpected spaces around keyword / parameter equals

(E251)


[error] 423-423: expected 2 blank lines, found 1

(E302)


[error] 423-423: unexpected spaces around keyword / parameter equals

(E251)


[error] 423-423: unexpected spaces around keyword / parameter equals

(E251)


[error] 484-484: expected 2 blank lines, found 1

(E302)


[error] 484-484: unexpected spaces around keyword / parameter equals

(E251)


[error] 484-484: unexpected spaces around keyword / parameter equals

(E251)


[error] 514-514: expected 2 blank lines, found 1

(E302)


[error] 514-514: unexpected spaces around keyword / parameter equals

(E251)


[error] 514-514: unexpected spaces around keyword / parameter equals

(E251)


[error] 566-566: expected 2 blank lines, found 1

(E302)


[error] 588-588: expected 2 blank lines, found 1

(E302)


[error] 610-610: expected 2 blank lines, found 1

(E302)


[error] 619-619: expected 2 blank lines, found 1

(E302)


[error] 631-631: expected 2 blank lines, found 1

(E302)


[error] 640-640: expected 2 blank lines, found 1

(E302)


[error] 656-656: expected 2 blank lines, found 1

(E302)


[error] 670-670: expected 2 blank lines, found 1

(E302)


[error] 684-684: expected 2 blank lines, found 1

(E302)

kinde_sdk/management/api/connections_api.py

[error] 15-15: 'warnings' imported but unused

(F401)


[error] 46-46: too many blank lines (2)

(E303)


[error] 89-89: at least two spaces before inline comment

(E261)


[error] 116-116: too many blank lines (2)

(E303)


[error] 159-159: at least two spaces before inline comment

(E261)


[error] 186-186: too many blank lines (2)

(E303)


[error] 229-229: at least two spaces before inline comment

(E261)


[error] 239-239: local variable '_response_types_map' is assigned to but never used

(F841)


[error] 252-252: too many blank lines (2)

(E303)


[error] 284-284: too many blank lines (2)

(E303)


[error] 329-329: too many blank lines (4)

(E303)


[error] 372-372: at least two spaces before inline comment

(E261)


[error] 400-400: too many blank lines (2)

(E303)


[error] 443-443: at least two spaces before inline comment

(E261)


[error] 471-471: too many blank lines (2)

(E303)


[error] 514-514: at least two spaces before inline comment

(E261)


[error] 524-524: local variable '_response_types_map' is assigned to but never used

(F841)


[error] 538-538: too many blank lines (2)

(E303)


[error] 570-570: too many blank lines (2)

(E303)


[error] 579-579: too many blank lines (2)

(E303)


[error] 602-602: too many blank lines (4)

(E303)


[error] 645-645: at least two spaces before inline comment

(E261)


[error] 672-672: too many blank lines (2)

(E303)


[error] 715-715: at least two spaces before inline comment

(E261)


[error] 742-742: too many blank lines (2)

(E303)


[error] 785-785: at least two spaces before inline comment

(E261)


[error] 795-795: local variable '_response_types_map' is assigned to but never used

(F841)


[error] 808-808: too many blank lines (2)

(E303)


[error] 840-840: too many blank lines (2)

(E303)


[error] 849-849: too many blank lines (2)

(E303)


[error] 872-872: too many blank lines (4)

(E303)


[error] 924-924: at least two spaces before inline comment

(E261)


[error] 954-954: too many blank lines (2)

(E303)


[error] 1006-1006: at least two spaces before inline comment

(E261)


[error] 1036-1036: too many blank lines (2)

(E303)


[error] 1088-1088: at least two spaces before inline comment

(E261)


[error] 1101-1101: local variable '_response_types_map' is assigned to but never used

(F841)


[error] 1114-1114: too many blank lines (2)

(E303)


[error] 1163-1163: too many blank lines (2)

(E303)


[error] 1173-1173: too many blank lines (2)

(E303)


[error] 1196-1196: too many blank lines (4)

(E303)


[error] 1242-1242: at least two spaces before inline comment

(E261)


[error] 1271-1271: too many blank lines (2)

(E303)


[error] 1317-1317: at least two spaces before inline comment

(E261)


[error] 1346-1346: too many blank lines (2)

(E303)


[error] 1392-1392: at least two spaces before inline comment

(E261)


[error] 1403-1403: local variable '_response_types_map' is assigned to but never used

(F841)


[error] 1417-1417: too many blank lines (2)

(E303)


[error] 1452-1452: too many blank lines (2)

(E303)


[error] 1497-1497: too many blank lines (4)

(E303)


[error] 1543-1543: at least two spaces before inline comment

(E261)


[error] 1572-1572: too many blank lines (2)

(E303)


[error] 1618-1618: at least two spaces before inline comment

(E261)


[error] 1647-1647: too many blank lines (2)

(E303)


[error] 1693-1693: at least two spaces before inline comment

(E261)


[error] 1704-1704: local variable '_response_types_map' is assigned to but never used

(F841)


[error] 1718-1718: too many blank lines (2)

(E303)


[error] 1753-1753: too many blank lines (2)

(E303)

🔇 Additional comments (4)
kinde_sdk/management/api/connections_api.py (1)

33-1796: LGTM! Well-structured API client implementation.

The ConnectionsApi class follows excellent patterns for an auto-generated API client:

  • Comprehensive CRUD operations with proper HTTP methods (POST, DELETE, GET, PUT, PATCH)
  • Three method variants per operation: standard deserialized response, detailed HTTP info, and raw response
  • Robust input validation using Pydantic's @validate_call decorator
  • Consistent authentication using kindeBearerAuth across all endpoints
  • Proper error handling with comprehensive response type mapping
  • Clean request serialization with dedicated methods for each operation

The implementation provides excellent flexibility for different use cases while maintaining consistency and type safety.

kinde_sdk/auth/oauth.py (1)

23-630: Excellent OAuth 2.0 implementation with comprehensive security features.

This OAuth class demonstrates solid architecture with:

  • Complete PKCE flow implementation for enhanced security
  • Proper state and nonce handling to prevent CSRF attacks
  • Comprehensive error handling with specific exception types
  • Framework-agnostic design supporting multiple web frameworks
  • Extensive OAuth parameter support for various authentication flows
  • Clean separation of concerns between authentication, session management, and storage

The implementation follows OAuth 2.0 and OpenID Connect best practices while providing a flexible, extensible foundation for the SDK.

kinde_sdk/core/helpers.py (2)

172-564: Excellent error handling patterns throughout API helper functions.

The helper functions demonstrate consistent, robust error handling with:

  • Proper exception type separation (ValueError for token issues, RequestException for network issues)
  • Detailed error message extraction from API responses including error codes and descriptions
  • Optional logger parameters providing flexibility while maintaining good observability
  • Graceful fallbacks for non-critical operations like feature flags
  • Clear error propagation allowing calling code to handle failures appropriately

This pattern creates a reliable foundation for API interactions throughout the SDK.


13-69: Solid cryptographic utilities following security best practices.

The cryptographic functions demonstrate good security practices:

  • Using secrets.token_urlsafe() for cryptographically secure random string generation
  • Proper PKCE implementation following RFC 7636 with SHA-256 hashing
  • Standard-compliant base64url encoding without padding
  • Appropriate error handling with fallback mechanisms

These utilities provide a secure foundation for OAuth 2.0 flows and token operations.

- Change verbose logging statements from warning to debug level
- Reduce log noise in production by using appropriate log levels
- Keep debug information available for troubleshooting when needed
- Affects authentication flow logging in is_authenticated() and get_user_info() methods
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (6)
kinde_sdk/auth/oauth.py (6)

5-15: Clean up unused imports to improve code quality.

Several imports are unused and should be removed based on static analysis.

Apply this diff to remove unused imports:

-from typing import Any, Dict, List, Optional, Tuple, Union
+from typing import Any, Dict, Optional
-from urllib.parse import urlencode, urlparse, quote
+from urllib.parse import urlencode

-from .enums import GrantType, IssuerRouteTypes, PromptTypes
+from .enums import IssuerRouteTypes, PromptTypes
-from kinde_sdk.core.helpers import generate_random_string, base64_url_encode, generate_pkce_pair, get_user_details as helper_get_user_details
+from kinde_sdk.core.helpers import generate_random_string, generate_pkce_pair, get_user_details as helper_get_user_details

135-144: Convert debug logging to appropriate level.

The logging statements are using warning level for debug information.

Apply this diff to use appropriate logging levels:

-        self._logger.debug(f"self._framework: {self._framework}")
+        self._logger.debug(f"self._framework: {self._framework}")
         user_id = self._framework.get_user_id()
-        self._logger.debug(f"user_id: {user_id}")
+        self._logger.debug(f"user_id: {user_id}")
         if not user_id:
-            self._logger.debug("No user ID found in session")
+            self._logger.debug("No user ID found in session")
             return False
             
         # Check authentication using session manager
-        self._logger.debug(f"self._session_manager: {self._session_manager}")
+        self._logger.debug(f"self._session_manager: {self._session_manager}")

486-486: Convert debug logging to appropriate level.

This appears to be debug logging that should use debug level instead of warning.

-            self._logger.warning(f"stored_state: {stored_state}, state: {state}")
+            self._logger.debug(f"stored_state: {stored_state}, state: {state}")

503-505: Use proper exception chaining.

When re-raising exceptions, use from e to maintain the exception chain for better debugging.

         except Exception as e:
             self._logger.error(f"Token exchange failed: {str(e)}")
-            raise KindeTokenException(f"Failed to exchange code for tokens: {str(e)}")
+            raise KindeTokenException(f"Failed to exchange code for tokens: {str(e)}") from e

568-572: Convert debug logging to appropriate level.

These warning logs appear to be for debugging purposes and should use the appropriate log level.

-        self._logger.warning(f"[Exchange code for tokens] [{self.token_url}] [{data}]")
+        self._logger.debug(f"[Exchange code for tokens] [{self.token_url}] [{data}]")

         response = requests.post(self.token_url, data=data)
-        self._logger.warning(f"[Exchange code for tokens] [{response.status_code}] [{response.text}]")
+        self._logger.debug(f"[Exchange code for tokens] [{response.status_code}] [{response.text}]")

628-630: Use proper exception chaining.

Similar to the previous exception handling issue, use from e for proper exception chaining.

         except Exception as e:
             self._logger.error(f"Error retrieving tokens: {str(e)}")
-            raise ValueError(f"Failed to retrieve tokens: {str(e)}")
+            raise ValueError(f"Failed to retrieve tokens: {str(e)}") from e
🧹 Nitpick comments (3)
kinde_sdk/auth/oauth.py (3)

160-177: Remove unnecessary f-string prefixes and improve logging.

Several f-strings don't have placeholders and logging could be improved.

Apply this diff to clean up the logging:

-        self._logger.debug(f"Retrieve the user id")
+        self._logger.debug("Retrieve the user id")
         user_id = self._framework.get_user_id()
         if not user_id:
             raise KindeConfigurationException("No user ID found in session")
             
         # Get token manager for the user
         self._logger.debug(f"User id: {user_id} retrieve the token for the user id")
         token_manager = self._session_manager.get_token_manager(user_id)
         if not token_manager:
             raise KindeConfigurationException("No token manager found for user")
             
         # Get claims from token manager
-        self._logger.debug(f"Get the claims from the token manager")
+        self._logger.debug("Get the claims from the token manager")
         claims = token_manager.get_claims()
         if not claims:
             raise KindeConfigurationException("No user claims found")
-        self._logger.debug(f"Return the claims")
+        self._logger.debug("Return the claims")
         return claims

184-188: Remove unused exception variable.

The exception variable e is assigned but never used in the except block.

Apply this diff to remove the unused variable:

-        except Exception as e:
+        except Exception:
             self.auth_url = f"{self.host}/oauth2/auth"
             self.token_url = f"{self.host}/oauth2/token"
             self.logout_url = f"{self.host}/logout"
             self.userinfo_url = f"{self.host}/oauth2/userinfo"

23-36: Consider adding type hints for better code documentation.

The app parameter lacks specific typing, which could improve IDE support and code clarity.

Consider adding a more specific type hint or using a protocol for the app parameter:

 class OAuth:
     def __init__(
         self,
         client_id: Optional[str] = None,
         client_secret: Optional[str] = None,
         redirect_uri: Optional[str] = None,
         config_file: Optional[str] = None,
         storage_config: Optional[Dict[str, Any]] = None,
         framework: Optional[str] = None,
         audience: Optional[str] = None,
         host: Optional[str] = None,
         state: Optional[str] = None,
-        app: Optional[Any] = None,
+        app: Optional[Any] = None,  # Consider: Union[Flask, FastAPI, Any] or create a Protocol
     ):
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3db423b and b52a07c.

📒 Files selected for processing (1)
  • kinde_sdk/auth/oauth.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
kinde_sdk/auth/oauth.py (1)
Learnt from: brettchaldecott
PR: kinde-oss/kinde-python-sdk#83
File: kinde_flask/examples/example_app.py:25-44
Timestamp: 2025-07-03T09:38:46.133Z
Learning: The kinde_flask framework automatically creates and registers standard OAuth routes (/login, /logout, /callback, /register, /user) at runtime when the OAuth instance is initialized with a Flask app. These routes do not need to be manually defined in application code.
🪛 Ruff (0.11.9)
kinde_sdk/auth/oauth.py

5-5: typing.List imported but unused

Remove unused import

(F401)


5-5: typing.Tuple imported but unused

Remove unused import

(F401)


5-5: typing.Union imported but unused

Remove unused import

(F401)


6-6: urllib.parse.urlparse imported but unused

Remove unused import

(F401)


6-6: urllib.parse.quote imported but unused

Remove unused import

(F401)


13-13: .enums.GrantType imported but unused

Remove unused import: .enums.GrantType

(F401)


15-15: kinde_sdk.core.helpers.base64_url_encode imported but unused

Remove unused import: kinde_sdk.core.helpers.base64_url_encode

(F401)


160-160: f-string without any placeholders

Remove extraneous f prefix

(F541)


172-172: f-string without any placeholders

Remove extraneous f prefix

(F541)


176-176: f-string without any placeholders

Remove extraneous f prefix

(F541)


184-184: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)


505-505: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🪛 GitHub Check: codecov/patch
kinde_sdk/auth/oauth.py

[warning] 60-60: kinde_sdk/auth/oauth.py#L60
Added line #L60 was not covered by tests


[warning] 67-68: kinde_sdk/auth/oauth.py#L67-L68
Added lines #L67 - L68 were not covered by tests


[warning] 78-78: kinde_sdk/auth/oauth.py#L78
Added line #L78 was not covered by tests


[warning] 101-101: kinde_sdk/auth/oauth.py#L101
Added line #L101 was not covered by tests


[warning] 104-104: kinde_sdk/auth/oauth.py#L104
Added line #L104 was not covered by tests


[warning] 110-110: kinde_sdk/auth/oauth.py#L110
Added line #L110 was not covered by tests


[warning] 113-113: kinde_sdk/auth/oauth.py#L113
Added line #L113 was not covered by tests


[warning] 116-116: kinde_sdk/auth/oauth.py#L116
Added line #L116 was not covered by tests


[warning] 119-119: kinde_sdk/auth/oauth.py#L119
Added line #L119 was not covered by tests


[warning] 122-122: kinde_sdk/auth/oauth.py#L122
Added line #L122 was not covered by tests


[warning] 135-137: kinde_sdk/auth/oauth.py#L135-L137
Added lines #L135 - L137 were not covered by tests


[warning] 139-140: kinde_sdk/auth/oauth.py#L139-L140
Added lines #L139 - L140 were not covered by tests


[warning] 143-144: kinde_sdk/auth/oauth.py#L143-L144
Added lines #L143 - L144 were not covered by tests


[warning] 160-161: kinde_sdk/auth/oauth.py#L160-L161
Added lines #L160 - L161 were not covered by tests


[warning] 163-163: kinde_sdk/auth/oauth.py#L163
Added line #L163 was not covered by tests


[warning] 166-167: kinde_sdk/auth/oauth.py#L166-L167
Added lines #L166 - L167 were not covered by tests


[warning] 169-169: kinde_sdk/auth/oauth.py#L169
Added line #L169 was not covered by tests


[warning] 172-173: kinde_sdk/auth/oauth.py#L172-L173
Added lines #L172 - L173 were not covered by tests


[warning] 175-177: kinde_sdk/auth/oauth.py#L175-L177
Added lines #L175 - L177 were not covered by tests


[warning] 184-188: kinde_sdk/auth/oauth.py#L184-L188
Added lines #L184 - L188 were not covered by tests


[warning] 212-215: kinde_sdk/auth/oauth.py#L212-L215
Added lines #L212 - L215 were not covered by tests


[warning] 235-235: kinde_sdk/auth/oauth.py#L235
Added line #L235 was not covered by tests


[warning] 238-238: kinde_sdk/auth/oauth.py#L238
Added line #L238 was not covered by tests


[warning] 262-262: kinde_sdk/auth/oauth.py#L262
Added line #L262 was not covered by tests


[warning] 271-271: kinde_sdk/auth/oauth.py#L271
Added line #L271 was not covered by tests


[warning] 279-279: kinde_sdk/auth/oauth.py#L279
Added line #L279 was not covered by tests

🪛 Flake8 (7.2.0)
kinde_sdk/auth/oauth.py

[error] 5-5: 'typing.List' imported but unused

(F401)


[error] 5-5: 'typing.Tuple' imported but unused

(F401)


[error] 5-5: 'typing.Union' imported but unused

(F401)


[error] 6-6: 'urllib.parse.urlparse' imported but unused

(F401)


[error] 6-6: 'urllib.parse.quote' imported but unused

(F401)


[error] 13-13: '.enums.GrantType' imported but unused

(F401)


[error] 15-15: 'kinde_sdk.core.helpers.base64_url_encode' imported but unused

(F401)


[error] 23-23: expected 2 blank lines, found 1

(E302)


[error] 160-160: f-string is missing placeholders

(F541)


[error] 172-172: f-string is missing placeholders

(F541)


[error] 176-176: f-string is missing placeholders

(F541)


[error] 184-184: local variable 'e' is assigned to but never used

(F841)


[error] 278-278: continuation line under-indented for visual indent

(E128)

🔇 Additional comments (1)
kinde_sdk/auth/oauth.py (1)

310-313: No action needed: async PKCE generation verified

The helper generate_pkce_pair is declared as
async def generate_pkce_pair(length: int = 52) -> Dict[str, str]
in kinde_sdk/core/helpers.py:40, so using await generate_pkce_pair(52) is correct.

- Add 'from e' to KindeTokenException to preserve original exception context
- Improve error traceability for debugging token exchange failures
- Follow Python best practices for exception chaining
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
kinde_sdk/auth/oauth.py (3)

5-15: Remove unused imports to clean up the code.

Several imports are not used in the code and should be removed for cleaner code.


135-144: Convert debug logging to appropriate level.

The warning logs appear to be for debugging purposes and should use the appropriate log level.


568-572: Convert debug logging to appropriate level.

These warning logs appear to be for debugging purposes and should use the appropriate log level.

🧹 Nitpick comments (3)
kinde_sdk/auth/oauth.py (3)

23-23: Add proper spacing before class definition.

The class definition should have 2 blank lines before it according to PEP 8.

+

 class OAuth:

160-177: Fix f-string formatting issues.

Several f-strings don't have placeholders and should be converted to regular strings.

-        self._logger.debug(f"Retrieve the user id")
+        self._logger.debug("Retrieve the user id")
         user_id = self._framework.get_user_id()
         if not user_id:
             raise KindeConfigurationException("No user ID found in session")
             
         # Get token manager for the user
         self._logger.debug(f"User id: {user_id} retrieve the token for the user id")
         token_manager = self._session_manager.get_token_manager(user_id)
         if not token_manager:
             raise KindeConfigurationException("No token manager found for user")
             
         # Get claims from token manager
-        self._logger.debug(f"Get the claims from the token manager")
+        self._logger.debug("Get the claims from the token manager")
         claims = token_manager.get_claims()
         if not claims:
             raise KindeConfigurationException("No user claims found")
-        self._logger.debug(f"Return the claims")
+        self._logger.debug("Return the claims")
         return claims

179-188: Remove unused variable in exception handling.

The exception variable e is assigned but never used.

         try:
             self._fetch_openid_configuration()
-        except Exception as e:
+        except Exception:
             self.auth_url = f"{self.host}/oauth2/auth"
             self.token_url = f"{self.host}/oauth2/token"
             self.logout_url = f"{self.host}/logout"
             self.userinfo_url = f"{self.host}/oauth2/userinfo"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b52a07c and 8249c85.

📒 Files selected for processing (1)
  • kinde_sdk/auth/oauth.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
kinde_sdk/auth/oauth.py (1)
Learnt from: brettchaldecott
PR: kinde-oss/kinde-python-sdk#83
File: kinde_flask/examples/example_app.py:25-44
Timestamp: 2025-07-03T09:38:46.133Z
Learning: The kinde_flask framework automatically creates and registers standard OAuth routes (/login, /logout, /callback, /register, /user) at runtime when the OAuth instance is initialized with a Flask app. These routes do not need to be manually defined in application code.
🪛 Ruff (0.11.9)
kinde_sdk/auth/oauth.py

5-5: typing.List imported but unused

Remove unused import

(F401)


5-5: typing.Tuple imported but unused

Remove unused import

(F401)


5-5: typing.Union imported but unused

Remove unused import

(F401)


6-6: urllib.parse.urlparse imported but unused

Remove unused import

(F401)


6-6: urllib.parse.quote imported but unused

Remove unused import

(F401)


13-13: .enums.GrantType imported but unused

Remove unused import: .enums.GrantType

(F401)


15-15: kinde_sdk.core.helpers.base64_url_encode imported but unused

Remove unused import: kinde_sdk.core.helpers.base64_url_encode

(F401)


160-160: f-string without any placeholders

Remove extraneous f prefix

(F541)


172-172: f-string without any placeholders

Remove extraneous f prefix

(F541)


176-176: f-string without any placeholders

Remove extraneous f prefix

(F541)


184-184: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

🪛 GitHub Check: codecov/patch
kinde_sdk/auth/oauth.py

[warning] 60-60: kinde_sdk/auth/oauth.py#L60
Added line #L60 was not covered by tests


[warning] 67-68: kinde_sdk/auth/oauth.py#L67-L68
Added lines #L67 - L68 were not covered by tests


[warning] 78-78: kinde_sdk/auth/oauth.py#L78
Added line #L78 was not covered by tests


[warning] 101-101: kinde_sdk/auth/oauth.py#L101
Added line #L101 was not covered by tests


[warning] 104-104: kinde_sdk/auth/oauth.py#L104
Added line #L104 was not covered by tests


[warning] 110-110: kinde_sdk/auth/oauth.py#L110
Added line #L110 was not covered by tests


[warning] 113-113: kinde_sdk/auth/oauth.py#L113
Added line #L113 was not covered by tests


[warning] 116-116: kinde_sdk/auth/oauth.py#L116
Added line #L116 was not covered by tests


[warning] 119-119: kinde_sdk/auth/oauth.py#L119
Added line #L119 was not covered by tests


[warning] 122-122: kinde_sdk/auth/oauth.py#L122
Added line #L122 was not covered by tests


[warning] 135-137: kinde_sdk/auth/oauth.py#L135-L137
Added lines #L135 - L137 were not covered by tests


[warning] 139-140: kinde_sdk/auth/oauth.py#L139-L140
Added lines #L139 - L140 were not covered by tests


[warning] 143-144: kinde_sdk/auth/oauth.py#L143-L144
Added lines #L143 - L144 were not covered by tests


[warning] 160-161: kinde_sdk/auth/oauth.py#L160-L161
Added lines #L160 - L161 were not covered by tests


[warning] 163-163: kinde_sdk/auth/oauth.py#L163
Added line #L163 was not covered by tests


[warning] 166-167: kinde_sdk/auth/oauth.py#L166-L167
Added lines #L166 - L167 were not covered by tests


[warning] 169-169: kinde_sdk/auth/oauth.py#L169
Added line #L169 was not covered by tests


[warning] 172-173: kinde_sdk/auth/oauth.py#L172-L173
Added lines #L172 - L173 were not covered by tests


[warning] 175-177: kinde_sdk/auth/oauth.py#L175-L177
Added lines #L175 - L177 were not covered by tests


[warning] 184-188: kinde_sdk/auth/oauth.py#L184-L188
Added lines #L184 - L188 were not covered by tests


[warning] 212-215: kinde_sdk/auth/oauth.py#L212-L215
Added lines #L212 - L215 were not covered by tests


[warning] 235-235: kinde_sdk/auth/oauth.py#L235
Added line #L235 was not covered by tests


[warning] 238-238: kinde_sdk/auth/oauth.py#L238
Added line #L238 was not covered by tests


[warning] 262-262: kinde_sdk/auth/oauth.py#L262
Added line #L262 was not covered by tests


[warning] 271-271: kinde_sdk/auth/oauth.py#L271
Added line #L271 was not covered by tests


[warning] 279-279: kinde_sdk/auth/oauth.py#L279
Added line #L279 was not covered by tests

🪛 Flake8 (7.2.0)
kinde_sdk/auth/oauth.py

[error] 5-5: 'typing.List' imported but unused

(F401)


[error] 5-5: 'typing.Tuple' imported but unused

(F401)


[error] 5-5: 'typing.Union' imported but unused

(F401)


[error] 6-6: 'urllib.parse.urlparse' imported but unused

(F401)


[error] 6-6: 'urllib.parse.quote' imported but unused

(F401)


[error] 13-13: '.enums.GrantType' imported but unused

(F401)


[error] 15-15: 'kinde_sdk.core.helpers.base64_url_encode' imported but unused

(F401)


[error] 23-23: expected 2 blank lines, found 1

(E302)


[error] 160-160: f-string is missing placeholders

(F541)


[error] 172-172: f-string is missing placeholders

(F541)


[error] 176-176: f-string is missing placeholders

(F541)


[error] 184-184: local variable 'e' is assigned to but never used

(F841)


[error] 278-278: continuation line under-indented for visual indent

(E128)

🔇 Additional comments (9)
kinde_sdk/auth/oauth.py (9)

24-94: LGTM! Well-structured constructor with comprehensive configuration handling.

The constructor properly handles multiple configuration sources (parameters, environment variables, config files) and validates required settings. The fallback logic for storage configuration is well-implemented.


95-123: LGTM! Proper framework initialization pattern.

The method correctly initializes framework-specific components, sets up middleware, and creates appropriate storage instances. The error handling for missing framework configuration is appropriate.


190-216: LGTM! Proper OpenID configuration fetching with fallback.

The method correctly fetches OpenID configuration from the well-known endpoint and falls back to default URLs when the configuration is unavailable. The error handling is appropriate.


217-333: LGTM! Comprehensive URL generation with excellent parameter handling.

The method properly handles all OAuth parameters, generates secure PKCE pairs, manages state and nonce, and supports both login and registration flows. The parameter mapping and validation logic is well-implemented.


335-371: LGTM! Proper login URL generation with framework validation.

The method correctly validates framework presence and delegates to the comprehensive URL generation method. The parameter passing is clean and efficient.


373-414: LGTM! Appropriate registration flow with proper prompt setting.

The method correctly sets the prompt to 'create' for registration flows when not specified, ensuring the proper user experience for new user registration.


416-469: LGTM! Comprehensive logout handling with proper cleanup.

The method properly handles session cleanup, retrieves ID tokens for logout hints, and generates appropriate logout URLs with all necessary parameters.


471-540: LGTM! Robust OAuth redirect handling with proper security validation.

The method correctly validates state parameters, handles PKCE flow, exchanges codes for tokens, and manages user session data. The error handling and cleanup logic are well-implemented.


577-630: LGTM! Comprehensive token retrieval with proper error handling.

The method correctly retrieves tokens from the token manager, handles various token types, and calculates expiration times. The error handling and validation are appropriate.

- Change verbose logging in exchange_code_for_tokens from warning to debug level
- Reduce log noise in production by using appropriate log levels for token exchange details
- Keep sensitive token exchange information at debug level for security
- Affects logging of token URL, request data, and response details
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
kinde_sdk/auth/oauth.py (1)

5-15: Remove unused imports.

Several imports are not used in the code and should be removed for cleaner code.

-from typing import Any, Dict, List, Optional, Tuple, Union
+from typing import Any, Dict, Optional
-from urllib.parse import urlencode, urlparse, quote
+from urllib.parse import urlencode

 from .user_session import UserSession
 from kinde_sdk.core.storage.storage_manager import StorageManager
 from kinde_sdk.core.storage.storage_factory import StorageFactory
 from kinde_sdk.core.framework.framework_factory import FrameworkFactory
 from .config_loader import load_config
-from .enums import GrantType, IssuerRouteTypes, PromptTypes
+from .enums import IssuerRouteTypes, PromptTypes
 from .login_options import LoginOptions
-from kinde_sdk.core.helpers import generate_random_string, base64_url_encode, generate_pkce_pair, get_user_details as helper_get_user_details
+from kinde_sdk.core.helpers import generate_random_string, generate_pkce_pair, get_user_details as helper_get_user_details
🧹 Nitpick comments (3)
kinde_sdk/auth/oauth.py (3)

160-177: Remove unnecessary f-string prefixes.

The following lines have f-string prefixes without any placeholders.

-        self._logger.debug(f"Retrieve the user id")
+        self._logger.debug("Retrieve the user id")
         user_id = self._framework.get_user_id()
         if not user_id:
             raise KindeConfigurationException("No user ID found in session")
             
         # Get token manager for the user
         self._logger.debug(f"User id: {user_id} retrieve the token for the user id")
         token_manager = self._session_manager.get_token_manager(user_id)
         if not token_manager:
             raise KindeConfigurationException("No token manager found for user")
             
         # Get claims from token manager
-        self._logger.debug(f"Get the claims from the token manager")
+        self._logger.debug("Get the claims from the token manager")
         claims = token_manager.get_claims()
         if not claims:
             raise KindeConfigurationException("No user claims found")
-        self._logger.debug(f"Return the claims")
+        self._logger.debug("Return the claims")

179-189: Remove unused exception variable.

The exception variable e is not used in the except block.

         # Attempt to fetch OpenID Configuration first
         try:
             self._fetch_openid_configuration()
-        except Exception as e:
+        except Exception:
             self.auth_url = f"{self.host}/oauth2/auth"
             self.token_url = f"{self.host}/oauth2/token"
             self.logout_url = f"{self.host}/logout"
             self.userinfo_url = f"{self.host}/oauth2/userinfo"

194-195: Remove redundant import statement.

The requests module is already imported at the top of the file.

-        import requests
-        
         # Construct the OpenID Configuration URL
         openid_config_url = f"{self.host}/.well-known/openid-configuration"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8249c85 and d78901e.

📒 Files selected for processing (1)
  • kinde_sdk/auth/oauth.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
kinde_sdk/auth/oauth.py (1)
Learnt from: brettchaldecott
PR: kinde-oss/kinde-python-sdk#83
File: kinde_flask/examples/example_app.py:25-44
Timestamp: 2025-07-03T09:38:46.133Z
Learning: The kinde_flask framework automatically creates and registers standard OAuth routes (/login, /logout, /callback, /register, /user) at runtime when the OAuth instance is initialized with a Flask app. These routes do not need to be manually defined in application code.
🪛 Ruff (0.11.9)
kinde_sdk/auth/oauth.py

5-5: typing.List imported but unused

Remove unused import

(F401)


5-5: typing.Tuple imported but unused

Remove unused import

(F401)


5-5: typing.Union imported but unused

Remove unused import

(F401)


6-6: urllib.parse.urlparse imported but unused

Remove unused import

(F401)


6-6: urllib.parse.quote imported but unused

Remove unused import

(F401)


13-13: .enums.GrantType imported but unused

Remove unused import: .enums.GrantType

(F401)


15-15: kinde_sdk.core.helpers.base64_url_encode imported but unused

Remove unused import: kinde_sdk.core.helpers.base64_url_encode

(F401)


160-160: f-string without any placeholders

Remove extraneous f prefix

(F541)


172-172: f-string without any placeholders

Remove extraneous f prefix

(F541)


176-176: f-string without any placeholders

Remove extraneous f prefix

(F541)


184-184: Local variable e is assigned to but never used

Remove assignment to unused variable e

(F841)

🪛 Flake8 (7.2.0)
kinde_sdk/auth/oauth.py

[error] 5-5: 'typing.List' imported but unused

(F401)


[error] 5-5: 'typing.Tuple' imported but unused

(F401)


[error] 5-5: 'typing.Union' imported but unused

(F401)


[error] 6-6: 'urllib.parse.urlparse' imported but unused

(F401)


[error] 6-6: 'urllib.parse.quote' imported but unused

(F401)


[error] 13-13: '.enums.GrantType' imported but unused

(F401)


[error] 15-15: 'kinde_sdk.core.helpers.base64_url_encode' imported but unused

(F401)


[error] 23-23: expected 2 blank lines, found 1

(E302)


[error] 160-160: f-string is missing placeholders

(F541)


[error] 172-172: f-string is missing placeholders

(F541)


[error] 176-176: f-string is missing placeholders

(F541)


[error] 184-184: local variable 'e' is assigned to but never used

(F841)


[error] 278-278: continuation line under-indented for visual indent

(E128)

🔇 Additional comments (5)
kinde_sdk/auth/oauth.py (5)

23-94: Well-structured initialization with proper configuration handling.

The OAuth class initialization properly handles configuration from multiple sources (parameters, environment variables, config files) and sets up the necessary components. The validation of required configurations and storage management setup are implemented correctly.


217-334: Comprehensive OAuth URL generation with proper security measures.

The generate_auth_url method correctly implements OAuth 2.0 authorization URL generation with:

  • Complete parameter mapping for various OAuth flows
  • Proper state and nonce generation for security
  • PKCE support with code challenge generation
  • Flexible parameter handling for different authentication scenarios

335-470: Well-implemented authentication flow methods.

The login, register, and logout methods are properly implemented with:

  • Framework requirement validation
  • Proper async/await usage
  • Comprehensive parameter support through login_options
  • Correct session cleanup in logout with ID token hint handling

471-541: Robust OAuth redirect handling with proper security validation.

The handle_redirect method correctly implements:

  • State parameter validation for CSRF protection
  • PKCE code verifier handling and cleanup
  • Proper token storage and user details retrieval
  • Cleanup of temporary values (state, nonce, code_verifier)

577-630: Comprehensive token retrieval with proper validation.

The get_tokens method correctly:

  • Validates token manager availability
  • Checks for required access token
  • Calculates token expiration
  • Includes all available token types and claims
  • Provides detailed error messages

Brett Chaldecott added 2 commits July 3, 2025 14:01
- Add blank line after imports in FrameworkInterface for PEP 8 compliance
- Add blank line after imports in StorageInterface for PEP 8 compliance
- Fix docstring parameter type in StorageInterface set method from Dict to str
- Remove redundant key parameter documentation in set method
- Replace JavaScript-style getItem() with Python dict get() method
- Replace setItem() with Python dict assignment using []
- Replace removeItem() with Python dict pop() method for safe deletion
- Fix set_flat() method implementation to use proper key-value storage
- Update docstring parameters in set_flat() method to match implementation
- Remove unnecessary blank line at top of file for cleaner formatting
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
kinde_sdk/core/storage/local_storage.py (1)

6-9: LGTM! Dictionary method calls have been fixed.

The previous issues with incorrect method calls (getItem(), setItem(), removeItem(), set()) on dictionary objects have been properly resolved. The implementation now correctly uses:

  • self.storage.get(key) for retrieval
  • self.storage[key] = value for storage
  • self.storage.pop(key, None) for deletion

This addresses all the critical issues identified in the past review comments.

Also applies to: 21-22, 32-32, 43-43, 52-52

🧹 Nitpick comments (2)
kinde_sdk/core/storage/local_storage.py (2)

4-5: Fix PEP 8 formatting issue.

According to PEP 8, there should be 2 blank lines before class definitions.

 from .storage_interface import StorageInterface
+

 class LocalStorage(StorageInterface):

34-43: Fix misleading docstring.

The docstring incorrectly describes the method as storing "data associated with the given key" when it actually stores flat data under a fixed key.

     def set_flat(self, data: str) -> None:
         """
-        Store data associated with the given key.
+        Store flat string data under a reserved key.
         
         Args:
             data (str): The data to store.
         """
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c60383d and 2a34243.

📒 Files selected for processing (1)
  • kinde_sdk/core/storage/local_storage.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
kinde_sdk/core/storage/local_storage.py (3)
kinde_sdk/core/storage/storage_interface.py (4)
  • StorageInterface (6-49)
  • get (8-18)
  • set_flat (32-39)
  • delete (42-49)
kinde_sdk/core/storage/storage_manager.py (3)
  • storage (88-99)
  • get (139-153)
  • delete (185-196)
kinde_sdk/core/storage/memory_storage.py (3)
  • get (10-20)
  • set_flat (32-40)
  • delete (42-50)
🪛 Flake8 (7.2.0)
kinde_sdk/core/storage/local_storage.py

[error] 5-5: expected 2 blank lines, found 1

(E302)

- Change storage factory registration logs from warning to info level
- Change storage type detection logs from warning to info level
- Change fallback storage selection log from warning to info level
- Use appropriate log level for informational messages that are not warnings
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
kinde_sdk/core/storage/storage_factory.py (2)

1-1: Remove unused import

The Optional type is imported but never used in this file.


59-59: Pass required config to create_framework

The call to FrameworkFactory.create_framework() is missing its required config argument.

🧹 Nitpick comments (3)
kinde_sdk/core/storage/storage_factory.py (3)

10-10: Add required blank line before class definition

PEP 8 requires two blank lines before top-level class definitions.

+
 class StorageFactory:

40-41: Use debug level for diagnostic logging

These diagnostic messages about storage type and framework factories are more suitable for debug level logging.

-            logger.info(f"Storage type: {storage_type}")
-            logger.info(f"Framework factories: {cls._framework_factories}")
+            logger.debug(f"Storage type: {storage_type}")
+            logger.debug(f"Framework factories: {cls._framework_factories}")

26-68: Consider refactoring to reduce complexity

The method has 7 return statements which could be simplified for better readability. Consider consolidating the logic into fewer return paths.

However, the overall factory pattern implementation is solid with proper error handling and fallback mechanisms.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a34243 and 129521f.

📒 Files selected for processing (1)
  • kinde_sdk/core/storage/storage_factory.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.11.9)
kinde_sdk/core/storage/storage_factory.py

1-1: typing.Optional imported but unused

Remove unused import: typing.Optional

(F401)

🪛 Flake8 (7.2.0)
kinde_sdk/core/storage/storage_factory.py

[error] 1-1: 'typing.Optional' imported but unused

(F401)


[error] 10-10: expected 2 blank lines, found 1

(E302)

🪛 Pylint (3.3.7)
kinde_sdk/core/storage/storage_factory.py

[error] 59-59: No value for argument 'config' in classmethod call

(E1120)


[refactor] 26-26: Too many return statements (7/6)

(R0911)

🔇 Additional comments (1)
kinde_sdk/core/storage/storage_factory.py (1)

13-23: LGTM! Registration method is well-implemented

The method correctly registers framework-specific storage factories with appropriate logging and clear documentation.

- Add JSON decode error handling in LocalStorage.get() method
- Add exception chaining in portals.py for better error traceability
- Remove unused imports in FastAPI session example
- Remove unused imports in Flask storage factory
- Remove unused Optional import in storage factory
- Fix FrameworkFactory.create_framework() call to pass config parameter
- Improve code reliability and reduce import clutter
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
kinde_sdk/auth/portals.py (1)

118-122: Remove unused variable and improve exception chaining.

The portal_url variable is assigned but never used, and the exception should be chained properly.

             try:
-                portal_url = urlparse(result["url"])
+                urlparse(result["url"])  # Validate URL format
                 return {"url": result["url"]}
             except Exception as e:
                 self._logger.error(f"Error parsing URL: {e}")
-                raise Exception(f"Invalid URL format received from API: {result['url']}")
+                raise Exception(f"Invalid URL format received from API: {result['url']}") from e
🧹 Nitpick comments (13)
kinde_sdk/auth/portals.py (6)

1-8: Fix duplicate import and formatting issue.

There are two formatting and import issues:

  1. urllib.parse is imported twice - once on line 3 and urlparse specifically on line 4
  2. Missing blank line before the first class definition per PEP 8

Apply this diff to fix the imports and formatting:

 from typing import Dict, Any, Optional
 import logging
-import urllib.parse
 from urllib.parse import urlparse
 import httpx
 from enum import Enum
 from kinde_sdk.core.framework.framework_factory import FrameworkFactory
 from kinde_sdk.auth.user_session import UserSession

+
 class PortalPage(str, Enum):

10-18: Add missing blank line before class definition.

Missing blank line before the PortalPage class definition per PEP 8.

Apply this diff:

 from kinde_sdk.auth.user_session import UserSession

+
 class PortalPage(str, Enum):

19-47: Add missing blank line before class definition.

Missing blank line before the Portals class definition per PEP 8.

Apply this diff:

     PROFILE = "profile"

+
 class Portals:

49-61: Clarify URL sanitization behavior.

The method documentation states it "ensures it has a scheme" but the implementation specifically forces HTTPS. This could be misleading if HTTP URLs are expected in development environments.

Consider either:

  1. Updating the docstring to clarify that HTTPS is enforced
  2. Or allowing HTTP in development environments
     def _sanitize_url(self, url: str) -> str:
         """
-        Sanitize the URL by ensuring it has a scheme and removing trailing slashes.
+        Sanitize the URL by ensuring it has HTTPS scheme and removing trailing slashes.
         
         Args:
             url: The URL to sanitize
             
         Returns:
             str: The sanitized URL
         """

97-100: Fix the urllib.parse usage after import correction.

After removing the duplicate urllib.parse import, this line needs to be updated to use urlparse module functions directly.

Apply this diff:

         sanitized_domain = self._sanitize_url(domain)
-        params = urllib.parse.urlencode({
+        params = urlparse.urlencode({
             'sub_nav': sub_nav.value,
             'return_url': return_url
         })

Wait, that's incorrect. We need to import urlencode specifically since we're removing the general urllib.parse import.

-from urllib.parse import urlparse
+from urllib.parse import urlparse, urlencode

Then:

-        params = urllib.parse.urlencode({
+        params = urlencode({
             'sub_nav': sub_nav.value,
             'return_url': return_url
         })

124-125: Add missing blank lines after class definition.

Missing blank lines after the class definition per PEP 8.

Apply this diff:

                 raise Exception(f"Invalid URL format received from API: {result['url']}") from e

+
 # Create a singleton instance
-portals = Portals() 
+portals = Portals()
kinde_sdk/core/storage/local_storage.py (1)

4-5: Fix PEP 8 formatting issue.

Add an additional blank line before the class definition to comply with PEP 8 standards.

 from .storage_interface import StorageInterface
-
+

 class LocalStorage(StorageInterface):
kinde_sdk/core/storage/storage_factory.py (1)

9-10: Fix PEP 8 formatting issue.

Add an additional blank line before the class definition to comply with PEP 8 standards.

 logger = logging.getLogger(__name__)
-
+

 class StorageFactory:
kinde_flask/storage/flask_storage_factory.py (3)

7-8: Fix PEP 8 formatting issue.

Add an additional blank line before the class definition to comply with PEP 8 standards.

 logger = logging.getLogger(__name__)
-
+

 class FlaskStorage(FrameworkAwareStorage):

57-58: Fix PEP 8 formatting issue.

Add a blank line before the method definition to comply with PEP 8 standards.

             session.modified = True
+
     def set_flat(self, value: str) -> None:

69-70: Fix PEP 8 formatting issue.

Add an additional blank line before the class definition to comply with PEP 8 standards.

             session.modified = True
-
+

 class FlaskStorageFactory(StorageFactory):
kinde_fastapi/examples/session.py (2)

1-8: PEP 8: add one blank line before the class definition

Flake8 flags E302 here – ensure two blank lines separate top-level imports and class declarations.

 from starlette.types import ASGIApp
 
+
 class InMemorySessionMiddleware(BaseHTTPMiddleware):

22-24: Unbounded in-memory store risks memory bloat

_sessions never evicts entries; long-running processes or high-traffic apps can exhaust memory.
At minimum, wire cleanup_expired_sessions() into a background task or use a TTL cache/LRU implementation.

Also applies to: 68-72

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 129521f and 81c38f9.

📒 Files selected for processing (5)
  • kinde_fastapi/examples/session.py (1 hunks)
  • kinde_flask/storage/flask_storage_factory.py (1 hunks)
  • kinde_sdk/auth/portals.py (1 hunks)
  • kinde_sdk/core/storage/local_storage.py (1 hunks)
  • kinde_sdk/core/storage/storage_factory.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
kinde_fastapi/examples/session.py (2)
kinde_sdk/core/storage/local_storage.py (1)
  • get (11-27)
kinde_flask/storage/flask_storage_factory.py (1)
  • get (17-32)
🪛 Flake8 (7.2.0)
kinde_sdk/core/storage/storage_factory.py

[error] 10-10: expected 2 blank lines, found 1

(E302)

kinde_fastapi/examples/session.py

[error] 8-8: expected 2 blank lines, found 1

(E302)

kinde_flask/storage/flask_storage_factory.py

[error] 8-8: expected 2 blank lines, found 1

(E302)


[error] 58-58: expected 1 blank line, found 0

(E301)


[error] 70-70: expected 2 blank lines, found 1

(E302)

kinde_sdk/auth/portals.py

[error] 10-10: expected 2 blank lines, found 1

(E302)


[error] 19-19: expected 2 blank lines, found 1

(E302)


[error] 118-118: local variable 'portal_url' is assigned to but never used

(F841)


[error] 125-125: expected 2 blank lines after class or function definition, found 1

(E305)

kinde_sdk/core/storage/local_storage.py

[error] 5-5: expected 2 blank lines, found 1

(E302)

🪛 Pylint (3.3.7)
kinde_sdk/core/storage/storage_factory.py

[refactor] 26-26: Too many return statements (7/6)

(R0911)

kinde_fastapi/examples/session.py

[refactor] 9-9: Too many arguments (6/5)

(R0913)


[refactor] 9-9: Too many positional arguments (6/5)

(R0917)

kinde_flask/storage/flask_storage_factory.py

[refactor] 70-70: Too few public methods (1/2)

(R0903)

kinde_sdk/auth/portals.py

[refactor] 19-19: Too few public methods (1/2)

(R0903)

🪛 Ruff (0.11.9)
kinde_sdk/auth/portals.py

118-118: Local variable portal_url is assigned to but never used

Remove assignment to unused variable portal_url

(F841)

🔇 Additional comments (4)
kinde_sdk/core/storage/local_storage.py (1)

5-57: LGTM! Well-implemented local storage with proper error handling.

The implementation correctly:

  • Uses proper dictionary methods for storage operations
  • Includes JSON error handling in the get method
  • Provides clear documentation
  • Follows the StorageInterface contract
  • Addresses all previously identified issues
kinde_sdk/core/storage/storage_factory.py (1)

26-68: LGTM! Well-designed factory with comprehensive fallback logic.

The create_storage method implements a robust factory pattern with:

  • Support for explicit storage type configuration
  • Framework-specific storage factory delegation
  • Built-in storage type handling
  • Automatic framework detection fallback
  • Proper error handling and logging

The multiple return statements are justified here as they represent different logical paths in the factory creation process, making the code more readable than complex conditional nesting.

kinde_flask/storage/flask_storage_factory.py (1)

8-87: LGTM! Excellent Flask session integration with proper error handling.

The implementation provides:

  • Proper Flask session integration through _get_session() method
  • Consistent error handling with session existence checks
  • Correct session modification flag management
  • Clean factory pattern implementation
  • Comprehensive documentation

The single public method in FlaskStorageFactory is appropriate for a simple factory class.

kinde_fastapi/examples/session.py (1)

12-16: Parameter naming inconsistency – https_only vs secure

response.set_cookie() expects the keyword secure.
Exposing it as https_only is confusing and reverses the polarity (secure=True means HTTPS-only). Consider renaming the argument and internal attribute for clarity:

-        https_only: bool = False
+        secure: bool = False
 ...
-        self.https_only = https_only
+        self.secure = secure
 ...
-                secure=self.https_only
+                secure=self.secure

Update call-sites accordingly.

Also applies to: 45-52

- Add thread lock protection to device_id property in StorageManager
- Ensure thread-safe device ID generation and retrieval
- Remove unused Union import from feature_flags.py
- Remove unused logging import from feature_flags.py
- Improve concurrent access safety for device ID operations
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
kinde_sdk/core/storage/storage_manager.py (2)

170-184: Fix misleading method signature and documentation.

The set method's documentation describes storing key-value pairs, but the implementation only accepts an access_token parameter and calls set_flat. This creates a confusing API.

Either rename the method to be more specific or update it to match the documented behavior. Also fix the formatting issues:

-
-    def set(self, access_token : str) -> None:
+    def set_access_token(self, access_token: str) -> None:
         """
-        Store data in storage.
+        Store access token in flat storage.
         
         Args:
-            key (str): The key to store under.
-            value (Dict): The data to store.
+            access_token (str): The access token to store.
         """

199-227: Avoid breaking storage encapsulation.

The fallback implementation directly accesses the private _storage attribute of storage implementations, which breaks encapsulation and may not work with all storage backends.

Consider requiring all storage implementations to support prefix operations or use a different approach:

     def clear_device_data(self) -> None:
         """
         Clear all data associated with the current device.
         """
         if self._storage is None:
             return
             
         device_id = self.get_device_id()
         prefix = f"device:{device_id}:"
         
         if hasattr(self._storage, "clear_prefix"):
             self._storage.clear_prefix(prefix)
         else:
-            # Fallback implementation - less efficient
-            if hasattr(self._storage, "_storage") and isinstance(self._storage._storage, dict):
-                keys_to_delete = [k for k in self._storage._storage.keys() if k.startswith(prefix)]
-                for k in keys_to_delete:
-                    self._storage.delete(k)
+            # Log warning instead of accessing private attributes
+            import logging
+            logger = logging.getLogger(__name__)
+            logger.warning(
+                f"Storage backend {type(self._storage).__name__} does not support "
+                "prefix-based clearing. Device data may not be fully cleared."
+            )
🧹 Nitpick comments (6)
kinde_sdk/core/storage/storage_manager.py (3)

9-9: Fix formatting: Add required blank lines before class definition.

Static analysis indicates missing blank lines before the class definition.

+

 class StorageManager:

185-185: Fix formatting: Remove excessive blank lines.

Static analysis indicates too many blank lines.

-

224-224: Simplify dictionary key checking.

Use key in dict instead of key in dict.keys() for better performance and readability.

-                keys_to_delete = [k for k in self._storage._storage.keys() if k.startswith(prefix)]
+                keys_to_delete = [k for k in self._storage._storage if k.startswith(prefix)]
kinde_sdk/auth/feature_flags.py (3)

6-11: Fix formatting and consider adding methods for better encapsulation.

The class logic is sound, but there are formatting issues to address.

+

 class FeatureFlag(Generic[T]):

The Pylint warning about too few public methods can be safely ignored as this is intended as a data container class.


13-13: Fix formatting issue.

Add required blank lines before class definition.

+

 class FeatureFlags(BaseAuth):

104-105: Fix formatting issue.

Add required blank lines after class definition.

+

 # Create a singleton instance
 feature_flags = FeatureFlags()

The singleton pattern is appropriate for this module's use case.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 81c38f9 and 3eb52b9.

📒 Files selected for processing (2)
  • kinde_sdk/auth/feature_flags.py (1 hunks)
  • kinde_sdk/core/storage/storage_manager.py (1 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
kinde_sdk/auth/feature_flags.py

[warning] 43-43: kinde_sdk/auth/feature_flags.py#L43
Added line #L43 was not covered by tests

🪛 Flake8 (7.2.0)
kinde_sdk/auth/feature_flags.py

[error] 6-6: expected 2 blank lines, found 1

(E302)


[error] 13-13: expected 2 blank lines, found 1

(E302)


[error] 105-105: expected 2 blank lines after class or function definition, found 1

(E305)

kinde_sdk/core/storage/storage_manager.py

[error] 9-9: expected 2 blank lines, found 1

(E302)


[error] 171-171: too many blank lines (2)

(E303)


[error] 171-171: whitespace before ':'

(E203)


[error] 186-186: too many blank lines (2)

(E303)

🪛 Pylint (3.3.7)
kinde_sdk/auth/feature_flags.py

[refactor] 6-6: Too few public methods (0/2)

(R0903)

kinde_sdk/core/storage/storage_manager.py

[error] 22-22: Access to member '_initialized' before its definition line 26

(E0203)

🪛 Ruff (0.11.9)
kinde_sdk/core/storage/storage_manager.py

224-224: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (3)
kinde_sdk/core/storage/storage_manager.py (2)

20-26: LGTM: AttributeError issue has been resolved.

The initialization check now works correctly since _initialized is properly set to False in the __new__ method (line 17). This addresses the previous AttributeError concern.


68-86: LGTM: Thread safety has been implemented.

The get_device_id method now properly uses the lock to prevent race conditions when multiple threads access it simultaneously. This addresses the previous thread safety concern.

kinde_sdk/auth/feature_flags.py (1)

1-2: LGTM! Imports are clean and appropriate.

The unused imports issue from the previous review has been resolved.

…ibility

- Replace threading.Lock with asyncio.Lock for proper async context handling
- Convert session operation methods to async for non-blocking execution
- Update _get_session() and _set_session() to async methods with await
- Update delete_session() and cleanup_expired_sessions() to async methods
- Ensure thread safety in async FastAPI environment with proper async locks
- Improve performance by avoiding blocking operations in async context
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
kinde_fastapi/examples/session.py (1)

1-23: Great improvements to the async implementation!

The code properly addresses the previous review comments by:

  • Removing all unused imports
  • Using asyncio.Lock instead of threading.Lock for non-blocking async operations

The session configuration parameters are well-structured and provide good defaults.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3eb52b9 and 57db0ea.

📒 Files selected for processing (1)
  • kinde_fastapi/examples/session.py (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
kinde_fastapi/examples/session.py (2)
kinde_flask/storage/flask_storage_factory.py (1)
  • get (17-32)
kinde_sdk/core/storage/local_storage.py (1)
  • get (11-27)
🪛 Flake8 (7.2.0)
kinde_fastapi/examples/session.py

[error] 8-8: expected 2 blank lines, found 1

(E302)

🪛 Pylint (3.3.7)
kinde_fastapi/examples/session.py

[refactor] 9-9: Too many arguments (6/5)

(R0913)


[refactor] 9-9: Too many positional arguments (6/5)

(R0917)

… safety

- Add input validation to ensure flag_data is a dictionary
- Add try-catch block for type conversion errors with descriptive messages
- Handle None values gracefully for string and integer types
- Convert None string values to empty string instead of 'None'
- Convert None integer values to 0 instead of throwing error
- Provide clear error messages for invalid type conversions
- Add comments for better code documentation
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
kinde_sdk/auth/feature_flags.py (4)

14-22: expected_type parameter is never used – remove or implement

_parse_flag_value accepts an expected_type argument but never references it, which can mislead readers and static-analysis tools. Either implement the coercion logic or drop the parameter to keep the public contract minimal.

-    def _parse_flag_value(self, flag_data: Dict[str, Any], expected_type: Optional[str] = None) -> FeatureFlag:
+    def _parse_flag_value(self, flag_data: Dict[str, Any]) -> FeatureFlag:

52-55: Preserve original traceback when re-raising

Ruff flags this (B904). Chain the new exception with the caught one to keep context.

-        except (TypeError, ValueError) as e:
-            raise ValueError(
-                f"Cannot convert flag value {raw_value!r} to type {flag_type!r}: {e}"
-            )
+        except (TypeError, ValueError) as err:
+            raise ValueError(
+                f"Cannot convert flag value {raw_value!r} to type {flag_type!r}: {err}"
+            ) from err

64-82: Generic type parameter T leaks implementation details

get_flag promises FeatureFlag[T], yet _parse_flag_value returns a concrete str|bool|int based on the token, not necessarily matching the caller-supplied default_value. This weakens type safety for downstream users.

Two options:

  1. Return FeatureFlag[Any] and accept default_value: Optional[Any] (simplest).
  2. Enforce that default_value and parsed value share the same runtime type (heavier).

Given typical SDK usage, option 1 keeps typing honest without extra runtime checks.


1-13: Minor style – add the customary blank line separators

Flake8 complains about missing blank lines before/after top-level definitions (E302/E305). Adding one extra blank line above T = TypeVar('T'), above class FeatureFlag, and at EOF will silence the linter and keep consistency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57db0ea and d833f90.

📒 Files selected for processing (1)
  • kinde_sdk/auth/feature_flags.py (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: brettchaldecott
PR: kinde-oss/kinde-python-sdk#83
File: kinde_sdk/auth/feature_flags.py:85-102
Timestamp: 2025-07-04T07:09:21.409Z
Learning: In the Kinde Python SDK v2, the maintainer (brettchaldecott) prefers to keep async keywords on methods in the feature flags module even when they don't currently perform await operations, as this approach has been tested and is preferred for the SDK's design.
kinde_sdk/auth/feature_flags.py (2)
Learnt from: brettchaldecott
PR: kinde-oss/kinde-python-sdk#83
File: kinde_sdk/auth/feature_flags.py:85-102
Timestamp: 2025-07-04T07:09:21.409Z
Learning: In the Kinde Python SDK v2, the maintainer (brettchaldecott) prefers to keep async keywords on methods in the feature flags module even when they don't currently perform await operations, as this approach has been tested and is preferred for the SDK's design.
Learnt from: brettchaldecott
PR: kinde-oss/kinde-python-sdk#83
File: kinde_sdk/auth/claims.py:35-49
Timestamp: 2025-07-03T13:05:24.796Z
Learning: In the Kinde Python SDK v2, the TokenManager.get_claims() method internally handles token lookups with a fallback strategy - it first tries to get claims from access_token_claims and falls back to id_token_claims if access token claims are unavailable. The token_type parameter in Claims class methods (get_claim, get_all_claims) is therefore not used because the TokenManager abstracts away the token selection logic.
🪛 Ruff (0.11.9)
kinde_sdk/auth/feature_flags.py

53-55: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🪛 GitHub Check: codecov/patch
kinde_sdk/auth/feature_flags.py

[warning] 26-26: kinde_sdk/auth/feature_flags.py#L26
Added line #L26 was not covered by tests


[warning] 51-53: kinde_sdk/auth/feature_flags.py#L51-L53
Added lines #L51 - L53 were not covered by tests

🪛 Flake8 (7.2.0)
kinde_sdk/auth/feature_flags.py

[error] 6-6: expected 2 blank lines, found 1

(E302)


[error] 13-13: expected 2 blank lines, found 1

(E302)


[error] 117-117: expected 2 blank lines after class or function definition, found 1

(E305)

🪛 Pylint (3.3.7)
kinde_sdk/auth/feature_flags.py

[refactor] 6-6: Too few public methods (0/2)

(R0903)

🔇 Additional comments (1)
kinde_sdk/auth/feature_flags.py (1)

41-46: Boolean conversion may return incorrect results for string tokens

bool(raw_value) converts every non-empty string (including "false") to True, which breaks flags delivered as JSON strings. Consider an explicit check so that "false"False.

-            elif flag_type == "b":
-                value = bool(raw_value)
+            elif flag_type == "b":
+                if isinstance(raw_value, str):
+                    value = raw_value.lower() == "true"
+                else:
+                    value = bool(raw_value)

@brettchaldecott brettchaldecott merged commit 0ef6696 into main Jul 4, 2025
9 checks passed
This was referenced Aug 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants