Skip to content

Commit

Permalink
more code
Browse files Browse the repository at this point in the history
  • Loading branch information
rishabhpoddar committed Aug 25, 2024
1 parent ad9ae35 commit 1c15536
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 13 deletions.
10 changes: 10 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
You are an expert Python and Typescript developer. Your job is to convert node code (in typescript) into Python code. The python code then goes into this SDK. The python code style should keep in mind:
- Avoid using TypeDict
- Avoid using generic Dict as much as possible, except when defining the types for `user_context`.
- If a function has multiple `status` strings as outputs, then define one unique class per unique `status` string. The class name should be such that it indicates the status it is associated with.
- Variable and function names should be in snake_case. Class names in PascalCase.
- Whenever importing `Literal`, import it from `typing_extensions`, and not `types`.
- Do not use `|` for OR type, instead use `Union`
- When defining API interface functions, make sure the output classes inherit from `APIResponse` class, and that they have a `to_json` function defined whose output matches the structure of the provided Typescript code output objects.

The semantic of the python code should be the same as what's of the provided Typescript code.
7 changes: 1 addition & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,4 @@ Additional resources you might find useful:
This will generate the API docs in a folder called docs
```
make build-docs
```

## AI prompt rules for generating code (with Claude sonnet-3.5):
- Avoid using TypeDict
- Avoid using generic Dict as much as possible, except when defining the types for user_context. Instead, create a custom class to indicate that type. If a function has multiple status Literal output, then there should be one class per status.
- Variable and function names should be in snake_case. Class names in PascalCase.
```
144 changes: 137 additions & 7 deletions supertokens_python/recipe/totp/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
from typing_extensions import Literal
from abc import ABC, abstractmethod

from supertokens_python.recipe.session import SessionContainer
from supertokens_python.types import APIResponse, GeneralErrorResponse

class OkResult:

class OkResult(APIResponse):
def __init__(self):
self.status: Literal["OK"] = "OK"

Expand All @@ -28,10 +31,13 @@ def __init__(self, info: str):
self.info: str = info


class UnknownUserIdError:
class UnknownUserIdError(APIResponse):
def __init__(self):
self.status: Literal["UNKNOWN_USER_ID_ERROR"] = "UNKNOWN_USER_ID_ERROR"

def to_json(self) -> Dict[str, Any]:
return {"status": self.status}


class UserIdentifierInfoDoesNotExistError:
def __init__(self):
Expand All @@ -47,42 +53,76 @@ def __init__(self, device_name: str, secret: str, qr_code_string: str):
self.secret: str = secret
self.qr_code_string: str = qr_code_string

def to_json(self) -> Dict[str, Any]:
return {
"status": self.status,
"deviceName": self.device_name,
"secret": self.secret,
"qrCodeString": self.qr_code_string,
}

class DeviceAlreadyExistsError:

class DeviceAlreadyExistsError(APIResponse):
def __init__(self):
self.status: Literal[
"DEVICE_ALREADY_EXISTS_ERROR"
] = "DEVICE_ALREADY_EXISTS_ERROR"

def to_json(self) -> Dict[str, Any]:
return {"status": self.status}


class UpdateDeviceOkResult(OkResult):
pass


class UnknownDeviceError:
class UnknownDeviceError(APIResponse):
def __init__(self):
self.status: Literal["UNKNOWN_DEVICE_ERROR"] = "UNKNOWN_DEVICE_ERROR"

def to_json(self) -> Dict[str, Any]:
return {"status": self.status}

class Device:

class Device(APIResponse):
def __init__(self, name: str, period: int, skew: int, verified: bool):
self.name: str = name
self.period: int = period
self.skew: int = skew
self.verified: bool = verified

def to_json(self) -> Dict[str, Any]:
return {
"name": self.name,
"period": self.period,
"skew": self.skew,
"verified": self.verified,
}


class ListDevicesOkResult(OkResult):
def __init__(self, devices: List[Device]):
super().__init__()
self.devices: List[Device] = devices

def to_json(self) -> Dict[str, Any]:
return {
"status": self.status,
"devices": [device.to_json() for device in self.devices],
}


class RemoveDeviceOkResult(OkResult):
def __init__(self, did_device_exist: bool):
super().__init__()
self.did_device_exist: bool = did_device_exist

def to_json(self) -> Dict[str, Any]:
return {
"status": self.status,
"didDeviceExist": self.did_device_exist,
}


class VerifyDeviceOkResult(OkResult):
def __init__(
Expand All @@ -92,28 +132,50 @@ def __init__(
super().__init__()
self.was_already_verified: bool = was_already_verified

def to_json(self) -> Dict[str, Any]:
return {
"status": self.status,
"wasAlreadyVerified": self.was_already_verified,
}

class InvalidTOTPError:

class InvalidTOTPError(APIResponse):
def __init__(
self, current_number_of_failed_attempts: int, max_number_of_failed_attempts: int
):
self.status: Literal["INVALID_TOTP_ERROR"] = "INVALID_TOTP_ERROR"
self.current_number_of_failed_attempts: int = current_number_of_failed_attempts
self.max_number_of_failed_attempts: int = max_number_of_failed_attempts

def to_json(self) -> Dict[str, Any]:
return {
"status": self.status,
"currentNumberOfFailedAttempts": self.current_number_of_failed_attempts,
"maxNumberOfFailedAttempts": self.max_number_of_failed_attempts,
}


class LimitReachedError:
class LimitReachedError(APIResponse):
def __init__(self, retry_after_ms: int):
self.status: Literal["LIMIT_REACHED_ERROR"] = "LIMIT_REACHED_ERROR"
self.retry_after_ms: int = retry_after_ms

def to_json(self) -> Dict[str, Any]:
return {
"status": self.status,
"retryAfterMs": self.retry_after_ms,
}


class VerifyTOTPOkResult(OkResult):
def __init__(
self,
):
super().__init__()

def to_json(self) -> Dict[str, Any]:
return {"status": self.status}


class RecipeInterface(ABC):
@abstractmethod
Expand Down Expand Up @@ -186,3 +248,71 @@ async def verify_totp(
LimitReachedError,
]:
pass


class APIOptions:
pass


class APIInterface(ABC):
@abstractmethod
async def create_device_post(
self,
device_name: Union[str, None],
options: APIOptions,
session: SessionContainer,
user_context: Dict[str, Any],
) -> Union[CreateDeviceOkResult, DeviceAlreadyExistsError, GeneralErrorResponse]:
pass

@abstractmethod
async def list_devices_get(
self,
options: APIOptions,
session: SessionContainer,
user_context: Dict[str, Any],
) -> Union[ListDevicesOkResult, GeneralErrorResponse]:
pass

@abstractmethod
async def remove_device_post(
self,
device_name: str,
options: APIOptions,
session: SessionContainer,
user_context: Dict[str, Any],
) -> Union[RemoveDeviceOkResult, GeneralErrorResponse]:
pass

@abstractmethod
async def verify_device_post(
self,
device_name: str,
totp: str,
options: APIOptions,
session: SessionContainer,
user_context: Dict[str, Any],
) -> Union[
VerifyDeviceOkResult,
UnknownDeviceError,
InvalidTOTPError,
LimitReachedError,
GeneralErrorResponse,
]:
pass

@abstractmethod
async def verify_totp_post(
self,
totp: str,
options: APIOptions,
session: SessionContainer,
user_context: Dict[str, Any],
) -> Union[
VerifyTOTPOkResult,
UnknownUserIdError,
InvalidTOTPError,
LimitReachedError,
GeneralErrorResponse,
]:
pass

0 comments on commit 1c15536

Please sign in to comment.