fastapi-toolsets 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.
- fastapi_toolsets/__init__.py +24 -0
- fastapi_toolsets/cli/__init__.py +5 -0
- fastapi_toolsets/cli/app.py +97 -0
- fastapi_toolsets/cli/commands/__init__.py +1 -0
- fastapi_toolsets/cli/commands/fixtures.py +225 -0
- fastapi_toolsets/crud.py +378 -0
- fastapi_toolsets/db.py +175 -0
- fastapi_toolsets/exceptions/__init__.py +19 -0
- fastapi_toolsets/exceptions/exceptions.py +166 -0
- fastapi_toolsets/exceptions/handler.py +169 -0
- fastapi_toolsets/fixtures/__init__.py +17 -0
- fastapi_toolsets/fixtures/fixtures.py +321 -0
- fastapi_toolsets/fixtures/pytest_plugin.py +204 -0
- fastapi_toolsets/py.typed +0 -0
- fastapi_toolsets/schemas.py +116 -0
- fastapi_toolsets-0.1.0.dist-info/METADATA +89 -0
- fastapi_toolsets-0.1.0.dist-info/RECORD +20 -0
- fastapi_toolsets-0.1.0.dist-info/WHEEL +4 -0
- fastapi_toolsets-0.1.0.dist-info/entry_points.txt +3 -0
- fastapi_toolsets-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""Pytest plugin for using FixtureRegistry fixtures in tests.
|
|
2
|
+
|
|
3
|
+
This module provides utilities to automatically generate pytest fixtures
|
|
4
|
+
from your FixtureRegistry, with proper dependency resolution.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
# conftest.py
|
|
8
|
+
import pytest
|
|
9
|
+
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
|
|
10
|
+
|
|
11
|
+
from app.fixtures import fixtures # Your FixtureRegistry
|
|
12
|
+
from app.models import Base
|
|
13
|
+
from fastapi_toolsets.pytest_plugin import register_fixtures
|
|
14
|
+
|
|
15
|
+
DATABASE_URL = "postgresql+asyncpg://postgres:postgres@localhost:5432/test_db"
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
async def engine():
|
|
19
|
+
engine = create_async_engine(DATABASE_URL)
|
|
20
|
+
yield engine
|
|
21
|
+
await engine.dispose()
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
async def db_session(engine):
|
|
25
|
+
async with engine.begin() as conn:
|
|
26
|
+
await conn.run_sync(Base.metadata.create_all)
|
|
27
|
+
|
|
28
|
+
session_factory = async_sessionmaker(engine, expire_on_commit=False)
|
|
29
|
+
session = session_factory()
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
yield session
|
|
33
|
+
finally:
|
|
34
|
+
await session.close()
|
|
35
|
+
async with engine.begin() as conn:
|
|
36
|
+
await conn.run_sync(Base.metadata.drop_all)
|
|
37
|
+
|
|
38
|
+
# Automatically generate pytest fixtures from registry
|
|
39
|
+
# Creates: fixture_roles, fixture_users, fixture_posts, etc.
|
|
40
|
+
register_fixtures(fixtures, globals())
|
|
41
|
+
|
|
42
|
+
Usage in tests:
|
|
43
|
+
# test_users.py
|
|
44
|
+
async def test_user_count(db_session, fixture_users):
|
|
45
|
+
# fixture_users automatically loads fixture_roles first (if dependency)
|
|
46
|
+
# and returns the list of User models
|
|
47
|
+
assert len(fixture_users) > 0
|
|
48
|
+
|
|
49
|
+
async def test_user_role(db_session, fixture_users):
|
|
50
|
+
user = fixture_users[0]
|
|
51
|
+
assert user.role_id is not None
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
from collections.abc import Callable, Sequence
|
|
55
|
+
from typing import Any
|
|
56
|
+
|
|
57
|
+
import pytest
|
|
58
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
59
|
+
from sqlalchemy.orm import DeclarativeBase
|
|
60
|
+
|
|
61
|
+
from ..db import get_transaction
|
|
62
|
+
from .fixtures import FixtureRegistry, LoadStrategy
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def register_fixtures(
|
|
66
|
+
registry: FixtureRegistry,
|
|
67
|
+
namespace: dict[str, Any],
|
|
68
|
+
*,
|
|
69
|
+
prefix: str = "fixture_",
|
|
70
|
+
session_fixture: str = "db_session",
|
|
71
|
+
strategy: LoadStrategy = LoadStrategy.MERGE,
|
|
72
|
+
) -> list[str]:
|
|
73
|
+
"""Register pytest fixtures from a FixtureRegistry.
|
|
74
|
+
|
|
75
|
+
Automatically creates pytest fixtures for each fixture in the registry.
|
|
76
|
+
Dependencies are resolved via pytest fixture dependencies.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
registry: The FixtureRegistry containing fixtures
|
|
80
|
+
namespace: The module's globals() dict to add fixtures to
|
|
81
|
+
prefix: Prefix for generated fixture names (default: "fixture_")
|
|
82
|
+
session_fixture: Name of the db session fixture (default: "db_session")
|
|
83
|
+
strategy: Loading strategy for fixtures (default: MERGE)
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
List of created fixture names
|
|
87
|
+
|
|
88
|
+
Example:
|
|
89
|
+
# conftest.py
|
|
90
|
+
from app.fixtures import fixtures
|
|
91
|
+
from fastapi_toolsets.pytest_plugin import register_fixtures
|
|
92
|
+
|
|
93
|
+
register_fixtures(fixtures, globals())
|
|
94
|
+
|
|
95
|
+
# Creates fixtures like:
|
|
96
|
+
# - fixture_roles
|
|
97
|
+
# - fixture_users (depends on fixture_roles if users depends on roles)
|
|
98
|
+
# - fixture_posts (depends on fixture_users if posts depends on users)
|
|
99
|
+
"""
|
|
100
|
+
created_fixtures: list[str] = []
|
|
101
|
+
|
|
102
|
+
for fixture in registry.get_all():
|
|
103
|
+
fixture_name = f"{prefix}{fixture.name}"
|
|
104
|
+
|
|
105
|
+
# Build list of pytest fixture dependencies
|
|
106
|
+
pytest_deps = [session_fixture]
|
|
107
|
+
for dep in fixture.depends_on:
|
|
108
|
+
pytest_deps.append(f"{prefix}{dep}")
|
|
109
|
+
|
|
110
|
+
# Create the fixture function
|
|
111
|
+
fixture_func = _create_fixture_function(
|
|
112
|
+
registry=registry,
|
|
113
|
+
fixture_name=fixture.name,
|
|
114
|
+
dependencies=pytest_deps,
|
|
115
|
+
strategy=strategy,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Apply pytest.fixture decorator
|
|
119
|
+
decorated = pytest.fixture(fixture_func)
|
|
120
|
+
|
|
121
|
+
# Add to namespace
|
|
122
|
+
namespace[fixture_name] = decorated
|
|
123
|
+
created_fixtures.append(fixture_name)
|
|
124
|
+
|
|
125
|
+
return created_fixtures
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _create_fixture_function(
|
|
129
|
+
registry: FixtureRegistry,
|
|
130
|
+
fixture_name: str,
|
|
131
|
+
dependencies: list[str],
|
|
132
|
+
strategy: LoadStrategy,
|
|
133
|
+
) -> Callable[..., Any]:
|
|
134
|
+
"""Create a fixture function with the correct signature.
|
|
135
|
+
|
|
136
|
+
The function signature must include all dependencies as parameters
|
|
137
|
+
for pytest to resolve them correctly.
|
|
138
|
+
"""
|
|
139
|
+
# Get the fixture definition
|
|
140
|
+
fixture_def = registry.get(fixture_name)
|
|
141
|
+
|
|
142
|
+
# Build the function dynamically with correct parameters
|
|
143
|
+
# We need the session as first param, then all dependencies
|
|
144
|
+
async def fixture_func(**kwargs: Any) -> Sequence[DeclarativeBase]:
|
|
145
|
+
# Get session from kwargs (first dependency)
|
|
146
|
+
session: AsyncSession = kwargs[dependencies[0]]
|
|
147
|
+
|
|
148
|
+
# Load the fixture data
|
|
149
|
+
instances = list(fixture_def.func())
|
|
150
|
+
|
|
151
|
+
if not instances:
|
|
152
|
+
return []
|
|
153
|
+
|
|
154
|
+
loaded: list[DeclarativeBase] = []
|
|
155
|
+
|
|
156
|
+
async with get_transaction(session):
|
|
157
|
+
for instance in instances:
|
|
158
|
+
if strategy == LoadStrategy.INSERT:
|
|
159
|
+
session.add(instance)
|
|
160
|
+
loaded.append(instance)
|
|
161
|
+
elif strategy == LoadStrategy.MERGE:
|
|
162
|
+
merged = await session.merge(instance)
|
|
163
|
+
loaded.append(merged)
|
|
164
|
+
elif strategy == LoadStrategy.SKIP_EXISTING:
|
|
165
|
+
pk = _get_primary_key(instance)
|
|
166
|
+
if pk is not None:
|
|
167
|
+
existing = await session.get(type(instance), pk)
|
|
168
|
+
if existing is None:
|
|
169
|
+
session.add(instance)
|
|
170
|
+
loaded.append(instance)
|
|
171
|
+
else:
|
|
172
|
+
loaded.append(existing)
|
|
173
|
+
else:
|
|
174
|
+
session.add(instance)
|
|
175
|
+
loaded.append(instance)
|
|
176
|
+
|
|
177
|
+
return loaded
|
|
178
|
+
|
|
179
|
+
# Update function signature to include dependencies
|
|
180
|
+
# This is needed for pytest to inject the right fixtures
|
|
181
|
+
params = ", ".join(dependencies)
|
|
182
|
+
code = f"async def {fixture_name}_fixture({params}):\n return await _impl({', '.join(f'{d}={d}' for d in dependencies)})"
|
|
183
|
+
|
|
184
|
+
local_ns: dict[str, Any] = {"_impl": fixture_func}
|
|
185
|
+
exec(code, local_ns) # noqa: S102
|
|
186
|
+
|
|
187
|
+
created_func = local_ns[f"{fixture_name}_fixture"]
|
|
188
|
+
created_func.__doc__ = f"Load {fixture_name} fixture data."
|
|
189
|
+
|
|
190
|
+
return created_func
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _get_primary_key(instance: DeclarativeBase) -> Any | None:
|
|
194
|
+
"""Get the primary key value of a model instance."""
|
|
195
|
+
mapper = instance.__class__.__mapper__
|
|
196
|
+
pk_cols = mapper.primary_key
|
|
197
|
+
|
|
198
|
+
if len(pk_cols) == 1:
|
|
199
|
+
return getattr(instance, pk_cols[0].name, None)
|
|
200
|
+
|
|
201
|
+
pk_values = tuple(getattr(instance, col.name, None) for col in pk_cols)
|
|
202
|
+
if all(v is not None for v in pk_values):
|
|
203
|
+
return pk_values
|
|
204
|
+
return None
|
|
File without changes
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Base Pydantic schemas for API responses."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import ClassVar, Generic, TypeVar
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"ApiError",
|
|
10
|
+
"ErrorResponse",
|
|
11
|
+
"Pagination",
|
|
12
|
+
"PaginatedResponse",
|
|
13
|
+
"Response",
|
|
14
|
+
"ResponseStatus",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
DataT = TypeVar("DataT")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PydanticBase(BaseModel):
|
|
21
|
+
"""Base class for all Pydantic models with common configuration."""
|
|
22
|
+
|
|
23
|
+
model_config: ClassVar[ConfigDict] = ConfigDict(
|
|
24
|
+
from_attributes=True,
|
|
25
|
+
validate_assignment=True,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ResponseStatus(str, Enum):
|
|
30
|
+
"""Standard API response status."""
|
|
31
|
+
|
|
32
|
+
SUCCESS = "SUCCESS"
|
|
33
|
+
FAIL = "FAIL"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ApiError(PydanticBase):
|
|
37
|
+
"""Structured API error definition.
|
|
38
|
+
|
|
39
|
+
Used to define standard error responses with consistent format.
|
|
40
|
+
|
|
41
|
+
Attributes:
|
|
42
|
+
code: HTTP status code
|
|
43
|
+
msg: Short error message
|
|
44
|
+
desc: Detailed error description
|
|
45
|
+
err_code: Application-specific error code (e.g., "AUTH-401")
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
code: int
|
|
49
|
+
msg: str
|
|
50
|
+
desc: str
|
|
51
|
+
err_code: str
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class BaseResponse(PydanticBase):
|
|
55
|
+
"""Base response structure for all API responses.
|
|
56
|
+
|
|
57
|
+
Attributes:
|
|
58
|
+
status: SUCCESS or FAIL
|
|
59
|
+
message: Human-readable message
|
|
60
|
+
error_code: Error code if status is FAIL, None otherwise
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
status: ResponseStatus = ResponseStatus.SUCCESS
|
|
64
|
+
message: str = "Success"
|
|
65
|
+
error_code: str | None = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Response(BaseResponse, Generic[DataT]):
|
|
69
|
+
"""Generic API response with data payload.
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
Response[UserRead](data=user, message="User retrieved")
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
data: DataT | None = None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class ErrorResponse(BaseResponse):
|
|
79
|
+
"""Error response with additional description field.
|
|
80
|
+
|
|
81
|
+
Used for error responses that need more context.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
status: ResponseStatus = ResponseStatus.FAIL
|
|
85
|
+
description: str | None = None
|
|
86
|
+
data: None = None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class Pagination(PydanticBase):
|
|
90
|
+
"""Pagination metadata for list responses.
|
|
91
|
+
|
|
92
|
+
Attributes:
|
|
93
|
+
total_count: Total number of items across all pages
|
|
94
|
+
items_per_page: Number of items per page
|
|
95
|
+
page: Current page number (1-indexed)
|
|
96
|
+
has_more: Whether there are more pages
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
total_count: int
|
|
100
|
+
items_per_page: int
|
|
101
|
+
page: int
|
|
102
|
+
has_more: bool
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class PaginatedResponse(BaseResponse, Generic[DataT]):
|
|
106
|
+
"""Paginated API response for list endpoints.
|
|
107
|
+
|
|
108
|
+
Example:
|
|
109
|
+
PaginatedResponse[UserRead](
|
|
110
|
+
data=users,
|
|
111
|
+
pagination=Pagination(total_count=100, items_per_page=10, page=1, has_more=True)
|
|
112
|
+
)
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
data: list[DataT]
|
|
116
|
+
pagination: Pagination
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-toolsets
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reusable tools for FastAPI: async CRUD, fixtures, CLI, and standardized responses for SQLAlchemy + PostgreSQL
|
|
5
|
+
Keywords: fastapi,sqlalchemy,postgresql
|
|
6
|
+
Author: d3vyce
|
|
7
|
+
Author-email: d3vyce <contact@d3vyce.fr>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Framework :: AsyncIO
|
|
12
|
+
Classifier: Framework :: FastAPI
|
|
13
|
+
Classifier: Framework :: Pydantic
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: Intended Audience :: System Administrators
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
25
|
+
Classifier: Topic :: Software Development
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Dist: fastapi>=0.100.0
|
|
28
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0
|
|
29
|
+
Requires-Dist: asyncpg>=0.29.0
|
|
30
|
+
Requires-Dist: pydantic>=2.0
|
|
31
|
+
Requires-Dist: typer>=0.9.0
|
|
32
|
+
Requires-Dist: httpx>=0.25.0
|
|
33
|
+
Requires-Dist: fastapi-toolsets[test] ; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.1.0 ; extra == 'dev'
|
|
35
|
+
Requires-Dist: ty>=0.0.1a0 ; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=8.0.0 ; extra == 'test'
|
|
37
|
+
Requires-Dist: pytest-anyio>=0.0.0 ; extra == 'test'
|
|
38
|
+
Requires-Dist: coverage>=7.0.0 ; extra == 'test'
|
|
39
|
+
Requires-Dist: pytest-cov>=4.0.0 ; extra == 'test'
|
|
40
|
+
Requires-Python: >=3.11
|
|
41
|
+
Project-URL: Homepage, https://github.com/d3vyce/fastapi-toolsets
|
|
42
|
+
Project-URL: Documentation, https://fastapi-toolsets.d3vyce.fr/
|
|
43
|
+
Project-URL: Repository, https://github.com/d3vyce/fastapi-toolsets
|
|
44
|
+
Project-URL: Issues, https://github.com/d3vyce/fastapi-toolsets/issues
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Provides-Extra: test
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
|
|
49
|
+
# FastAPI Toolsets
|
|
50
|
+
|
|
51
|
+
FastAPI Toolsets provides production-ready utilities for FastAPI applications built with async SQLAlchemy and PostgreSQL. It includes generic CRUD operations, a fixture system with dependency resolution, a Django-like CLI, standardized API responses, and structured exception handling with automatic OpenAPI documentation.
|
|
52
|
+
|
|
53
|
+
[](https://github.com/d3vyce/fastapi-toolsets/actions/workflows/ci.yml)
|
|
54
|
+
[](https://codecov.io/gh/d3vyce/fastapi-toolsets)
|
|
55
|
+
[](https://github.com/astral-sh/ty)
|
|
56
|
+
[](https://github.com/astral-sh/uv)
|
|
57
|
+
[](https://github.com/astral-sh/ruff)
|
|
58
|
+
[](https://www.python.org/downloads/)
|
|
59
|
+
[](https://opensource.org/licenses/MIT)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
**Documentation**: [https://fastapi-toolsets.d3vyce.fr](https://fastapi-toolsets.d3vyce.fr)
|
|
64
|
+
|
|
65
|
+
**Source Code**: [https://github.com/d3vyce/fastapi-toolsets](https://github.com/d3vyce/fastapi-toolsets)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uv add fastapi-toolsets
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Features
|
|
76
|
+
|
|
77
|
+
- **CRUD**: Generic async CRUD operations with `CrudFactory`
|
|
78
|
+
- **Fixtures**: Fixture system with dependency management, context support and pytest integration
|
|
79
|
+
- **CLI**: Django-like command-line interface for fixtures and custom commands
|
|
80
|
+
- **Standardized API Responses**: Consistent response format across your API
|
|
81
|
+
- **Exception Handling**: Structured error responses with automatic OpenAPI documentation
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
86
|
+
|
|
87
|
+
## Contributing
|
|
88
|
+
|
|
89
|
+
Contributions are welcome! Please feel free to submit issues and pull requests.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
fastapi_toolsets/__init__.py,sha256=bLVbdgVNhQdN9LhAvb4FPNrgoIqHUjLx9TvgJzm46Jc,820
|
|
2
|
+
fastapi_toolsets/cli/__init__.py,sha256=QAcrenphE7D5toid_Kn777Cy1icSOWiEBjSE_oCuU4o,111
|
|
3
|
+
fastapi_toolsets/cli/app.py,sha256=G3y3PNN3biHs8GtiiGsrX2X8nXNjkrsUhHLXQo2-MXc,2588
|
|
4
|
+
fastapi_toolsets/cli/commands/__init__.py,sha256=BogehmsY6olwLdfIBzviuppXP1LLl9znnxtmji3eLwI,29
|
|
5
|
+
fastapi_toolsets/cli/commands/fixtures.py,sha256=qiC2dcrJ_Rb1PRzx6EycTFQQXwa_GQUVoptpx4chf9k,6679
|
|
6
|
+
fastapi_toolsets/crud.py,sha256=pD26V91y0Z5f9ft0I6ggY1EJ-Oh-QATgANgzEyj4EHU,11370
|
|
7
|
+
fastapi_toolsets/db.py,sha256=YUj5CrxCnREg7AqpJLNrLR2RDIOCS7stQCNOSS3cRho,5619
|
|
8
|
+
fastapi_toolsets/exceptions/__init__.py,sha256=PDiTg4NpEUhGi5p9Sfvn1FtxdlD9-Y4OPhWCQz6fW9g,391
|
|
9
|
+
fastapi_toolsets/exceptions/exceptions.py,sha256=O6fqDbPfEFSj1oi_vo3-gnES7RPpSf-l_yXh4fTCBjg,4470
|
|
10
|
+
fastapi_toolsets/exceptions/handler.py,sha256=IXfKiIr_LPo-11PRpOIrNRAXBkeQ5TdLcu3Gy-r6ChU,5916
|
|
11
|
+
fastapi_toolsets/fixtures/__init__.py,sha256=EWODe3vwjyrnZ_4jEpDdQ4NFLmYvdFqvvvrRaKq6Bsk,323
|
|
12
|
+
fastapi_toolsets/fixtures/fixtures.py,sha256=RB073yojMQoRCxP_-pvZWSW_viPQsD3RRJ5NhEZ2wZQ,9720
|
|
13
|
+
fastapi_toolsets/fixtures/pytest_plugin.py,sha256=J2PjasekQUxzurk7_MVncQRcIZ1AIawsO6OlqKqKYT8,6891
|
|
14
|
+
fastapi_toolsets/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
fastapi_toolsets/schemas.py,sha256=LBzrq4s5VWYeQqlUfOEvWDtpFdO8scgY0LRypk9KUAE,2639
|
|
16
|
+
fastapi_toolsets-0.1.0.dist-info/licenses/LICENSE,sha256=V2jCjI-VPB-veGY2Ktb0sU4vT_TldRciZ9lCE98bMoE,1063
|
|
17
|
+
fastapi_toolsets-0.1.0.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
|
|
18
|
+
fastapi_toolsets-0.1.0.dist-info/entry_points.txt,sha256=pNU38Nn_DXBgYd-nLZCizMvrrdaPhHmkRwouDoBqvzw,63
|
|
19
|
+
fastapi_toolsets-0.1.0.dist-info/METADATA,sha256=fRrFRvKtO4m2lbF0pq6qgbHxrHTPitfMSVkD6WlknXU,4170
|
|
20
|
+
fastapi_toolsets-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 d3vyce
|
|
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.
|