stackmate 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- stackmate/__init__.py +24 -0
- stackmate/auth.py +82 -0
- stackmate/db_helper.py +94 -0
- stackmate/error_handler.py +73 -0
- stackmate/logger.py +96 -0
- stackmate/utils.py +62 -0
- stackmate/validator.py +66 -0
- stackmate-0.1.0.dist-info/METADATA +74 -0
- stackmate-0.1.0.dist-info/RECORD +12 -0
- stackmate-0.1.0.dist-info/WHEEL +5 -0
- stackmate-0.1.0.dist-info/licenses/LICENSE +21 -0
- stackmate-0.1.0.dist-info/top_level.txt +1 -0
stackmate/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
StackMate: A Full-Stack Development Toolkit for Python.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
__version__ = "0.1.0"
|
|
6
|
+
__author__ = "Sudhakar K"
|
|
7
|
+
|
|
8
|
+
from stackmate.auth import AuthManager
|
|
9
|
+
from stackmate.db_helper import DBHelper
|
|
10
|
+
from stackmate.error_handler import APIResponse, ErrorCode
|
|
11
|
+
from stackmate.logger import AppLogger
|
|
12
|
+
from stackmate.utils import generate_uuid, get_timestamp
|
|
13
|
+
from stackmate.validator import PayloadValidator
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"AuthManager",
|
|
17
|
+
"DBHelper",
|
|
18
|
+
"APIResponse",
|
|
19
|
+
"ErrorCode",
|
|
20
|
+
"AppLogger",
|
|
21
|
+
"generate_uuid",
|
|
22
|
+
"get_timestamp",
|
|
23
|
+
"PayloadValidator",
|
|
24
|
+
]
|
stackmate/auth.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
JWT and token management utilities for StackMate.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from datetime import datetime, timedelta, timezone
|
|
6
|
+
from typing import Any, Dict, Optional, Union
|
|
7
|
+
|
|
8
|
+
import jwt
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AuthManager:
|
|
12
|
+
"""
|
|
13
|
+
Manager for creating and verifying JWT tokens.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
secret_key: str,
|
|
19
|
+
algorithm: str = "HS256",
|
|
20
|
+
expires_delta: int = 60,
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
Initializes the Auth Manager.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
secret_key (str): Secret key for encoding/decoding.
|
|
27
|
+
algorithm (str): JWT algorithm. Defaults to HS256.
|
|
28
|
+
expires_delta (int): Expiry time in minutes. Defaults to 60.
|
|
29
|
+
"""
|
|
30
|
+
self.secret_key = secret_key
|
|
31
|
+
self.algorithm = algorithm
|
|
32
|
+
self.expires_delta = expires_delta
|
|
33
|
+
|
|
34
|
+
def create_token(self, data: Dict[str, Any]) -> str:
|
|
35
|
+
"""
|
|
36
|
+
Creates a JWT token.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
data (Dict): The payload to include.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
str: Encoded JWT token.
|
|
43
|
+
"""
|
|
44
|
+
to_encode = data.copy()
|
|
45
|
+
expire = datetime.now(timezone.utc) + timedelta(minutes=self.expires_delta)
|
|
46
|
+
to_encode.update({"exp": expire})
|
|
47
|
+
return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
|
|
48
|
+
|
|
49
|
+
def verify_token(self, token: str) -> Optional[Dict[str, Any]]:
|
|
50
|
+
"""
|
|
51
|
+
Verifies and decodes a JWT token.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
token (str): The JWT string.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Optional[Dict]: The decoded payload if valid, None otherwise.
|
|
58
|
+
"""
|
|
59
|
+
try:
|
|
60
|
+
return jwt.decode(token, self.secret_key, algorithms=[self.algorithm])
|
|
61
|
+
except (jwt.ExpiredSignatureError, jwt.InvalidTokenError):
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
def decode_token(self, token: str) -> Optional[Dict[str, Any]]:
|
|
65
|
+
"""
|
|
66
|
+
Decodes a token without verifying expiry (for debug/extraction).
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
token (str): The JWT string.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Optional[Dict]: The decoded payload.
|
|
73
|
+
"""
|
|
74
|
+
try:
|
|
75
|
+
return jwt.decode(
|
|
76
|
+
token,
|
|
77
|
+
self.secret_key,
|
|
78
|
+
algorithms=[self.algorithm],
|
|
79
|
+
options={"verify_exp": False},
|
|
80
|
+
)
|
|
81
|
+
except Exception:
|
|
82
|
+
return None
|
stackmate/db_helper.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database utility helpers for StackMate.
|
|
3
|
+
Simulates a generic CRUD interface.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any, Dict, List, Optional, Union
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DBHelper:
|
|
10
|
+
"""
|
|
11
|
+
Generic Database Helper for CRUD operations.
|
|
12
|
+
Acts as an abstraction layer (Mocked for demonstration).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(self, connection_string: str = "mock://localhost"):
|
|
16
|
+
"""
|
|
17
|
+
Initializes the DB helper.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
connection_string (str): Database connection URI.
|
|
21
|
+
"""
|
|
22
|
+
self.connection_string = connection_string
|
|
23
|
+
# In a real app, you'd initialize a pool or client here
|
|
24
|
+
self._mock_db: List[Dict[str, Any]] = []
|
|
25
|
+
|
|
26
|
+
def create(self, table: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
27
|
+
"""
|
|
28
|
+
Inserts a new record into the "table".
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
table (str): Target table/collection name.
|
|
32
|
+
data (Dict): Record content.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Dict: The created record.
|
|
36
|
+
"""
|
|
37
|
+
# Mock implementation
|
|
38
|
+
record = {"id": len(self._mock_db) + 1, "table": table, **data}
|
|
39
|
+
self._mock_db.append(record)
|
|
40
|
+
return record
|
|
41
|
+
|
|
42
|
+
def read(self, table: str, filters: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
|
|
43
|
+
"""
|
|
44
|
+
Retrieves records from the "table" based on filters.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
table (str): Target table name.
|
|
48
|
+
filters (Dict): Query filters.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
List[Dict]: List of matching records.
|
|
52
|
+
"""
|
|
53
|
+
results = [r for r in self._mock_db if r["table"] == table]
|
|
54
|
+
if filters:
|
|
55
|
+
for key, value in filters.items():
|
|
56
|
+
results = [r for r in results if r.get(key) == value]
|
|
57
|
+
return results
|
|
58
|
+
|
|
59
|
+
def update(
|
|
60
|
+
self, table: str, record_id: int, updates: Dict[str, Any]
|
|
61
|
+
) -> Optional[Dict[str, Any]]:
|
|
62
|
+
"""
|
|
63
|
+
Updates an existing record.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
table (str): Target table name.
|
|
67
|
+
record_id (int): ID of the record to update.
|
|
68
|
+
updates (Dict): Field-value updates.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Optional[Dict]: The updated record if found.
|
|
72
|
+
"""
|
|
73
|
+
for record in self._mock_db:
|
|
74
|
+
if record["table"] == table and record["id"] == record_id:
|
|
75
|
+
record.update(updates)
|
|
76
|
+
return record
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
def delete(self, table: str, record_id: int) -> bool:
|
|
80
|
+
"""
|
|
81
|
+
Deletes a record.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
table (str): Target table name.
|
|
85
|
+
record_id (int): ID of the record.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
bool: True if deleted, False if not found.
|
|
89
|
+
"""
|
|
90
|
+
for i, record in enumerate(self._mock_db):
|
|
91
|
+
if record["table"] == table and record["id"] == record_id:
|
|
92
|
+
del self._mock_db[i]
|
|
93
|
+
return True
|
|
94
|
+
return False
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unified error handling and structured API responses for StackMate.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Any, Dict, Optional, Union
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ErrorCode(str, Enum):
|
|
10
|
+
"""Enumeration of standard error codes."""
|
|
11
|
+
|
|
12
|
+
SUCCESS = "SUCCESS"
|
|
13
|
+
VALIDATION_ERROR = "VALIDATION_ERROR"
|
|
14
|
+
AUTHENTICATION_ERROR = "AUTHENTICATION_ERROR"
|
|
15
|
+
NOT_FOUND = "NOT_FOUND"
|
|
16
|
+
DATABASE_ERROR = "DATABASE_ERROR"
|
|
17
|
+
INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class APIResponse:
|
|
21
|
+
"""Class to handle structured API responses."""
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def success(
|
|
25
|
+
data: Any = None,
|
|
26
|
+
message: str = "Operation successful",
|
|
27
|
+
status_code: int = 200,
|
|
28
|
+
) -> Dict[str, Any]:
|
|
29
|
+
"""
|
|
30
|
+
Generates a successful API response.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
data (Any): The payload to return.
|
|
34
|
+
message (str): A message for the user.
|
|
35
|
+
status_code (int): HTTP status code.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Dict[str, Any]: Structured success response.
|
|
39
|
+
"""
|
|
40
|
+
return {
|
|
41
|
+
"success": True,
|
|
42
|
+
"message": message,
|
|
43
|
+
"data": data,
|
|
44
|
+
"error_code": ErrorCode.SUCCESS,
|
|
45
|
+
"status_code": status_code,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def failure(
|
|
50
|
+
message: str,
|
|
51
|
+
error_code: ErrorCode = ErrorCode.INTERNAL_SERVER_ERROR,
|
|
52
|
+
data: Any = None,
|
|
53
|
+
status_code: int = 500,
|
|
54
|
+
) -> Dict[str, Any]:
|
|
55
|
+
"""
|
|
56
|
+
Generates a failed API response.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
message (str): Error message.
|
|
60
|
+
error_code (ErrorCode): Standardized error code.
|
|
61
|
+
data (Any): Optional additional error context.
|
|
62
|
+
status_code (int): HTTP status code.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Dict[str, Any]: Structured failure response.
|
|
66
|
+
"""
|
|
67
|
+
return {
|
|
68
|
+
"success": False,
|
|
69
|
+
"message": message,
|
|
70
|
+
"data": data,
|
|
71
|
+
"error_code": error_code,
|
|
72
|
+
"status_code": status_code,
|
|
73
|
+
}
|
stackmate/logger.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Request/Response logging utilities for StackMate.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import logging
|
|
7
|
+
import time
|
|
8
|
+
from typing import Any, Dict, Optional
|
|
9
|
+
|
|
10
|
+
from stackmate.utils import get_timestamp, parse_latency
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AppLogger:
|
|
14
|
+
"""
|
|
15
|
+
Standard logger for API requests and responses.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, name: str = "StackMate", level: int = logging.INFO):
|
|
19
|
+
"""
|
|
20
|
+
Initializes the logger.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
name (str): Name of the logger.
|
|
24
|
+
level (int): Logging level.
|
|
25
|
+
"""
|
|
26
|
+
self.logger = logging.getLogger(name)
|
|
27
|
+
handler = logging.StreamHandler()
|
|
28
|
+
formatter = logging.Formatter(
|
|
29
|
+
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
30
|
+
)
|
|
31
|
+
handler.setFormatter(formatter)
|
|
32
|
+
if not self.logger.handlers:
|
|
33
|
+
self.logger.addHandler(handler)
|
|
34
|
+
self.logger.setLevel(level)
|
|
35
|
+
|
|
36
|
+
def log_request(self, method: str, url: str, payload: Optional[Dict[str, Any]] = None) -> float:
|
|
37
|
+
"""
|
|
38
|
+
Logs an incoming API request.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
method (str): HTTP method (GET, POST, etc.).
|
|
42
|
+
url (str): Target URL.
|
|
43
|
+
payload (Dict): Request body.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
float: The start time of the request.
|
|
47
|
+
"""
|
|
48
|
+
start_time = time.time()
|
|
49
|
+
log_data = {
|
|
50
|
+
"timestamp": get_timestamp(),
|
|
51
|
+
"type": "REQUEST",
|
|
52
|
+
"method": method,
|
|
53
|
+
"url": url,
|
|
54
|
+
"payload": payload,
|
|
55
|
+
}
|
|
56
|
+
self.logger.info("Request: %s", json.dumps(log_data))
|
|
57
|
+
return start_time
|
|
58
|
+
|
|
59
|
+
def log_response(
|
|
60
|
+
self,
|
|
61
|
+
method: str,
|
|
62
|
+
url: str,
|
|
63
|
+
status_code: int,
|
|
64
|
+
start_time: float,
|
|
65
|
+
response_data: Optional[Any] = None,
|
|
66
|
+
) -> None:
|
|
67
|
+
"""
|
|
68
|
+
Logs an API response with latency calculation.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
method (str): HTTP method.
|
|
72
|
+
url (str): Target URL.
|
|
73
|
+
status_code (int): HTTP status code.
|
|
74
|
+
start_time (float): The timestamp when the request started.
|
|
75
|
+
response_data (Any): The response content.
|
|
76
|
+
"""
|
|
77
|
+
end_time = time.time()
|
|
78
|
+
latency = parse_latency(start_time, end_time)
|
|
79
|
+
log_data = {
|
|
80
|
+
"timestamp": get_timestamp(),
|
|
81
|
+
"type": "RESPONSE",
|
|
82
|
+
"method": method,
|
|
83
|
+
"url": url,
|
|
84
|
+
"status": status_code,
|
|
85
|
+
"latency": latency,
|
|
86
|
+
"data": response_data,
|
|
87
|
+
}
|
|
88
|
+
self.logger.info("Response: %s", json.dumps(log_data))
|
|
89
|
+
|
|
90
|
+
def error(self, message: str, exc_info: bool = True) -> None:
|
|
91
|
+
"""Logs an error message."""
|
|
92
|
+
self.logger.error(message, exc_info=exc_info)
|
|
93
|
+
|
|
94
|
+
def info(self, message: str) -> None:
|
|
95
|
+
"""Logs an info message."""
|
|
96
|
+
self.logger.info(message)
|
stackmate/utils.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Miscellaneous helper functions for StackMate.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import uuid
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
from typing import Any, Dict, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def generate_uuid() -> str:
|
|
11
|
+
"""
|
|
12
|
+
Generates a unique UUID v4 string.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
str: A unique UUID.
|
|
16
|
+
"""
|
|
17
|
+
return str(uuid.uuid4())
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_timestamp(utc: bool = True) -> str:
|
|
21
|
+
"""
|
|
22
|
+
Returns the current timestamp in ISO format.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
utc (bool): Whether to use UTC time. Defaults to True.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
str: ISO formatted timestamp.
|
|
29
|
+
"""
|
|
30
|
+
if utc:
|
|
31
|
+
return datetime.now(timezone.utc).isoformat()
|
|
32
|
+
return datetime.now().isoformat()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def format_response_data(data: Any) -> Dict[str, Any]:
|
|
36
|
+
"""
|
|
37
|
+
Helper to ensure data is in a dictionary format for JSON responses.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
data (Any): Input data.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Dict[str, Any]: Formatted data.
|
|
44
|
+
"""
|
|
45
|
+
if isinstance(data, dict):
|
|
46
|
+
return data
|
|
47
|
+
return {"result": data}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def parse_latency(start_time: float, end_time: float) -> str:
|
|
51
|
+
"""
|
|
52
|
+
Calculates latency and returns it as a formatted string.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
start_time (float): Execution start time.
|
|
56
|
+
end_time (float): Execution end time.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
str: Latency in milliseconds (e.g., "120ms").
|
|
60
|
+
"""
|
|
61
|
+
duration = (end_time - start_time) * 1000
|
|
62
|
+
return f"{duration:.2f}ms"
|
stackmate/validator.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API payload validation utilities for StackMate.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Optional, Type, Union
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PayloadValidator:
|
|
9
|
+
"""
|
|
10
|
+
Validates API request payloads against required fields and types.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def validate(
|
|
15
|
+
payload: Dict[str, Any],
|
|
16
|
+
schema: Dict[str, Type],
|
|
17
|
+
required_fields: Optional[List[str]] = None,
|
|
18
|
+
) -> List[str]:
|
|
19
|
+
"""
|
|
20
|
+
Validates the payload against a schema.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
payload (Dict): The data to validate.
|
|
24
|
+
schema (Dict): A mapping of field names to expected types.
|
|
25
|
+
required_fields (List): A list of fields that must be present.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
List[str]: A list of error messages. Empty if valid.
|
|
29
|
+
"""
|
|
30
|
+
errors = []
|
|
31
|
+
required = required_fields or []
|
|
32
|
+
|
|
33
|
+
# Check for missing required fields
|
|
34
|
+
for field in required:
|
|
35
|
+
if field not in payload:
|
|
36
|
+
errors.append(f"Field '{field}' is required.")
|
|
37
|
+
|
|
38
|
+
# Check types for present fields
|
|
39
|
+
for field, value in payload.items():
|
|
40
|
+
if field in schema:
|
|
41
|
+
expected_type = schema[field]
|
|
42
|
+
if not isinstance(value, expected_type):
|
|
43
|
+
errors.append(
|
|
44
|
+
f"Field '{field}' must be of type {expected_type.__name__}, "
|
|
45
|
+
f"got {type(value).__name__}."
|
|
46
|
+
)
|
|
47
|
+
elif field not in schema and required_fields is not None:
|
|
48
|
+
# Optionally handle unexpected fields if schema is strict
|
|
49
|
+
# For now, we allow them unless we want strict validation
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
return errors
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def is_valid(
|
|
56
|
+
payload: Dict[str, Any],
|
|
57
|
+
schema: Dict[str, Type],
|
|
58
|
+
required_fields: Optional[List[str]] = None,
|
|
59
|
+
) -> bool:
|
|
60
|
+
"""
|
|
61
|
+
Shortcut to check if a payload is valid.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
bool: True if valid, False otherwise.
|
|
65
|
+
"""
|
|
66
|
+
return len(PayloadValidator.validate(payload, schema, required_fields)) == 0
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stackmate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A Full-Stack Development Toolkit for Python developers.
|
|
5
|
+
Author-email: Sudhakar K <sudhakark4227@gmail.com>
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: PyJWT>=2.8.0
|
|
15
|
+
Requires-Dist: pydantic>=2.0.0
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
19
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
20
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
21
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# StackMate
|
|
25
|
+
|
|
26
|
+
**StackMate** is a production-ready Full-Stack Development Toolkit for Python developers. It provides essential utilities for building robust APIs, managing authentication, handling errors, and simplifying database operations.
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- **Logger**: Structured request/response logging with latency tracking.
|
|
31
|
+
- **Validator**: API payload validation using type hints and schema checks.
|
|
32
|
+
- **DB Helper**: Generic CRUD utilities for SQL/NoSQL databases.
|
|
33
|
+
- **Auth**: Secure JWT token management (creation and verification).
|
|
34
|
+
- **Error Handler**: Standardized API response formatting.
|
|
35
|
+
- **Utils**: Common helper functions (UUIDs, timestamps, etc.).
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install stackmate
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from stackmate.logger import AppLogger
|
|
47
|
+
from stackmate.auth import AuthManager
|
|
48
|
+
|
|
49
|
+
# Initialize components
|
|
50
|
+
logger = AppLogger("my-app")
|
|
51
|
+
auth = AuthManager(secret_key="your-secret-key")
|
|
52
|
+
|
|
53
|
+
# Use them in your application
|
|
54
|
+
token = auth.create_token({"user_id": 123})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Project Structure
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
stackmate/
|
|
61
|
+
├── stackmate/ # Core library files
|
|
62
|
+
├── examples/ # Example usage scripts
|
|
63
|
+
├── tests/ # Unit tests
|
|
64
|
+
├── pyproject.toml # Build configuration
|
|
65
|
+
└── README.md # Project documentation
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Author
|
|
69
|
+
|
|
70
|
+
- **Sudhakar K** - [sudhakark4227@gmail.com](mailto:sudhakark4227@gmail.com)
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
stackmate/__init__.py,sha256=IPfrLdFHIHgHB_4V3X3Hn-TqtCk6Dwm9lzAj1s452ak,591
|
|
2
|
+
stackmate/auth.py,sha256=B4tOtpXXxp1Ce017HLLgmSaRNAe03OF8FR1rG5vG384,2344
|
|
3
|
+
stackmate/db_helper.py,sha256=KpCXNCxl_8iXsNcdRUcstoZUJgDwhukK4laSL3BOpaY,2912
|
|
4
|
+
stackmate/error_handler.py,sha256=XYat-D9mlmUhcVCCUewsQYG2o7YOUW5zANPU2KD3w9I,2038
|
|
5
|
+
stackmate/logger.py,sha256=ya3nV6KA9RfIZ3uV2pvStchirMryO_SxCd5eOycy1L4,2876
|
|
6
|
+
stackmate/utils.py,sha256=COtTHEKU2t7IyBE5oB_-vC9KcM0O_gMQr5dG_UQglVo,1419
|
|
7
|
+
stackmate/validator.py,sha256=HcizDceTYQJYb29fwGs6HARauHa35LMikOhgdScJ6yc,2151
|
|
8
|
+
stackmate-0.1.0.dist-info/licenses/LICENSE,sha256=mpx1EG96iVtm54Ttxu_r5k9cj9Q6vjiozWO-n3UMTLM,1088
|
|
9
|
+
stackmate-0.1.0.dist-info/METADATA,sha256=_wNFezIWN-Wxj48wzVsMfMDxtJtEXcPw3Kxa_RgnjUA,2421
|
|
10
|
+
stackmate-0.1.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
|
|
11
|
+
stackmate-0.1.0.dist-info/top_level.txt,sha256=mV9VScpq-qTtrQJk9bHvvmQ-2L93_y25D4SeAB6t1CE,10
|
|
12
|
+
stackmate-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sudhakar K
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
stackmate
|