• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

angelkurten / response_handler / 14917348890

08 May 2025 10:28PM UTC coverage: 98.986% (-0.3%) from 99.299%
14917348890

push

github

web-flow
feat: Add Success.of() factory method and improve JSON output control (#13)

* ci: add support for Python 3.10, 3.11, and 3.12

* feat: add Success.of() factory method and improve JSON output control

* test: update tests for new JSON output control features

* chore: bump version to 0.2.1

* docs: update documentation and examples with latest features

* feat: add success data type

44 of 47 new or added lines in 4 files covered. (93.62%)

1 existing line in 1 file now uncovered.

1172 of 1184 relevant lines covered (98.99%)

0.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.64
/response_handler_lib/response.py
1
from typing import Any, Dict, List, Optional, Union, Set
1✔
2
from pydantic import BaseModel, Field, field_validator, ConfigDict
1✔
3
from .either import Either, ErrorItem, Success, Failure
1✔
4
from .config import Config
1✔
5

6
class Response(BaseModel):
1✔
7
    """
8
    A class representing a final response, typically used for HTTP responses.
9
    This class is designed to be the final output format, while Either is used
10
    for intermediate error handling in the business logic layers.
11
    """
12
    data: Optional[Any] = None
1✔
13
    errors: List[ErrorItem] = Field(default_factory=list)
1✔
14
    context: Dict[str, Any] = Field(default_factory=dict)
1✔
15
    status_code: int = Field(default=200)
1✔
16

17
    model_config = ConfigDict(
1✔
18
        arbitrary_types_allowed=True,
19
        json_schema_extra={
20
            "example": {
21
                "data": {"key": "value"},
22
                "errors": [],
23
                "context": {},
24
                "status_code": 200
25
            }
26
        }
27
    )
28

29
    @field_validator('status_code')
1✔
30
    @classmethod
1✔
31
    def validate_status_code(cls, v: int) -> int:
1✔
32
        """Validate that status code is a valid HTTP status code."""
33
        if not (100 <= v <= 599):
1✔
34
            raise ValueError('Status code must be between 100 and 599')
1✔
35
        return v
×
36

37
    def __init__(self, **data):
1✔
38
        super().__init__(**data)
1✔
39
        if self.errors:
1✔
40
            self._update_status_code(self.errors[0].code)
1✔
41

42
    def _update_status_code(self, error_code: str) -> None:
1✔
43
        """Update status code based on error type."""
44
        status_map = {
1✔
45
            'VAL_ERROR': 400,
46
            'AUTH_ERROR': 401,
47
            'FORB_ERROR': 403,
48
            'NOT_ERROR': 404,
49
            'TIM_ERROR': 408,
50
            'INT_ERROR': 500
51
        }
52
        self.status_code = status_map.get(error_code, 400)
1✔
53

54
    def to_dict(self) -> Dict[str, Any]:
1✔
55
        """Convert the response to a dictionary format."""
56
        data = self.model_dump()
1✔
57
        if not Config.ENABLE_CONTEXT_IN_JSON:
1✔
58
            data.pop('context', None)
1✔
59
        if data.get('errors'):
1✔
60
            for error in data['errors']:
1✔
61
                if not Config.ENABLE_WHERE_IN_JSON:
1✔
62
                    error.pop('where', None)
1✔
63
                if not Config.ENABLE_CONTEXT_IN_JSON:
1✔
64
                    error.pop('context', None)
1✔
65
        return data
1✔
66

67
    def to_json(self) -> str:
1✔
68
        """Convert the response to JSON format."""
69
        if not Config.ENABLE_CONTEXT_IN_JSON or not Config.ENABLE_WHERE_IN_JSON:
1✔
70
            exclude: Dict[str, Any] = {}
1✔
71
            if not Config.ENABLE_CONTEXT_IN_JSON:
1✔
72
                exclude['context'] = True
1✔
73
                exclude['errors'] = {'__all__': {'context'}}
1✔
74
            if not Config.ENABLE_WHERE_IN_JSON:
1✔
75
                if 'errors' not in exclude:
1✔
76
                    exclude['errors'] = {'__all__': set()}
1✔
77
                exclude['errors']['__all__'].add('where')
1✔
78
            return self.model_dump_json(exclude=exclude)
1✔
UNCOV
79
        return self.model_dump_json()
×
80

81
    @classmethod
1✔
82
    def from_either(cls, either: Either) -> 'Response':
1✔
83
        """
84
        Create a Response from an Either.
85
        This is useful when converting from intermediate error handling
86
        to a final response format.
87
        """
88
        if isinstance(either, Success):
1✔
89
            return cls(data=either._value)
1✔
90
        elif isinstance(either, Failure):
1✔
91
            response = cls(errors=either._errors)
1✔
92
            if either._errors and either._errors[0].context:
1✔
93
                response.context.update(either._errors[0].context)
1✔
94
            return response
1✔
95
        raise ValueError("Invalid Either type")
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc