pyrestkit 1.2.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.
Files changed (115) hide show
  1. pyrestkit/__init__.py +35 -0
  2. pyrestkit/ai/__init__.py +17 -0
  3. pyrestkit/ai/analyzer.py +137 -0
  4. pyrestkit/ai/client.py +101 -0
  5. pyrestkit/ai/config/__init__.py +5 -0
  6. pyrestkit/ai/config/ai_config.py +200 -0
  7. pyrestkit/ai/exceptions.py +22 -0
  8. pyrestkit/ai/generators/__init__.py +0 -0
  9. pyrestkit/ai/models.py +44 -0
  10. pyrestkit/ai/parsers/__init__.py +0 -0
  11. pyrestkit/ai/prompts/failure_analysis.md +21 -0
  12. pyrestkit/ai/provider.py +58 -0
  13. pyrestkit/ai/providers/__init__.py +21 -0
  14. pyrestkit/ai/providers/anthropic.py +85 -0
  15. pyrestkit/ai/providers/azure_openai.py +84 -0
  16. pyrestkit/ai/providers/base.py +39 -0
  17. pyrestkit/ai/providers/bedrock.py +70 -0
  18. pyrestkit/ai/providers/cohere.py +82 -0
  19. pyrestkit/ai/providers/gemini.py +113 -0
  20. pyrestkit/ai/providers/groq.py +81 -0
  21. pyrestkit/ai/providers/mistral.py +88 -0
  22. pyrestkit/ai/providers/ollama.py +82 -0
  23. pyrestkit/ai/providers/openai.py +124 -0
  24. pyrestkit/ai/utils/__init__.py +0 -0
  25. pyrestkit/ai/utils/prompt_loader.py +52 -0
  26. pyrestkit/assertions/__init__.py +7 -0
  27. pyrestkit/assertions/assertion_exception.py +4 -0
  28. pyrestkit/assertions/response_assertions.py +181 -0
  29. pyrestkit/auth/__init__.py +11 -0
  30. pyrestkit/auth/auth_strategy.py +14 -0
  31. pyrestkit/auth/authentication_manager.py +35 -0
  32. pyrestkit/auth/strategies/__init__.py +5 -0
  33. pyrestkit/auth/strategies/api_key_auth.py +18 -0
  34. pyrestkit/auth/strategies/basic_auth.py +24 -0
  35. pyrestkit/auth/strategies/bearer_auth.py +17 -0
  36. pyrestkit/auth/token_cache.py +44 -0
  37. pyrestkit/auth/token_manager.py +32 -0
  38. pyrestkit/auth/token_provider.py +12 -0
  39. pyrestkit/auth/token_response.py +13 -0
  40. pyrestkit/builder/__init__.py +5 -0
  41. pyrestkit/builder/fluent_request_builder.py +167 -0
  42. pyrestkit/clients/__init__.py +7 -0
  43. pyrestkit/clients/base_client.py +68 -0
  44. pyrestkit/clients/user_client.py +66 -0
  45. pyrestkit/config/__init__.py +5 -0
  46. pyrestkit/config/config.py +97 -0
  47. pyrestkit/constants/__init__.py +0 -0
  48. pyrestkit/constants/content_types.py +0 -0
  49. pyrestkit/constants/headers.py +0 -0
  50. pyrestkit/constants/status_codes.py +0 -0
  51. pyrestkit/core/__init__.py +13 -0
  52. pyrestkit/core/api_client.py +129 -0
  53. pyrestkit/core/logger.py +41 -0
  54. pyrestkit/core/request_builder.py +45 -0
  55. pyrestkit/core/request_executor.py +64 -0
  56. pyrestkit/core/request_logger.py +0 -0
  57. pyrestkit/core/response_logger.py +0 -0
  58. pyrestkit/core/session_manager.py +19 -0
  59. pyrestkit/database/__init__.py +0 -0
  60. pyrestkit/endpoints/__init__.py +5 -0
  61. pyrestkit/endpoints/base_endpoints.py +32 -0
  62. pyrestkit/endpoints/order_endpoints.py +9 -0
  63. pyrestkit/endpoints/payment_endpoints.py +5 -0
  64. pyrestkit/endpoints/user_endpoints.py +48 -0
  65. pyrestkit/exceptions/__init__.py +21 -0
  66. pyrestkit/exceptions/api_exception.py +8 -0
  67. pyrestkit/exceptions/authentication_exception.py +10 -0
  68. pyrestkit/exceptions/configuration_exception.py +10 -0
  69. pyrestkit/exceptions/exception_mapper.py +32 -0
  70. pyrestkit/exceptions/network_exception.py +10 -0
  71. pyrestkit/exceptions/response_exception.py +10 -0
  72. pyrestkit/exceptions/serialization_exception.py +10 -0
  73. pyrestkit/exceptions/validation_exception.py +10 -0
  74. pyrestkit/factories/__init__.py +5 -0
  75. pyrestkit/factories/base_factory.py +25 -0
  76. pyrestkit/factories/user_factory.py +37 -0
  77. pyrestkit/hooks/__init__.py +5 -0
  78. pyrestkit/hooks/hook.py +27 -0
  79. pyrestkit/hooks/hook_manager.py +39 -0
  80. pyrestkit/hooks/request_hook.py +18 -0
  81. pyrestkit/hooks/response_hook.py +17 -0
  82. pyrestkit/hooks/timing_hook.py +32 -0
  83. pyrestkit/models/__init__.py +8 -0
  84. pyrestkit/models/base_response.py +11 -0
  85. pyrestkit/models/request/__init__.py +7 -0
  86. pyrestkit/models/request/create_user_request.py +11 -0
  87. pyrestkit/models/request/update_user_request.py +10 -0
  88. pyrestkit/models/response/__init__.py +5 -0
  89. pyrestkit/models/response/create_user_response.py +26 -0
  90. pyrestkit/models/response/get_user_response.py +28 -0
  91. pyrestkit/models/response/user_response.py +12 -0
  92. pyrestkit/pipeline/__init__.py +5 -0
  93. pyrestkit/pipeline/middleware.py +18 -0
  94. pyrestkit/pipeline/middleware_chain.py +11 -0
  95. pyrestkit/pipeline/pipeline.py +27 -0
  96. pyrestkit/pipeline/request_context.py +26 -0
  97. pyrestkit/response/__init__.py +8 -0
  98. pyrestkit/response/framework_response.py +271 -0
  99. pyrestkit/response/response_body.py +124 -0
  100. pyrestkit/retry/__init__.py +5 -0
  101. pyrestkit/retry/backoff.py +32 -0
  102. pyrestkit/retry/retry_handler.py +52 -0
  103. pyrestkit/retry/retry_policy.py +33 -0
  104. pyrestkit/serializers/__init__.py +0 -0
  105. pyrestkit/serializers/response_mapper.py +25 -0
  106. pyrestkit/types/__init__.py +0 -0
  107. pyrestkit/types/model_protocol.py +17 -0
  108. pyrestkit/utils/__init__.py +0 -0
  109. pyrestkit/validators/__init__.py +7 -0
  110. pyrestkit/validators/response_validator.py +57 -0
  111. pyrestkit/validators/schema_validator.py +33 -0
  112. pyrestkit-1.2.0.dist-info/METADATA +741 -0
  113. pyrestkit-1.2.0.dist-info/RECORD +115 -0
  114. pyrestkit-1.2.0.dist-info/WHEEL +5 -0
  115. pyrestkit-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from pyrestkit.config.config import ConfigManager
6
+ from pyrestkit.core.logger import FrameworkLogger
7
+ from pyrestkit.core.session_manager import SessionManager
8
+ from pyrestkit.exceptions.exception_mapper import ExceptionMapper
9
+ from pyrestkit.hooks.hook_manager import HookManager
10
+ from pyrestkit.response.framework_response import FrameworkResponse
11
+
12
+
13
+ class RequestExecutor:
14
+ """
15
+ Executes HTTP requests using the configured session.
16
+ """
17
+
18
+ def __init__(
19
+ self,
20
+ config: ConfigManager,
21
+ session_manager: SessionManager,
22
+ hook_manager: HookManager | None = None,
23
+ ) -> None:
24
+ self._config = config
25
+ self._session = session_manager.session
26
+ self._logger = FrameworkLogger.get_logger()
27
+ self._hook_manager = hook_manager or HookManager()
28
+
29
+ def execute(
30
+ self,
31
+ method: str,
32
+ url: str,
33
+ **kwargs: Any,
34
+ ) -> FrameworkResponse:
35
+ self._logger.info(
36
+ "%s %s",
37
+ method.upper(),
38
+ url,
39
+ )
40
+
41
+ self._hook_manager.before_request(
42
+ method=method,
43
+ url=url,
44
+ kwargs=kwargs,
45
+ )
46
+
47
+ response = self._session.request(
48
+ method=method,
49
+ url=url,
50
+ **kwargs,
51
+ )
52
+
53
+ self._hook_manager.after_response(response)
54
+
55
+ if self._config.auto_raise_exceptions:
56
+ ExceptionMapper.raise_for_response(response)
57
+
58
+ self._logger.info(
59
+ "Status Code: %s | Response Time: %.2f ms",
60
+ response.status_code,
61
+ response.elapsed.total_seconds() * 1000,
62
+ )
63
+
64
+ return FrameworkResponse(response)
File without changes
File without changes
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ import requests
4
+
5
+
6
+ class SessionManager:
7
+ """
8
+ Creates and manages HTTP sessions for the framework.
9
+ """
10
+
11
+ def __init__(self) -> None:
12
+ self._session = requests.Session()
13
+
14
+ @property
15
+ def session(self) -> requests.Session:
16
+ return self._session
17
+
18
+ def close(self) -> None:
19
+ self._session.close()
File without changes
@@ -0,0 +1,5 @@
1
+ from .user_endpoints import UserEndpoints
2
+
3
+ __all__ = [
4
+ "UserEndpoints",
5
+ ]
@@ -0,0 +1,32 @@
1
+ """
2
+ Base endpoint definitions.
3
+
4
+ All endpoint classes should inherit from this class.
5
+ """
6
+
7
+
8
+ class BaseEndpoints:
9
+ """
10
+ Base class responsible for building API endpoint paths.
11
+
12
+ Future enhancements:
13
+ - API versioning
14
+ - Service prefixes
15
+ - Tenant support
16
+ """
17
+
18
+ API_VERSION = ""
19
+
20
+ @classmethod
21
+ def build(cls, path: str) -> str:
22
+ """
23
+ Returns complete endpoint path.
24
+
25
+ Example:
26
+ "/users"
27
+
28
+ Future:
29
+ "/api/v1/users"
30
+ """
31
+
32
+ return f"{cls.API_VERSION}{path}"
@@ -0,0 +1,9 @@
1
+ from pyrestkit.endpoints.base_endpoints import BaseEndpoints
2
+
3
+ """
4
+ Order endpoint definitions.
5
+ """
6
+
7
+
8
+ class OrderEndpoints(BaseEndpoints):
9
+ RESOURCE = "/orders"
@@ -0,0 +1,5 @@
1
+ from pyrestkit.endpoints.base_endpoints import BaseEndpoints
2
+
3
+
4
+ class PaymentEndpoints(BaseEndpoints):
5
+ RESOURCE = "/payments"
@@ -0,0 +1,48 @@
1
+ """
2
+ User endpoint definitions.
3
+ """
4
+
5
+ from pyrestkit.endpoints.base_endpoints import BaseEndpoints
6
+
7
+
8
+ class UserEndpoints(BaseEndpoints):
9
+ """
10
+ Contains all endpoints related to Users.
11
+ """
12
+
13
+ RESOURCE = "/users"
14
+
15
+ @classmethod
16
+ def list_users(cls) -> str:
17
+ """
18
+ GET /users
19
+ """
20
+ return cls.build(cls.RESOURCE)
21
+
22
+ @classmethod
23
+ def create_user(cls) -> str:
24
+ """
25
+ POST /users
26
+ """
27
+ return cls.build(cls.RESOURCE)
28
+
29
+ @classmethod
30
+ def get_user(cls, user_id: int) -> str:
31
+ """
32
+ GET /users/{id}
33
+ """
34
+ return cls.build(f"{cls.RESOURCE}/{user_id}")
35
+
36
+ @classmethod
37
+ def update_user(cls, user_id: int) -> str:
38
+ """
39
+ PUT /users/{id}
40
+ """
41
+ return cls.build(f"{cls.RESOURCE}/{user_id}")
42
+
43
+ @classmethod
44
+ def delete_user(cls, user_id: int) -> str:
45
+ """
46
+ DELETE /users/{id}
47
+ """
48
+ return cls.build(f"{cls.RESOURCE}/{user_id}")
@@ -0,0 +1,21 @@
1
+ """
2
+ Custom exceptions used throughout the API automation framework.
3
+ """
4
+
5
+ from .api_exception import APIException
6
+ from .authentication_exception import AuthenticationException
7
+ from .configuration_exception import ConfigurationException
8
+ from .network_exception import NetworkException
9
+ from .response_exception import ResponseException
10
+ from .serialization_exception import SerializationException
11
+ from .validation_exception import ValidationException
12
+
13
+ __all__ = [
14
+ "APIException",
15
+ "AuthenticationException",
16
+ "ConfigurationException",
17
+ "NetworkException",
18
+ "ResponseException",
19
+ "SerializationException",
20
+ "ValidationException",
21
+ ]
@@ -0,0 +1,8 @@
1
+ class APIException(Exception):
2
+ """
3
+ Base exception for the API automation framework.
4
+ """
5
+
6
+ def __init__(self, message: str = "") -> None:
7
+ super().__init__(message)
8
+ self.message = message
@@ -0,0 +1,10 @@
1
+ from pyrestkit.exceptions.api_exception import APIException
2
+
3
+
4
+ class AuthenticationException(APIException):
5
+ """
6
+ Raised when authentication fails.
7
+ """
8
+
9
+ def __init__(self, message: str = "Authentication failed.") -> None:
10
+ super().__init__(message)
@@ -0,0 +1,10 @@
1
+ from pyrestkit.exceptions.api_exception import APIException
2
+
3
+
4
+ class ConfigurationException(APIException):
5
+ """
6
+ Raised when configuration is invalid.
7
+ """
8
+
9
+ def __init__(self, message: str = "Configuration is invalid.") -> None:
10
+ super().__init__(message)
@@ -0,0 +1,32 @@
1
+ from __future__ import annotations
2
+
3
+ import requests
4
+
5
+ from pyrestkit.exceptions.authentication_exception import AuthenticationException
6
+ from pyrestkit.exceptions.response_exception import ResponseException
7
+ from pyrestkit.exceptions.validation_exception import ValidationException
8
+
9
+
10
+ class ExceptionMapper:
11
+ """
12
+ Maps HTTP status codes to framework exceptions.
13
+ """
14
+
15
+ @staticmethod
16
+ def raise_for_response(
17
+ response: requests.Response,
18
+ ) -> None:
19
+ status = response.status_code
20
+
21
+ if status < 400:
22
+ return
23
+
24
+ if status == 401:
25
+ raise AuthenticationException("Authentication failed.")
26
+
27
+ if status == 422:
28
+ raise ValidationException("Validation failed.")
29
+
30
+ raise ResponseException(
31
+ f"Request failed with status code {status}.",
32
+ )
@@ -0,0 +1,10 @@
1
+ from pyrestkit.exceptions.api_exception import APIException
2
+
3
+
4
+ class NetworkException(APIException):
5
+ """
6
+ Raised for network related failures.
7
+ """
8
+
9
+ def __init__(self, message: str = "Network error occurred.") -> None:
10
+ super().__init__(message)
@@ -0,0 +1,10 @@
1
+ from pyrestkit.exceptions.api_exception import APIException
2
+
3
+
4
+ class ResponseException(APIException):
5
+ """
6
+ Raised for unexpected HTTP responses.
7
+ """
8
+
9
+ def __init__(self, message: str = "Unexpected response received.") -> None:
10
+ super().__init__(message)
@@ -0,0 +1,10 @@
1
+ from pyrestkit.exceptions.api_exception import APIException
2
+
3
+
4
+ class SerializationException(APIException):
5
+ """
6
+ Raised when serialization/deserialization fails.
7
+ """
8
+
9
+ def __init__(self, message: str = "Serialization failed.") -> None:
10
+ super().__init__(message)
@@ -0,0 +1,10 @@
1
+ from pyrestkit.exceptions.api_exception import APIException
2
+
3
+
4
+ class ValidationException(APIException):
5
+ """
6
+ Raised when response validation fails.
7
+ """
8
+
9
+ def __init__(self, message: str = "Validation failed.") -> None:
10
+ super().__init__(message)
@@ -0,0 +1,5 @@
1
+ from .user_factory import UserFactory
2
+
3
+ __all__ = [
4
+ "UserFactory",
5
+ ]
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from typing import Any, cast
6
+
7
+
8
+ class BaseFactory:
9
+ """
10
+ Base class for loading test data.
11
+ """
12
+
13
+ TESTDATA_DIR = Path("testdata")
14
+
15
+ @classmethod
16
+ def load_json(
17
+ cls,
18
+ filename: str,
19
+ ) -> dict[str, Any]:
20
+ file_path = cls.TESTDATA_DIR / filename
21
+
22
+ with file_path.open(
23
+ encoding="utf-8",
24
+ ) as file:
25
+ return cast(dict[str, Any], json.load(file))
@@ -0,0 +1,37 @@
1
+ from __future__ import annotations
2
+
3
+ import random
4
+
5
+ from pyrestkit.factories.base_factory import BaseFactory
6
+ from pyrestkit.models.request.create_user_request import CreateUserRequest
7
+
8
+
9
+ class UserFactory(BaseFactory):
10
+ """
11
+ Factory for CreateUserRequest objects.
12
+ """
13
+
14
+ @classmethod
15
+ def random(cls) -> CreateUserRequest:
16
+ return CreateUserRequest(
17
+ name=f"User-{random.randint(1000, 9999)}",
18
+ job="QA Engineer",
19
+ )
20
+
21
+ @classmethod
22
+ def admin(cls) -> CreateUserRequest:
23
+ return CreateUserRequest(
24
+ name="Admin User",
25
+ job="Administrator",
26
+ )
27
+
28
+ @classmethod
29
+ def from_file(
30
+ cls,
31
+ filename: str,
32
+ ) -> CreateUserRequest:
33
+ data = cls.load_json(filename)
34
+
35
+ return CreateUserRequest(
36
+ **data,
37
+ )
@@ -0,0 +1,5 @@
1
+ from .hook_manager import HookManager
2
+
3
+ __all__ = [
4
+ "HookManager",
5
+ ]
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import requests
6
+
7
+
8
+ class Hook:
9
+ """
10
+ Base class for framework hooks.
11
+
12
+ Override only the callbacks you need.
13
+ """
14
+
15
+ def before_request(
16
+ self,
17
+ method: str,
18
+ url: str,
19
+ kwargs: dict[str, Any],
20
+ ) -> None:
21
+ return
22
+
23
+ def after_response(
24
+ self,
25
+ response: requests.Response,
26
+ ) -> None:
27
+ return
@@ -0,0 +1,39 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ import requests
6
+
7
+ from pyrestkit.hooks.hook import Hook
8
+
9
+
10
+ class HookManager:
11
+ """
12
+ Executes registered hooks.
13
+ """
14
+
15
+ def __init__(
16
+ self,
17
+ hooks: list[Hook] | None = None,
18
+ ) -> None:
19
+ self._hooks = hooks or []
20
+
21
+ def before_request(
22
+ self,
23
+ method: str,
24
+ url: str,
25
+ kwargs: dict[str, Any],
26
+ ) -> None:
27
+ for hook in self._hooks:
28
+ hook.before_request(
29
+ method,
30
+ url,
31
+ kwargs,
32
+ )
33
+
34
+ def after_response(
35
+ self,
36
+ response: requests.Response,
37
+ ) -> None:
38
+ for hook in self._hooks:
39
+ hook.after_response(response)
@@ -0,0 +1,18 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any
5
+
6
+
7
+ class RequestHook(ABC):
8
+ """
9
+ Executed before an HTTP request is sent.
10
+ """
11
+
12
+ @abstractmethod
13
+ def before_request(
14
+ self,
15
+ method: str,
16
+ url: str,
17
+ kwargs: dict[str, Any],
18
+ ) -> None: ...
@@ -0,0 +1,17 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+ import requests
6
+
7
+
8
+ class ResponseHook(ABC):
9
+ """
10
+ Executed after an HTTP response is received.
11
+ """
12
+
13
+ @abstractmethod
14
+ def after_response(
15
+ self,
16
+ response: requests.Response,
17
+ ) -> None: ...
@@ -0,0 +1,32 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from typing import Any
5
+
6
+ import requests
7
+
8
+ from pyrestkit.hooks.hook import Hook
9
+
10
+
11
+ class TimingHook(Hook):
12
+ """
13
+ Measures request execution time.
14
+ """
15
+
16
+ def __init__(self) -> None:
17
+ self._start = 0.0
18
+
19
+ def before_request(
20
+ self,
21
+ method: str,
22
+ url: str,
23
+ kwargs: dict[str, Any],
24
+ ) -> None:
25
+ self._start = time.perf_counter()
26
+
27
+ def after_response(
28
+ self,
29
+ response: requests.Response,
30
+ ) -> None:
31
+ elapsed = (time.perf_counter() - self._start) * 1000
32
+ print(f"Request completed in {elapsed:.2f} ms")
@@ -0,0 +1,8 @@
1
+ from .request import CreateUserRequest, UpdateUserRequest
2
+ from .response import UserResponse
3
+
4
+ __all__ = [
5
+ "CreateUserRequest",
6
+ "UpdateUserRequest",
7
+ "UserResponse",
8
+ ]
@@ -0,0 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Protocol, Self
4
+
5
+
6
+ class BaseResponse(Protocol):
7
+ @classmethod
8
+ def from_dict(
9
+ cls,
10
+ data: dict[str, Any],
11
+ ) -> Self: ...
@@ -0,0 +1,7 @@
1
+ from .create_user_request import CreateUserRequest
2
+ from .update_user_request import UpdateUserRequest
3
+
4
+ __all__ = [
5
+ "CreateUserRequest",
6
+ "UpdateUserRequest",
7
+ ]
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass(slots=True)
5
+ class CreateUserRequest:
6
+ """
7
+ Request model for creating a user.
8
+ """
9
+
10
+ name: str
11
+ job: str
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass(slots=True)
5
+ class UpdateUserRequest:
6
+ """
7
+ Request model for updating a user.
8
+ """
9
+
10
+ job: str
@@ -0,0 +1,5 @@
1
+ from .user_response import UserResponse
2
+
3
+ __all__ = [
4
+ "UserResponse",
5
+ ]
@@ -0,0 +1,26 @@
1
+ # from dataclasses import dataclass
2
+
3
+
4
+ # @dataclass(slots=True)
5
+ # class CreateUserResponse:
6
+ # id: str
7
+ # name: str
8
+ # job: str
9
+ # created_at: str
10
+
11
+ # @classmethod
12
+ # def from_dict(cls, data: dict) -> "CreateUserResponse":
13
+ # return cls(
14
+ # id=data["id"],
15
+ # name=data["name"],
16
+ # job=data["job"],
17
+ # created_at=data["createdAt"],
18
+ # )
19
+
20
+ from dataclasses import dataclass
21
+
22
+ from pyrestkit.models.base_response import BaseResponse
23
+
24
+
25
+ @dataclass(slots=True)
26
+ class CreateUserResponse(BaseResponse): ...
@@ -0,0 +1,28 @@
1
+ # from dataclasses import dataclass
2
+
3
+
4
+ # @dataclass(slots=True)
5
+ # class GetUserResponse:
6
+ # id: int
7
+ # email: str
8
+ # first_name: str
9
+ # last_name: str
10
+ # avatar: str
11
+
12
+ # @classmethod
13
+ # def from_dict(cls, data: dict) -> "GetUserResponse":
14
+ # return cls(
15
+ # id=data["id"],
16
+ # email=data["email"],
17
+ # first_name=data["first_name"],
18
+ # last_name=data["last_name"],
19
+ # avatar=data["avatar"],
20
+ # )
21
+
22
+ from dataclasses import dataclass
23
+
24
+ from pyrestkit.models.base_response import BaseResponse
25
+
26
+
27
+ @dataclass(slots=True)
28
+ class GetUserResponse(BaseResponse): ...