hypern 0.3.4__cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl → 0.3.5__cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.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.
Files changed (40) hide show
  1. hypern/{db → database}/sql/query.py +1 -1
  2. hypern/exceptions/__init__.py +34 -0
  3. hypern/exceptions/base.py +62 -0
  4. hypern/exceptions/common.py +12 -0
  5. hypern/exceptions/errors.py +15 -0
  6. hypern/exceptions/formatters.py +56 -0
  7. hypern/exceptions/http.py +76 -0
  8. hypern/hypern.cpython-311-i386-linux-gnu.so +0 -0
  9. hypern/middleware/security.py +6 -6
  10. hypern/processpool.py +24 -6
  11. hypern/response/response.py +8 -0
  12. hypern/routing/dispatcher.py +4 -5
  13. hypern/routing/parser.py +11 -13
  14. {hypern-0.3.4.dist-info → hypern-0.3.5.dist-info}/METADATA +2 -1
  15. {hypern-0.3.4.dist-info → hypern-0.3.5.dist-info}/RECORD +39 -34
  16. hypern/exceptions.py +0 -107
  17. /hypern/{db → database}/__init__.py +0 -0
  18. /hypern/{db → database}/addons/__init__.py +0 -0
  19. /hypern/{db → database}/addons/sqlalchemy/__init__.py +0 -0
  20. /hypern/{db → database}/addons/sqlalchemy/fields/__init__.py +0 -0
  21. /hypern/{db → database}/addons/sqlalchemy/fields/color.py +0 -0
  22. /hypern/{db → database}/addons/sqlalchemy/fields/daterange.py +0 -0
  23. /hypern/{db → database}/addons/sqlalchemy/fields/datetime.py +0 -0
  24. /hypern/{db → database}/addons/sqlalchemy/fields/encrypted.py +0 -0
  25. /hypern/{db → database}/addons/sqlalchemy/fields/password.py +0 -0
  26. /hypern/{db → database}/addons/sqlalchemy/fields/ts_vector.py +0 -0
  27. /hypern/{db → database}/addons/sqlalchemy/fields/unicode.py +0 -0
  28. /hypern/{db → database}/addons/sqlalchemy/repository.py +0 -0
  29. /hypern/{db → database}/nosql/__init__.py +0 -0
  30. /hypern/{db → database}/nosql/addons/__init__.py +0 -0
  31. /hypern/{db → database}/nosql/addons/color.py +0 -0
  32. /hypern/{db → database}/nosql/addons/daterange.py +0 -0
  33. /hypern/{db → database}/nosql/addons/encrypted.py +0 -0
  34. /hypern/{db → database}/nosql/addons/password.py +0 -0
  35. /hypern/{db → database}/nosql/addons/unicode.py +0 -0
  36. /hypern/{db → database}/sql/__init__.py +0 -0
  37. /hypern/{db → database}/sql/field.py +0 -0
  38. /hypern/{db → database}/sql/model.py +0 -0
  39. {hypern-0.3.4.dist-info → hypern-0.3.5.dist-info}/WHEEL +0 -0
  40. {hypern-0.3.4.dist-info → hypern-0.3.5.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  from enum import Enum
2
2
  from typing import Any, Dict, List, Tuple, Union
3
- from hypern.db.sql.field import ForeignKey
3
+ from hypern.database.sql.field import ForeignKey
4
4
 
5
5
 
6
6
  class JoinType(Enum):
@@ -0,0 +1,34 @@
1
+ from .base import HTTPException, ResponseFormatter, HypernError
2
+ from .errors import ErrorDefinitions
3
+ from .formatters import SimpleFormatter, DetailedFormatter, LocalizedFormatter
4
+ from .http import (
5
+ BadRequestException,
6
+ UnauthorizedException,
7
+ ForbiddenException,
8
+ NotFoundException,
9
+ ValidationException,
10
+ InternalServerException,
11
+ RateLimitException,
12
+ )
13
+
14
+ from .common import DBFieldValidationError, InvalidPortNumber, OutOfScopeApplicationException
15
+
16
+ __all__ = [
17
+ "HTTPException",
18
+ "ResponseFormatter",
19
+ "HypernError",
20
+ "ErrorDefinitions",
21
+ "SimpleFormatter",
22
+ "DetailedFormatter",
23
+ "LocalizedFormatter",
24
+ "BadRequestException",
25
+ "UnauthorizedException",
26
+ "ForbiddenException",
27
+ "NotFoundException",
28
+ "ValidationException",
29
+ "InternalServerException",
30
+ "RateLimitException",
31
+ "DBFieldValidationError",
32
+ "InvalidPortNumber",
33
+ "OutOfScopeApplicationException",
34
+ ]
@@ -0,0 +1,62 @@
1
+ import uuid
2
+ from abc import ABC, abstractmethod
3
+ from datetime import datetime, timezone
4
+ from http import HTTPStatus
5
+ from typing import Any, Dict, Optional
6
+
7
+
8
+ class ResponseFormatter(ABC):
9
+ @abstractmethod
10
+ def format_error(self, exception: "HTTPException") -> Dict[str, Any]:
11
+ """Format exception into response dictionary"""
12
+ pass
13
+
14
+
15
+ class DefaultFormatter(ResponseFormatter):
16
+ def format_error(self, exception: "HTTPException") -> Dict[str, Any]:
17
+ return {
18
+ "error": {
19
+ "code": exception.error.code if exception.error else "UNKNOWN_ERROR",
20
+ "message": exception.error.message if exception.error else "Unknown error occurred",
21
+ "details": exception.details or {},
22
+ "timestamp": datetime.now(tz=timezone.utc).isoformat(),
23
+ "request_id": str(uuid.uuid4()),
24
+ },
25
+ "status": exception.status_code,
26
+ }
27
+
28
+
29
+ class HypernError:
30
+ """Base error definition"""
31
+
32
+ def __init__(self, message: str, code: str):
33
+ self.message = message
34
+ self.code = code
35
+
36
+
37
+ class HTTPException(Exception):
38
+ """Base HTTP exception"""
39
+
40
+ _formatter: ResponseFormatter = DefaultFormatter()
41
+
42
+ @classmethod
43
+ def set_formatter(cls, formatter: ResponseFormatter):
44
+ cls._formatter = formatter
45
+
46
+ def __init__(
47
+ self,
48
+ status_code: int = HTTPStatus.BAD_REQUEST,
49
+ error: Optional[HypernError] = None,
50
+ details: Optional[Dict[str, Any]] = None,
51
+ headers: Optional[Dict[str, str]] = None,
52
+ formatter: Optional[ResponseFormatter] = None,
53
+ ):
54
+ self.status_code = status_code
55
+ self.error = error
56
+ self.details = details or {}
57
+ self.headers = headers or {}
58
+ self._instance_formatter = formatter
59
+
60
+ def to_dict(self) -> Dict[str, Any]:
61
+ formatter = self._instance_formatter or self._formatter
62
+ return formatter.format_error(self)
@@ -0,0 +1,12 @@
1
+ class InvalidPortNumber(Exception):
2
+ pass
3
+
4
+
5
+ class OutOfScopeApplicationException(Exception):
6
+ pass
7
+
8
+
9
+ class DBFieldValidationError(ValueError):
10
+ """Custom exception for field validation errors."""
11
+
12
+ pass
@@ -0,0 +1,15 @@
1
+ from .base import HypernError
2
+
3
+
4
+ class ErrorDefinitions:
5
+ """Standard error definitions"""
6
+
7
+ BAD_REQUEST = HypernError(message="Bad request", code="BAD_REQUEST")
8
+ UNAUTHORIZED = HypernError(message="Unauthorized access", code="UNAUTHORIZED")
9
+ FORBIDDEN = HypernError(message="Access forbidden", code="FORBIDDEN")
10
+ NOT_FOUND = HypernError(message="Resource not found", code="NOT_FOUND")
11
+ METHOD_NOT_ALLOWED = HypernError(message="Method not allowed", code="METHOD_NOT_ALLOWED")
12
+ VALIDATION_ERROR = HypernError(message="Validation error", code="VALIDATION_ERROR")
13
+ INTERNAL_ERROR = HypernError(message="Internal server error", code="INTERNAL_SERVER_ERROR")
14
+ CONFLICT = HypernError(message="Resource conflict", code="CONFLICT")
15
+ TOO_MANY_REQUESTS = HypernError(message="Too many requests", code="TOO_MANY_REQUESTS")
@@ -0,0 +1,56 @@
1
+ import uuid
2
+ from datetime import datetime, timezone
3
+ from typing import Any, Dict
4
+
5
+ from .base import HTTPException, ResponseFormatter
6
+
7
+
8
+ class SimpleFormatter(ResponseFormatter):
9
+ def format_error(self, exception: HTTPException) -> Dict[str, Any]:
10
+ return {
11
+ "code": exception.error.code if exception.error else "UNKNOWN_ERROR",
12
+ "message": exception.error.message if exception.error else "Unknown error occurred",
13
+ }
14
+
15
+
16
+ class DetailedFormatter(ResponseFormatter):
17
+ def format_error(self, exception: HTTPException) -> Dict[str, Any]:
18
+ return {
19
+ "status": {"code": exception.status_code, "text": str(exception.status_code)},
20
+ "error": {
21
+ "type": exception.error.code if exception.error else "UNKNOWN_ERROR",
22
+ "message": exception.error.message if exception.error else "Unknown error occurred",
23
+ "details": exception.details or {},
24
+ "timestamp": datetime.now(timezone.utc).isoformat(),
25
+ },
26
+ "request": {"path": exception.path, "id": str(uuid.uuid4())},
27
+ }
28
+
29
+
30
+ class LocalizedFormatter(ResponseFormatter):
31
+ def __init__(self, language: str = "en"):
32
+ self.language = language
33
+ self.translations = {
34
+ "en": {
35
+ "BAD_REQUEST": "Bad request",
36
+ "VALIDATION_ERROR": "Validation error",
37
+ "NOT_FOUND": "Resource not found",
38
+ # Add more translations
39
+ },
40
+ "vi": {
41
+ "BAD_REQUEST": "Yêu cầu không hợp lệ",
42
+ "VALIDATION_ERROR": "Lỗi xác thực",
43
+ "NOT_FOUND": "Không tìm thấy tài nguyên",
44
+ # Add more translations
45
+ },
46
+ }
47
+
48
+ def format_error(self, exception: HTTPException) -> Dict[str, Any]:
49
+ error_code = exception.error.code if exception.error else "UNKNOWN_ERROR"
50
+ translated_message = self.translations.get(self.language, {}).get(error_code, exception.error.message if exception.error else "Unknown error occurred")
51
+
52
+ return {
53
+ "error": {"code": error_code, "message": translated_message, "details": exception.details or {}},
54
+ "status": exception.status_code,
55
+ "timestamp": datetime.now(tz=timezone.utc).isoformat(),
56
+ }
@@ -0,0 +1,76 @@
1
+ from http import HTTPStatus
2
+ from typing import Any, Dict, Optional
3
+
4
+ from .base import HTTPException, ResponseFormatter, HypernError
5
+ from .errors import ErrorDefinitions
6
+
7
+
8
+ class BadRequestException(HTTPException):
9
+ def __init__(
10
+ self,
11
+ error: Optional[HypernError] = ErrorDefinitions.BAD_REQUEST,
12
+ details: Optional[Dict[str, Any]] = None,
13
+ headers: Optional[Dict[str, str]] = None,
14
+ formatter: Optional[ResponseFormatter] = None,
15
+ ):
16
+ super().__init__(status_code=HTTPStatus.BAD_REQUEST, error=error, details=details, headers=headers, formatter=formatter)
17
+
18
+
19
+ class UnauthorizedException(HTTPException):
20
+ def __init__(
21
+ self,
22
+ error: Optional[HypernError] = ErrorDefinitions.UNAUTHORIZED,
23
+ details: Optional[Dict[str, Any]] = None,
24
+ headers: Optional[Dict[str, str]] = None,
25
+ formatter: Optional[ResponseFormatter] = None,
26
+ ):
27
+ super().__init__(status_code=HTTPStatus.UNAUTHORIZED, error=error, details=details, headers=headers, formatter=formatter)
28
+
29
+
30
+ class ForbiddenException(HTTPException):
31
+ def __init__(
32
+ self,
33
+ error: Optional[HypernError] = ErrorDefinitions.FORBIDDEN,
34
+ details: Optional[Dict[str, Any]] = None,
35
+ headers: Optional[Dict[str, str]] = None,
36
+ formatter: Optional[ResponseFormatter] = None,
37
+ ):
38
+ super().__init__(status_code=HTTPStatus.FORBIDDEN, error=error, details=details, headers=headers, formatter=formatter)
39
+
40
+
41
+ class NotFoundException(HTTPException):
42
+ def __init__(
43
+ self,
44
+ error: Optional[HypernError] = ErrorDefinitions.NOT_FOUND,
45
+ details: Optional[Dict[str, Any]] = None,
46
+ headers: Optional[Dict[str, str]] = None,
47
+ formatter: Optional[ResponseFormatter] = None,
48
+ ):
49
+ super().__init__(status_code=HTTPStatus.NOT_FOUND, error=error, details=details, headers=headers, formatter=formatter)
50
+
51
+
52
+ class ValidationException(HTTPException):
53
+ def __init__(self, details: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None, formatter: Optional[ResponseFormatter] = None):
54
+ super().__init__(status_code=HTTPStatus.BAD_REQUEST, error=ErrorDefinitions.VALIDATION_ERROR, details=details, headers=headers, formatter=formatter)
55
+
56
+
57
+ class InternalServerException(HTTPException):
58
+ def __init__(
59
+ self,
60
+ error: Optional[HypernError] = ErrorDefinitions.INTERNAL_ERROR,
61
+ details: Optional[Dict[str, Any]] = None,
62
+ headers: Optional[Dict[str, str]] = None,
63
+ formatter: Optional[ResponseFormatter] = None,
64
+ ):
65
+ super().__init__(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, error=error, details=details, headers=headers, formatter=formatter)
66
+
67
+
68
+ class RateLimitException(HTTPException):
69
+ def __init__(self, retry_after: int, details: Optional[Dict[str, Any]] = None, formatter: Optional[ResponseFormatter] = None):
70
+ super().__init__(
71
+ status_code=HTTPStatus.TOO_MANY_REQUESTS,
72
+ error=ErrorDefinitions.TOO_MANY_REQUESTS,
73
+ details=details,
74
+ headers={"Retry-After": str(retry_after)},
75
+ formatter=formatter,
76
+ )
Binary file
@@ -9,7 +9,7 @@ from typing import Any, Dict, List, Optional
9
9
 
10
10
  import jwt
11
11
 
12
- from hypern.exceptions import Forbidden, Unauthorized
12
+ from hypern.exceptions import ForbiddenException, UnauthorizedException
13
13
  from hypern.hypern import Request, Response
14
14
  from .base import Middleware, MiddlewareConfig
15
15
 
@@ -91,9 +91,9 @@ class SecurityMiddleware(Middleware):
91
91
  payload = jwt.decode(token, self.secur_config.jwt_secret, algorithms=[self.secur_config.jwt_algorithm])
92
92
  return payload
93
93
  except jwt.ExpiredSignatureError:
94
- raise Unauthorized("Token has expired")
94
+ raise UnauthorizedException(details={"message": "Token has expired"})
95
95
  except jwt.InvalidTokenError:
96
- raise Unauthorized("Invalid token")
96
+ raise UnauthorizedException(details={"message": "Invalid token"})
97
97
 
98
98
  def _generate_csrf_token(self, session_id: str) -> str:
99
99
  """Generate a new CSRF token"""
@@ -155,18 +155,18 @@ class SecurityMiddleware(Middleware):
155
155
  if self.secur_config.jwt_auth:
156
156
  auth_header = request.headers.get("Authorization")
157
157
  if not auth_header or not auth_header.startswith("Bearer "):
158
- raise Unauthorized("Missing or invalid authorization header")
158
+ raise UnauthorizedException(details={"message": "Authorization header missing or invalid"})
159
159
  token = auth_header.split(" ")[1]
160
160
  try:
161
161
  request.user = self._verify_jwt_token(token)
162
- except Unauthorized as e:
162
+ except UnauthorizedException as e:
163
163
  return Response(status_code=401, description=str(e))
164
164
 
165
165
  # CSRF protection check
166
166
  if self.secur_config.csrf_protection and request.method in ["POST", "PUT", "DELETE", "PATCH"]:
167
167
  csrf_token = request.headers.get("X-CSRF-Token")
168
168
  if not csrf_token or not self._validate_csrf_token(csrf_token):
169
- raise Forbidden("CSRF token missing or invalid")
169
+ raise ForbiddenException(details={"message": "Invalid CSRF token"})
170
170
 
171
171
  return request
172
172
 
hypern/processpool.py CHANGED
@@ -3,7 +3,7 @@ import os
3
3
  import signal
4
4
  import sys
5
5
  from typing import List
6
-
6
+ from concurrent.futures import ThreadPoolExecutor
7
7
  from multiprocess import Process
8
8
  from watchdog.observers import Observer
9
9
 
@@ -76,7 +76,7 @@ def init_processpool(
76
76
  ) -> List[Process]:
77
77
  process_pool = []
78
78
 
79
- for _ in range(processes):
79
+ for i in range(processes):
80
80
  copied_socket = socket.try_clone()
81
81
  process = Process(
82
82
  target=spawn_process,
@@ -86,25 +86,43 @@ def init_processpool(
86
86
  workers,
87
87
  max_blocking_threads,
88
88
  ),
89
+ name=f"hypern-worker-{i}",
89
90
  )
91
+ process.daemon = True # This is important to avoid zombie processes
90
92
  process.start()
91
93
  process_pool.append(process)
92
94
 
93
95
  return process_pool
94
96
 
95
97
 
96
- def initialize_event_loop():
98
+ class OptimizedEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
99
+ def __init__(self, max_blocking_threads: int):
100
+ super().__init__()
101
+ self.max_blocking_threads = max_blocking_threads
102
+
103
+ def new_event_loop(self):
104
+ loop = super().new_event_loop()
105
+ # Optimize thread pool cho I/O operations
106
+ loop.set_default_executor(ThreadPoolExecutor(max_workers=self.max_blocking_threads, thread_name_prefix="hypern-io"))
107
+ return loop
108
+
109
+
110
+ def initialize_event_loop(max_blocking_threads: int = 100) -> asyncio.AbstractEventLoop:
97
111
  if sys.platform.startswith("win32") or sys.platform.startswith("linux-cross"):
98
112
  loop = asyncio.new_event_loop()
99
113
  asyncio.set_event_loop(loop)
100
- return loop
101
114
  else:
102
115
  import uvloop
103
116
 
104
117
  uvloop.install()
118
+
119
+ asyncio.set_event_loop_policy(OptimizedEventLoopPolicy(max_blocking_threads))
105
120
  loop = uvloop.new_event_loop()
106
121
  asyncio.set_event_loop(loop)
107
- return loop
122
+
123
+ loop.slow_callback_duration = 0.1 # Log warnings for slow callbacks
124
+ loop.set_debug(False) # Disable debug mode
125
+ return loop
108
126
 
109
127
 
110
128
  def spawn_process(
@@ -113,7 +131,7 @@ def spawn_process(
113
131
  workers: int,
114
132
  max_blocking_threads: int,
115
133
  ):
116
- loop = initialize_event_loop()
134
+ loop = initialize_event_loop(max_blocking_threads)
117
135
 
118
136
  try:
119
137
  server.start(socket, workers, max_blocking_threads)
@@ -4,6 +4,7 @@ import typing
4
4
  from urllib.parse import quote
5
5
  from hypern.hypern import Response as InternalResponse, Header
6
6
  import orjson
7
+ import msgpack
7
8
 
8
9
  from hypern.background import BackgroundTask, BackgroundTasks
9
10
 
@@ -132,3 +133,10 @@ class FileResponse(BaseResponse):
132
133
  self.raw_headers["content-disposition"] = f'attachment; filename="{filename}"'
133
134
  self.raw_headers.setdefault("content-type", "application/octet-stream")
134
135
  self.raw_headers.setdefault("content-length", str(len(content)))
136
+
137
+
138
+ @to_response
139
+ class BinaryResponse(BaseResponse):
140
+ def __init__(self, content: bytes):
141
+ super().__init__(status_code=200, media_type="application/x-msgpack", headers={"Content-Type": "application/x-msgpack"})
142
+ self.content = msgpack.packb(content)
@@ -10,7 +10,7 @@ import typing
10
10
  import orjson
11
11
  from pydantic import BaseModel
12
12
 
13
- from hypern.exceptions import BaseException
13
+ from hypern.exceptions import HTTPException
14
14
  from hypern.hypern import Request, Response
15
15
  from hypern.response import JSONResponse
16
16
 
@@ -56,10 +56,9 @@ async def dispatch(handler, request: Request, inject: typing.Dict[str, typing.An
56
56
 
57
57
  except Exception as e:
58
58
  _res: typing.Dict = {"message": "", "error_code": "UNKNOWN_ERROR"}
59
- if isinstance(e, BaseException):
60
- _res["error_code"] = e.error_code
61
- _res["message"] = e.msg
62
- _status = e.status
59
+ if isinstance(e, HTTPException):
60
+ _res = e.to_dict()
61
+ _status = e.status_code
63
62
  else:
64
63
  traceback.print_exc()
65
64
  _res["message"] = str(e)
hypern/routing/parser.py CHANGED
@@ -9,8 +9,8 @@ from pydantic import BaseModel, ValidationError
9
9
  from pydash import get
10
10
 
11
11
  from hypern.auth.authorization import Authorization
12
- from hypern.exceptions import BadRequest
13
- from hypern.exceptions import ValidationError as HypernValidationError
12
+ from hypern.exceptions import BadRequestException
13
+ from hypern.exceptions import ValidationException
14
14
  from hypern.hypern import Request
15
15
 
16
16
 
@@ -28,7 +28,7 @@ class ParamParser:
28
28
 
29
29
  parser = data_parsers.get(param_name)
30
30
  if not parser:
31
- raise BadRequest(msg="Backend Error: Invalid parameter type, must be query_params, path_params or form_data.")
31
+ raise BadRequestException(details={"message": f"Invalid parameter name: {param_name}"})
32
32
  return parser()
33
33
 
34
34
  def _parse_query_params(self) -> dict:
@@ -53,16 +53,14 @@ class InputHandler:
53
53
  return model_class(**data)
54
54
  except ValidationError as e:
55
55
  invalid_fields = orjson.loads(e.json())
56
- raise HypernValidationError(
57
- msg=orjson.dumps(
58
- [
59
- {
60
- "field": get(item, "loc")[0],
61
- "msg": get(item, "msg"),
62
- }
63
- for item in invalid_fields
64
- ]
65
- ).decode("utf-8"),
56
+ raise ValidationException(
57
+ details=[
58
+ {
59
+ "field": get(item, "loc")[0],
60
+ "msg": get(item, "msg"),
61
+ }
62
+ for item in invalid_fields
63
+ ]
66
64
  )
67
65
 
68
66
  async def handle_special_params(self, param_name: str) -> typing.Any:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypern
3
- Version: 0.3.4
3
+ Version: 0.3.5
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -25,6 +25,7 @@ Requires-Dist: cryptography ==43.0.3
25
25
  Requires-Dist: watchdog ==6.0.0
26
26
  Requires-Dist: jsonschema ==4.23.0
27
27
  Requires-Dist: psutil ==6.1.0
28
+ Requires-Dist: msgpack ==1.1.0
28
29
  License-File: LICENSE
29
30
  Summary: A Fast Async Python backend with a Rust runtime.
30
31
  Author-email: Martin Dang <vannghiem848@gmail.com>
@@ -1,7 +1,6 @@
1
- hypern-0.3.4.dist-info/METADATA,sha256=6lG_RNIeI43JEIwErMWPFmc9byTrMQOkm-akGhEYvVA,3723
2
- hypern-0.3.4.dist-info/WHEEL,sha256=7tIgc9iVs-udH1vh5eIZ1Q0fZTSpFzTPubZ0mCMu2bY,125
3
- hypern-0.3.4.dist-info/licenses/LICENSE,sha256=VdbaK2hSaaD-LUjtDIlEbeZVmvLGK7BEQvltP3mv-cY,1304
4
- hypern/exceptions.py,sha256=YjWcXfBbM0srzcCcYu6raw0KavcH_iVlr2RGuxw09M0,2501
1
+ hypern-0.3.5.dist-info/METADATA,sha256=3YWjQNKci-jBTZGWJX-ue43rETDHtkxN5jA_trYz4tM,3754
2
+ hypern-0.3.5.dist-info/WHEEL,sha256=7tIgc9iVs-udH1vh5eIZ1Q0fZTSpFzTPubZ0mCMu2bY,125
3
+ hypern-0.3.5.dist-info/licenses/LICENSE,sha256=VdbaK2hSaaD-LUjtDIlEbeZVmvLGK7BEQvltP3mv-cY,1304
5
4
  hypern/args_parser.py,sha256=jDcON-mVqYTPrBirMkmhH6Gm2QhS9rV2u_72SyoYSdY,2723
6
5
  hypern/gateway/aggregator.py,sha256=Z4LnsDlVDtlPlhsSKu8jCD0UsbztXOLu6UAVtkgJwQk,1100
7
6
  hypern/gateway/gateway.py,sha256=rAZrS9db55tQGUfEfVNIKw6EetBdHAcSXyrC7rLfCZ8,1434
@@ -17,41 +16,18 @@ hypern/middleware/compress.py,sha256=2eyxkYMgmsL6klbcTqr7WK0rFTo0grU0ZKQF15pVUBI
17
16
  hypern/middleware/cache.py,sha256=b4hRh1smFwhJE789hZ0p4TlkQ8ZjYR-7fXg9rI7uvbc,7406
18
17
  hypern/middleware/i18n.py,sha256=s82nQo6kKClZ0s3G3jsy87VRfwxpBDbASB_ErjRL3O0,15
19
18
  hypern/middleware/cors.py,sha256=q8Ts_znqApdUJYSJyLlRIbYKxxTQy6WNnJD6Kqbl32I,1759
20
- hypern/middleware/security.py,sha256=vteO6ISGF1okPP2tn0dCURyKv7J04i6FN2FU5KXmNaU,7355
19
+ hypern/middleware/security.py,sha256=hPYsilqhF9mRCX7DzOQw4AKh0y5k5FL0cM_zQdb9tiA,7491
21
20
  hypern/openapi/schemas.py,sha256=nmcmNYvKmjNkwFqi_3qpXVi1ukanNxMVay68bOLTrx8,1624
22
21
  hypern/openapi/__init__.py,sha256=oJ0HM9yAgSN00mBC_fRgV2irlGugrhvIpiveuDMv8PM,136
23
22
  hypern/openapi/swagger.py,sha256=E5fHYUfFa77zQsCyQGf_vnqJVpl4_KI5qsKFHdgJEdw,61
24
- hypern/db/sql/field.py,sha256=a_AVQP2r08RZG9twN3bWLB3QQHQIZq-J7HpAto01q2g,19466
25
- hypern/db/sql/model.py,sha256=VV5pmNacgyZEWb1MvBGxBd9RNaL8gywlKO447CK_3VA,3797
26
- hypern/db/sql/__init__.py,sha256=YjhnqREh4vWkcwcMXHYMMRVjx2_ew-ngqY50AGOVl48,248
27
- hypern/db/sql/query.py,sha256=huPnehqK_Hb1WiuyLQizu0VKrBG-0MzKR1V7z5NQokE,32425
28
- hypern/db/nosql/__init__.py,sha256=LCVBhcJCQmFt5dCLiSf7C_TsjsEILeZe8JqiFEKuD2s,619
29
- hypern/db/nosql/addons/password.py,sha256=kbqQRzT5uq9IQ4Z_eE69cVo1rHTiovhtG3I0l5AZmMk,4901
30
- hypern/db/nosql/addons/__init__.py,sha256=h6wJKPvCqyvivD52L7qsbFKnqqUnAdU1RQ30spnki98,121
31
- hypern/db/nosql/addons/unicode.py,sha256=vKyqfzrS9SKFo4eKlvu6klST0FrjM0wTx5N3ocvSSO8,258
32
- hypern/db/nosql/addons/encrypted.py,sha256=bbJozZfcsWvumqHYOrN1Y8XrwRZqaR-z__u11GEmIv4,1688
33
- hypern/db/nosql/addons/color.py,sha256=8zUBFjR19J1zy_WaOCXlS14GjgdOaHAcuSb__zFp_II,430
34
- hypern/db/nosql/addons/daterange.py,sha256=YJBVfiX13Wx8DZociajWLBm20L_c0ZxTUbgCYMNk10Q,1162
35
- hypern/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- hypern/db/addons/__init__.py,sha256=rzwN5hPXja_TLGUu863QQLSyQ1zbNNeYXfDVboxQE2I,58
37
- hypern/db/addons/sqlalchemy/__init__.py,sha256=LAhAdJRNu_izh0X9KbesuJiF33oEQ6ET_tkAkR74Lpw,2695
38
- hypern/db/addons/sqlalchemy/fields/password.py,sha256=SnPKke6YAyq4LRYMMHp1qGj5jKIVSU5GFV6Y4ungaRo,5618
39
- hypern/db/addons/sqlalchemy/fields/__init__.py,sha256=gZpp75nCNZHx9VDw5aNEmJzlpvVKv7Tulp40-Z7-ULM,345
40
- hypern/db/addons/sqlalchemy/fields/unicode.py,sha256=gvsWvt0gTEwy62U4l6yDQjEXfc982QAaVay3YfxD3do,396
41
- hypern/db/addons/sqlalchemy/fields/encrypted.py,sha256=TmbpI0XE4_GYYAnHwbx3lVqD5BewcMedHcD-18eWUJA,1872
42
- hypern/db/addons/sqlalchemy/fields/color.py,sha256=dxfY2K0RTIdwlul75y-Vs8ldRs-2UYMBZnTkvVATA1U,464
43
- hypern/db/addons/sqlalchemy/fields/datetime.py,sha256=vZEV0s8M6VlsV9DDcEsCFIwoEAi_vNGY5HGFGULc0H0,621
44
- hypern/db/addons/sqlalchemy/fields/daterange.py,sha256=zeylGZc4JWVzLJRQi1DjP_LAvB3JNBNYwAa-KSolZyQ,830
45
- hypern/db/addons/sqlalchemy/fields/ts_vector.py,sha256=xmh-iLLGG5uW4QL_cnONdQd5rEfYZpNXaX_rW2kBrZU,1315
46
- hypern/db/addons/sqlalchemy/repository.py,sha256=YShEl1DqRXtYwNnn1F3YVfXX-TEdoNRjDEWIO_3Lu2s,9226
47
23
  hypern/hypern.pyi,sha256=jdjclVZUpYPhJOy6kGBKXTbbVwm6x163twSk0N7l9fI,9008
48
- hypern/routing/dispatcher.py,sha256=ksPjd-JnOCvrmyWodJhsLm02S5R8BrSlW4SdtG86G0w,2437
24
+ hypern/routing/dispatcher.py,sha256=8_JuxyyOMiCqY3WsqcjSzUTpYjIGbvzGtI8j9T-fIkA,2391
49
25
  hypern/routing/route.py,sha256=AZc4Qo5iy74q0_U8E5X6RIsudznHZYEZR8MdHRoCmB4,10119
50
- hypern/routing/parser.py,sha256=4BFn8MAmSX1QplwBXEEgbabYiNUAllYf2svPZoPPD5k,3454
26
+ hypern/routing/parser.py,sha256=VYdQtf9TPe-NSx3J2wCfOZIh1S-iFLf0jdqrY9UPVMQ,3328
51
27
  hypern/routing/__init__.py,sha256=FvmUQlSraZ91q9AFGkgj3ELIep1jiKZLBCDrXIVf5DI,157
52
28
  hypern/routing/queue.py,sha256=Yus-49N4xc7O5S3YYxqL0muFLypu_Zgd0u2SADFh-Uk,7001
53
29
  hypern/routing/endpoint.py,sha256=AWLHLQNlSGR8IGU6xM0RP-1kP06OJQzqpbXKSiZEzEo,996
54
- hypern/response/response.py,sha256=s6KqscjA7jl8RaZh5gZQgVksPtHKzsRrQywDcEjVSR4,4448
30
+ hypern/response/response.py,sha256=_UbLlzEfDZvXKHDKOdXFdus-CJXgoNFPmV259cjQz2Q,4729
55
31
  hypern/response/__init__.py,sha256=9z99BDgASpG404GK8LGkOsXgac0wFwH_cQOTI5Ju-1U,223
56
32
  hypern/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
33
  hypern/cli/commands.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -62,7 +38,7 @@ hypern/worker.py,sha256=kN93QGx4bst0inHRO_fsTzMmhDA0N3pdzaqNXwyu3N0,894
62
38
  hypern/__init__.py,sha256=Ew7xzNI_FIXpXin5vgv6det0lVYxGI8Xtbtger3Y5JY,115
63
39
  hypern/reload.py,sha256=Y2pjHHh8Zv0z-pRkBPLezKiowRblb1ZJ7yI_oE55D4U,1523
64
40
  hypern/background.py,sha256=fN38UlJG6wZf1gOGcvdY-INoD8zJKvGZZOdVYTMjDwg,120
65
- hypern/processpool.py,sha256=TuqcHMpSdXNSOZi3DKgUINAS03sTDn9tRAJQ63YPYZU,2847
41
+ hypern/processpool.py,sha256=7DSUMKy0IL6D3822W-XseH6oAU2MCmb-wKRt_80RuZE,3744
66
42
  hypern/caching/__init__.py,sha256=I7X3bmdEHeHs80kjAI1s0mMlVD7RKmw9I-QupaTAIWo,346
67
43
  hypern/caching/backend.py,sha256=Tj66YSepGUvpXrwC04gSdJzs45IepHA2hNlMtnRVB6c,798
68
44
  hypern/caching/redis_backend.py,sha256=nRkAq07B248iFljn9TxE4tadYUeM8RqqERZWzEpfk7E,5767
@@ -70,7 +46,36 @@ hypern/caching/strategies.py,sha256=VU0FpYmIK6rEjjJSwRXPrprYdo0d2u1s9OxB3OAvs3g,
70
46
  hypern/i18n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
47
  hypern/config.py,sha256=Ksn2LnHU0yhtGUjnac9bNjqtxl7IcPKmMdbDfZYm7Jo,7911
72
48
  hypern/application.py,sha256=S80VpC5H0Xna7AHoF_nEGeKfQAv4QTBnJ7KJalrIp7k,17894
49
+ hypern/database/sql/field.py,sha256=a_AVQP2r08RZG9twN3bWLB3QQHQIZq-J7HpAto01q2g,19466
50
+ hypern/database/sql/model.py,sha256=VV5pmNacgyZEWb1MvBGxBd9RNaL8gywlKO447CK_3VA,3797
51
+ hypern/database/sql/__init__.py,sha256=YjhnqREh4vWkcwcMXHYMMRVjx2_ew-ngqY50AGOVl48,248
52
+ hypern/database/sql/query.py,sha256=MWSN1aVswSchw-LWj1j8nKJi_QkJXz8x4a_YsOVx9ek,32431
53
+ hypern/database/nosql/__init__.py,sha256=LCVBhcJCQmFt5dCLiSf7C_TsjsEILeZe8JqiFEKuD2s,619
54
+ hypern/database/nosql/addons/password.py,sha256=kbqQRzT5uq9IQ4Z_eE69cVo1rHTiovhtG3I0l5AZmMk,4901
55
+ hypern/database/nosql/addons/__init__.py,sha256=h6wJKPvCqyvivD52L7qsbFKnqqUnAdU1RQ30spnki98,121
56
+ hypern/database/nosql/addons/unicode.py,sha256=vKyqfzrS9SKFo4eKlvu6klST0FrjM0wTx5N3ocvSSO8,258
57
+ hypern/database/nosql/addons/encrypted.py,sha256=bbJozZfcsWvumqHYOrN1Y8XrwRZqaR-z__u11GEmIv4,1688
58
+ hypern/database/nosql/addons/color.py,sha256=8zUBFjR19J1zy_WaOCXlS14GjgdOaHAcuSb__zFp_II,430
59
+ hypern/database/nosql/addons/daterange.py,sha256=YJBVfiX13Wx8DZociajWLBm20L_c0ZxTUbgCYMNk10Q,1162
60
+ hypern/database/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ hypern/database/addons/__init__.py,sha256=rzwN5hPXja_TLGUu863QQLSyQ1zbNNeYXfDVboxQE2I,58
62
+ hypern/database/addons/sqlalchemy/__init__.py,sha256=LAhAdJRNu_izh0X9KbesuJiF33oEQ6ET_tkAkR74Lpw,2695
63
+ hypern/database/addons/sqlalchemy/fields/password.py,sha256=SnPKke6YAyq4LRYMMHp1qGj5jKIVSU5GFV6Y4ungaRo,5618
64
+ hypern/database/addons/sqlalchemy/fields/__init__.py,sha256=gZpp75nCNZHx9VDw5aNEmJzlpvVKv7Tulp40-Z7-ULM,345
65
+ hypern/database/addons/sqlalchemy/fields/unicode.py,sha256=gvsWvt0gTEwy62U4l6yDQjEXfc982QAaVay3YfxD3do,396
66
+ hypern/database/addons/sqlalchemy/fields/encrypted.py,sha256=TmbpI0XE4_GYYAnHwbx3lVqD5BewcMedHcD-18eWUJA,1872
67
+ hypern/database/addons/sqlalchemy/fields/color.py,sha256=dxfY2K0RTIdwlul75y-Vs8ldRs-2UYMBZnTkvVATA1U,464
68
+ hypern/database/addons/sqlalchemy/fields/datetime.py,sha256=vZEV0s8M6VlsV9DDcEsCFIwoEAi_vNGY5HGFGULc0H0,621
69
+ hypern/database/addons/sqlalchemy/fields/daterange.py,sha256=zeylGZc4JWVzLJRQi1DjP_LAvB3JNBNYwAa-KSolZyQ,830
70
+ hypern/database/addons/sqlalchemy/fields/ts_vector.py,sha256=xmh-iLLGG5uW4QL_cnONdQd5rEfYZpNXaX_rW2kBrZU,1315
71
+ hypern/database/addons/sqlalchemy/repository.py,sha256=YShEl1DqRXtYwNnn1F3YVfXX-TEdoNRjDEWIO_3Lu2s,9226
73
72
  hypern/enum.py,sha256=-StRU0cWboP-y5fNuhB4Q7yMk8Zm_h1Eua9KzOtIyI8,347
73
+ hypern/exceptions/common.py,sha256=p9cx3PC6Azn0WAz7jCH02DEoLRLCCvKqNrL-dGhMGSQ,215
74
+ hypern/exceptions/formatters.py,sha256=51krRQIUq3uvwvcQm81mYPifdp2r2ckwC98pXI5v_P8,2330
75
+ hypern/exceptions/__init__.py,sha256=t4GhxGHjOPgPQ34f0MycMjoRGw5u3TRb3OcTDYc4Orw,936
76
+ hypern/exceptions/errors.py,sha256=mt6ZXUGHFZ_FfyP7sZFj4XT6amb5G-1Fa_26rH7BSWc,842
77
+ hypern/exceptions/http.py,sha256=N98kHaQtH4x9EW6Gavrcr-Ll_-HDvsDSaRAX1sNuN4A,3150
78
+ hypern/exceptions/base.py,sha256=_tt42Tuy_7oXR-THhJ00lZFsCJMKWbArJyTlF-kcgH4,1955
74
79
  hypern/logging/__init__.py,sha256=lzYSz0382eIM3CvP0sZ6RbEEwYZwfeJEJh9cxQA6Rws,49
75
80
  hypern/logging/logger.py,sha256=62Qg4YAi_JDGV72Rd6R58jixqZk7anRqHbtnuBlkrwA,3174
76
81
  hypern/scheduler.py,sha256=nQoWIYMRmKd30g4XwdB072hWTNHvJlLd9S6rLlTFKS0,62
@@ -80,5 +85,5 @@ hypern/ws/room.py,sha256=9u6gLq1WY4hn9_yEniavaY0yetFbQzgya_g6VPN-cgg,2522
80
85
  hypern/ws/heartbeat.py,sha256=PIrYWnQn8VxQjfDXDmtMymMl-wN5MQ_Q6oHfAjPWznU,2787
81
86
  hypern/ws/route.py,sha256=8YPTf1fsF46oCyqoXePC3mEbhjNVFDp8rqyWSsBHhBA,777
82
87
  hypern/ws/__init__.py,sha256=iUYERiHxs7HCmHj7CS5iG2XewKAJgW7w8kqxSORu_N8,127
83
- hypern/hypern.cpython-311-i386-linux-gnu.so,sha256=zpQIY2ZzCRfJVylyoOv5X7UuqH_5A8fivghQkpcQ6Uo,12060284
84
- hypern-0.3.4.dist-info/RECORD,,
88
+ hypern/hypern.cpython-311-i386-linux-gnu.so,sha256=ejbRZl5HfgGT3ItZU08gF33fXrOCtySg8RT_8ESXc4g,12039804
89
+ hypern-0.3.5.dist-info/RECORD,,
hypern/exceptions.py DELETED
@@ -1,107 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from typing import Any
3
- from hypern.enum import ErrorCode
4
-
5
-
6
- class BaseException(Exception):
7
- def __init__(self, msg: str = "", *args: Any) -> None:
8
- super().__init__(*args)
9
- self.msg = msg
10
- self.status = 400
11
- self.error_code = ErrorCode.UNKNOWN_ERROR
12
-
13
-
14
- class BadRequest(BaseException):
15
- def __init__(
16
- self,
17
- msg: str = "Bad request",
18
- error_code: str = ErrorCode.BAD_REQUEST,
19
- *args: Any,
20
- ) -> None:
21
- super().__init__(msg, *args)
22
- self.error_code = error_code
23
-
24
-
25
- class ValidationError(BaseException):
26
- def __init__(
27
- self,
28
- msg: str = "Validation error",
29
- error_code: str = ErrorCode.VALIDATION_ERROR,
30
- *args: Any,
31
- ) -> None:
32
- super().__init__(msg, *args)
33
- self.error_code = error_code
34
-
35
-
36
- class Forbidden(BaseException):
37
- def __init__(
38
- self,
39
- msg: str = "Forbidden",
40
- error_code: str = ErrorCode.FORBIDDEN,
41
- *args: Any,
42
- ) -> None:
43
- super().__init__(msg, *args)
44
- self.status = 403
45
- self.error_code = error_code
46
-
47
-
48
- class NotFound(BaseException):
49
- def __init__(
50
- self,
51
- msg: str = "NotFound",
52
- error_code: str = ErrorCode.NOT_FOUND,
53
- *args: Any,
54
- ) -> None:
55
- super().__init__(msg, *args)
56
- self.status = 404
57
- self.error_code = error_code
58
-
59
-
60
- class MethodNotAllow(BaseException):
61
- def __init__(
62
- self,
63
- msg: str = "Method not allow",
64
- error_code: str = ErrorCode.METHOD_NOT_ALLOW,
65
- *args: Any,
66
- ) -> None:
67
- super().__init__(msg, *args)
68
- self.status = 405
69
- self.error_code = error_code
70
-
71
-
72
- class InternalServer(BaseException):
73
- def __init__(
74
- self,
75
- msg: str = "Internal server error",
76
- error_code: str = ErrorCode.SERVER_ERROR,
77
- *args: Any,
78
- ) -> None:
79
- super().__init__(msg, *args)
80
- self.status = 500
81
- self.error_code = error_code
82
-
83
-
84
- class Unauthorized(BaseException):
85
- def __init__(
86
- self,
87
- msg: str = "Unauthorized",
88
- error_code: str = ErrorCode.UNAUTHORIZED,
89
- *args: Any,
90
- ) -> None:
91
- super().__init__(msg, *args)
92
- self.status = 401
93
- self.error_code = error_code
94
-
95
-
96
- class InvalidPortNumber(Exception):
97
- pass
98
-
99
-
100
- class OutOfScopeApplicationException(Exception):
101
- pass
102
-
103
-
104
- class DBFieldValidationError(ValueError):
105
- """Custom exception for field validation errors."""
106
-
107
- pass
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes