tachyon-api 0.9.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 (44) hide show
  1. tachyon_api/__init__.py +59 -0
  2. tachyon_api/app.py +699 -0
  3. tachyon_api/background.py +72 -0
  4. tachyon_api/cache.py +270 -0
  5. tachyon_api/cli/__init__.py +9 -0
  6. tachyon_api/cli/__main__.py +8 -0
  7. tachyon_api/cli/commands/__init__.py +5 -0
  8. tachyon_api/cli/commands/generate.py +190 -0
  9. tachyon_api/cli/commands/lint.py +186 -0
  10. tachyon_api/cli/commands/new.py +82 -0
  11. tachyon_api/cli/commands/openapi.py +128 -0
  12. tachyon_api/cli/main.py +69 -0
  13. tachyon_api/cli/templates/__init__.py +8 -0
  14. tachyon_api/cli/templates/project.py +194 -0
  15. tachyon_api/cli/templates/service.py +330 -0
  16. tachyon_api/core/__init__.py +12 -0
  17. tachyon_api/core/lifecycle.py +106 -0
  18. tachyon_api/core/websocket.py +92 -0
  19. tachyon_api/di.py +86 -0
  20. tachyon_api/exceptions.py +39 -0
  21. tachyon_api/files.py +14 -0
  22. tachyon_api/middlewares/__init__.py +4 -0
  23. tachyon_api/middlewares/core.py +40 -0
  24. tachyon_api/middlewares/cors.py +159 -0
  25. tachyon_api/middlewares/logger.py +123 -0
  26. tachyon_api/models.py +73 -0
  27. tachyon_api/openapi.py +419 -0
  28. tachyon_api/params.py +268 -0
  29. tachyon_api/processing/__init__.py +14 -0
  30. tachyon_api/processing/dependencies.py +172 -0
  31. tachyon_api/processing/parameters.py +484 -0
  32. tachyon_api/processing/response_processor.py +93 -0
  33. tachyon_api/responses.py +92 -0
  34. tachyon_api/router.py +161 -0
  35. tachyon_api/security.py +295 -0
  36. tachyon_api/testing.py +110 -0
  37. tachyon_api/utils/__init__.py +15 -0
  38. tachyon_api/utils/type_converter.py +113 -0
  39. tachyon_api/utils/type_utils.py +162 -0
  40. tachyon_api-0.9.0.dist-info/METADATA +291 -0
  41. tachyon_api-0.9.0.dist-info/RECORD +44 -0
  42. tachyon_api-0.9.0.dist-info/WHEEL +4 -0
  43. tachyon_api-0.9.0.dist-info/entry_points.txt +3 -0
  44. tachyon_api-0.9.0.dist-info/licenses/LICENSE +17 -0
tachyon_api/testing.py ADDED
@@ -0,0 +1,110 @@
1
+ """
2
+ Tachyon Testing Utilities
3
+
4
+ Provides test clients and utilities for testing Tachyon applications.
5
+ """
6
+
7
+ from typing import Optional
8
+ from starlette.testclient import TestClient
9
+ from httpx import AsyncClient, ASGITransport
10
+
11
+
12
+ class TachyonTestClient(TestClient):
13
+ """
14
+ Synchronous test client for Tachyon applications.
15
+
16
+ A wrapper around Starlette's TestClient that provides a convenient
17
+ interface for testing Tachyon applications.
18
+
19
+ Example:
20
+ from tachyon_api.testing import TachyonTestClient
21
+
22
+ def test_hello():
23
+ app = Tachyon()
24
+
25
+ @app.get("/hello")
26
+ def hello():
27
+ return {"message": "Hello!"}
28
+
29
+ client = TachyonTestClient(app)
30
+ response = client.get("/hello")
31
+ assert response.status_code == 200
32
+ assert response.json() == {"message": "Hello!"}
33
+
34
+ Note:
35
+ For async testing, use AsyncTachyonTestClient instead.
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ app,
41
+ base_url: str = "http://test",
42
+ raise_server_exceptions: bool = True,
43
+ **kwargs,
44
+ ):
45
+ """
46
+ Initialize the test client.
47
+
48
+ Args:
49
+ app: The Tachyon application instance
50
+ base_url: Base URL for requests (default: "http://test")
51
+ raise_server_exceptions: Whether to raise exceptions from the app
52
+ **kwargs: Additional arguments passed to TestClient
53
+ """
54
+ super().__init__(
55
+ app,
56
+ base_url=base_url,
57
+ raise_server_exceptions=raise_server_exceptions,
58
+ **kwargs,
59
+ )
60
+
61
+
62
+ class AsyncTachyonTestClient:
63
+ """
64
+ Async test client for Tachyon applications.
65
+
66
+ Wraps httpx.AsyncClient with ASGITransport for async testing.
67
+
68
+ Example:
69
+ from tachyon_api.testing import AsyncTachyonTestClient
70
+
71
+ @pytest.mark.asyncio
72
+ async def test_hello():
73
+ app = Tachyon()
74
+
75
+ @app.get("/hello")
76
+ async def hello():
77
+ return {"message": "Hello!"}
78
+
79
+ async with AsyncTachyonTestClient(app) as client:
80
+ response = await client.get("/hello")
81
+ assert response.status_code == 200
82
+ """
83
+
84
+ def __init__(self, app, base_url: str = "http://test", **kwargs):
85
+ """
86
+ Initialize the async test client.
87
+
88
+ Args:
89
+ app: The Tachyon application instance
90
+ base_url: Base URL for requests (default: "http://test")
91
+ **kwargs: Additional arguments passed to AsyncClient
92
+ """
93
+ self._app = app
94
+ self._base_url = base_url
95
+ self._kwargs = kwargs
96
+ self._client: Optional[AsyncClient] = None
97
+
98
+ async def __aenter__(self) -> AsyncClient:
99
+ """Enter async context manager."""
100
+ self._client = AsyncClient(
101
+ transport=ASGITransport(app=self._app),
102
+ base_url=self._base_url,
103
+ **self._kwargs,
104
+ )
105
+ return self._client
106
+
107
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
108
+ """Exit async context manager."""
109
+ if self._client:
110
+ await self._client.aclose()
@@ -0,0 +1,15 @@
1
+ """
2
+ Tachyon API - Utilities Module
3
+
4
+ This package contains utility functions and classes that provide common functionality
5
+ across the Tachyon framework, including type conversion, validation, and helper functions.
6
+ """
7
+
8
+ from .type_utils import TypeUtils, OPENAPI_TYPE_MAP
9
+ from .type_converter import TypeConverter
10
+
11
+ __all__ = [
12
+ "TypeUtils",
13
+ "TypeConverter",
14
+ "OPENAPI_TYPE_MAP",
15
+ ]
@@ -0,0 +1,113 @@
1
+ """
2
+ Tachyon API - Type Converter
3
+
4
+ This module provides functionality for converting string values to appropriate Python types
5
+ with proper error handling. Used primarily for converting URL parameters and query strings
6
+ to typed values expected by endpoint functions.
7
+ """
8
+
9
+ from typing import Type, Union, Any
10
+ from starlette.responses import JSONResponse
11
+
12
+ from ..responses import validation_error_response
13
+ from .type_utils import TypeUtils
14
+
15
+
16
+ class TypeConverter:
17
+ """
18
+ Handles conversion of string values to target Python types.
19
+
20
+ This class provides methods to convert string representations of values
21
+ (typically from URL parameters or query strings) to their appropriate
22
+ Python types with comprehensive error handling.
23
+ """
24
+
25
+ @staticmethod
26
+ def convert_value(
27
+ value_str: str,
28
+ target_type: Type,
29
+ param_name: str,
30
+ is_path_param: bool = False,
31
+ ) -> Union[Any, JSONResponse]:
32
+ """
33
+ Convert a string value to the target type with appropriate error handling.
34
+
35
+ This method handles type conversion for query and path parameters,
36
+ including special handling for boolean values and proper error responses.
37
+
38
+ Args:
39
+ value_str: The string value to convert
40
+ target_type: The target Python type to convert to
41
+ param_name: Name of the parameter (for error messages)
42
+ is_path_param: Whether this is a path parameter (affects error response)
43
+
44
+ Returns:
45
+ The converted value, or a JSONResponse with appropriate error code
46
+
47
+ Note:
48
+ - Boolean conversion accepts: "true", "1", "t", "yes" (case-insensitive)
49
+ - Path parameter errors return 404, query parameter errors return 422
50
+
51
+ Examples:
52
+ >>> TypeConverter.convert_value("123", int, "limit")
53
+ 123
54
+ >>> TypeConverter.convert_value("true", bool, "active")
55
+ True
56
+ >>> TypeConverter.convert_value("invalid", int, "limit")
57
+ JSONResponse({"success": False, "error": "Invalid value for integer conversion", ...})
58
+ """
59
+ # Unwrap Optional/Union[T, None]
60
+ target_type, _ = TypeUtils.unwrap_optional(target_type)
61
+
62
+ try:
63
+ if target_type is bool:
64
+ return value_str.lower() in ("true", "1", "t", "yes")
65
+ elif target_type is not str:
66
+ return target_type(value_str)
67
+ else:
68
+ return value_str
69
+ except (ValueError, TypeError):
70
+ if is_path_param:
71
+ return JSONResponse({"detail": "Not Found"}, status_code=404)
72
+ else:
73
+ type_name = TypeUtils.get_type_name(target_type)
74
+ return validation_error_response(
75
+ f"Invalid value for {type_name} conversion"
76
+ )
77
+
78
+ @staticmethod
79
+ def convert_list_values(
80
+ values: list[str], item_type: Type, param_name: str, is_path_param: bool = False
81
+ ) -> Union[list[Any], JSONResponse]:
82
+ """
83
+ Convert a list of string values to the target item type.
84
+
85
+ Args:
86
+ values: List of string values to convert
87
+ item_type: Target type for each item
88
+ param_name: Parameter name for error messages
89
+ is_path_param: Whether this is a path parameter
90
+
91
+ Returns:
92
+ List of converted values or error response
93
+ """
94
+ base_item_type, item_is_optional = TypeUtils.unwrap_optional(item_type)
95
+ converted_list = []
96
+
97
+ for value_str in values:
98
+ # Handle null/empty values for optional items
99
+ if item_is_optional and (value_str == "" or value_str.lower() == "null"):
100
+ converted_list.append(None)
101
+ continue
102
+
103
+ converted_value = TypeConverter.convert_value(
104
+ value_str, base_item_type, param_name, is_path_param
105
+ )
106
+
107
+ # If conversion failed, return the error response
108
+ if isinstance(converted_value, JSONResponse):
109
+ return converted_value
110
+
111
+ converted_list.append(converted_value)
112
+
113
+ return converted_list
@@ -0,0 +1,162 @@
1
+ """
2
+ Tachyon API - Type Utilities
3
+
4
+ This module provides utility functions for working with Python types,
5
+ particularly for handling Optional types, Union types, and generic types
6
+ used throughout the Tachyon framework.
7
+
8
+ This is the centralized module for all type-related utilities to avoid
9
+ code duplication across the framework.
10
+ """
11
+
12
+ import typing
13
+ from typing import Type, Tuple, Union, Dict, Any
14
+
15
+
16
+ # Centralized type mapping from Python types to OpenAPI schema types
17
+ # Used by openapi.py and app.py for schema generation
18
+ OPENAPI_TYPE_MAP: Dict[Type, str] = {
19
+ int: "integer",
20
+ str: "string",
21
+ bool: "boolean",
22
+ float: "number",
23
+ }
24
+
25
+
26
+ class TypeUtils:
27
+ """
28
+ Utility class for type inspection and manipulation.
29
+
30
+ Provides static methods to analyze Python type annotations,
31
+ particularly useful for handling Optional[T], Union types,
32
+ and generic types in parameter processing.
33
+ """
34
+
35
+ @staticmethod
36
+ def unwrap_optional(python_type: Type) -> Tuple[Type, bool]:
37
+ """
38
+ Unwrap Optional[T] types to get the inner type and optionality flag.
39
+
40
+ This method analyzes a type annotation and determines if it represents
41
+ an Optional type (Union[T, None]). It returns the inner type and a
42
+ boolean indicating whether the type is optional.
43
+
44
+ Args:
45
+ python_type: The type annotation to analyze
46
+
47
+ Returns:
48
+ Tuple containing:
49
+ - inner_type: The unwrapped type (T from Optional[T])
50
+ - is_optional: Boolean indicating if the type was Optional
51
+
52
+ Examples:
53
+ >>> TypeUtils.unwrap_optional(Optional[str])
54
+ (str, True)
55
+ >>> TypeUtils.unwrap_optional(str)
56
+ (str, False)
57
+ >>> TypeUtils.unwrap_optional(Union[int, None])
58
+ (int, True)
59
+ """
60
+ origin = typing.get_origin(python_type)
61
+ args = typing.get_args(python_type)
62
+
63
+ if origin is Union and args:
64
+ non_none = [a for a in args if a is not type(None)] # noqa: E721
65
+ if len(non_none) == 1:
66
+ return non_none[0], True
67
+
68
+ return python_type, False
69
+
70
+ @staticmethod
71
+ def is_list_type(python_type: Type) -> Tuple[bool, Type]:
72
+ """
73
+ Check if a type is a List type and extract the item type.
74
+
75
+ Args:
76
+ python_type: The type annotation to check
77
+
78
+ Returns:
79
+ Tuple containing:
80
+ - is_list: Boolean indicating if the type is a List
81
+ - item_type: The type of list items (str if not a list or no args)
82
+
83
+ Examples:
84
+ >>> TypeUtils.is_list_type(List[str])
85
+ (True, str)
86
+ >>> TypeUtils.is_list_type(str)
87
+ (False, str)
88
+ """
89
+ origin = typing.get_origin(python_type)
90
+ args = typing.get_args(python_type)
91
+
92
+ if origin in (list, typing.List):
93
+ item_type = args[0] if args else str
94
+ return True, item_type
95
+
96
+ return False, str
97
+
98
+ @staticmethod
99
+ def get_type_name(python_type: Type) -> str:
100
+ """
101
+ Get a human-readable name for a type.
102
+
103
+ Args:
104
+ python_type: The type to get the name for
105
+
106
+ Returns:
107
+ Human-readable type name
108
+
109
+ Examples:
110
+ >>> TypeUtils.get_type_name(int)
111
+ 'integer'
112
+ >>> TypeUtils.get_type_name(str)
113
+ 'string'
114
+ """
115
+ return OPENAPI_TYPE_MAP.get(
116
+ python_type, getattr(python_type, "__name__", str(python_type))
117
+ )
118
+
119
+ @staticmethod
120
+ def get_openapi_type(python_type: Type) -> str:
121
+ """
122
+ Convert Python type to OpenAPI schema type string.
123
+
124
+ Args:
125
+ python_type: The Python type to convert
126
+
127
+ Returns:
128
+ OpenAPI type string ('integer', 'string', 'boolean', 'number')
129
+
130
+ Examples:
131
+ >>> TypeUtils.get_openapi_type(int)
132
+ 'integer'
133
+ >>> TypeUtils.get_openapi_type(str)
134
+ 'string'
135
+ """
136
+ return OPENAPI_TYPE_MAP.get(python_type, "string")
137
+
138
+ @staticmethod
139
+ def get_origin(python_type: Type) -> Any:
140
+ """
141
+ Get the origin of a generic type (wrapper for typing.get_origin).
142
+
143
+ Args:
144
+ python_type: The type to get the origin for
145
+
146
+ Returns:
147
+ The origin type or None
148
+ """
149
+ return typing.get_origin(python_type)
150
+
151
+ @staticmethod
152
+ def get_args(python_type: Type) -> Tuple:
153
+ """
154
+ Get the arguments of a generic type (wrapper for typing.get_args).
155
+
156
+ Args:
157
+ python_type: The type to get the arguments for
158
+
159
+ Returns:
160
+ Tuple of type arguments
161
+ """
162
+ return typing.get_args(python_type)
@@ -0,0 +1,291 @@
1
+ Metadata-Version: 2.4
2
+ Name: tachyon-api
3
+ Version: 0.9.0
4
+ Summary: A lightweight, FastAPI-inspired web framework
5
+ License: GPL-3.0-or-later
6
+ License-File: LICENSE
7
+ Author: Juan Manuel Panozzo Zรฉnere
8
+ Author-email: jm.panozzozenere@gmail.com
9
+ Requires-Python: >=3.9,<3.14
10
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Requires-Dist: msgspec (>=0.19.0,<0.20.0)
18
+ Requires-Dist: orjson (>=3.11.1,<4.0.0)
19
+ Requires-Dist: python-multipart (>=0.0.20,<0.0.21)
20
+ Requires-Dist: ruff (==0.14.9)
21
+ Requires-Dist: starlette (>=0.47.2,<0.48.0)
22
+ Requires-Dist: typer (>=0.16.0,<0.17.0)
23
+ Requires-Dist: uvicorn (>=0.35.0,<0.36.0)
24
+ Description-Content-Type: text/markdown
25
+
26
+ # ๐Ÿš€ Tachyon API
27
+
28
+ ![Version](https://img.shields.io/badge/version-0.9.0-blue.svg)
29
+ ![Python](https://img.shields.io/badge/python-3.10+-brightgreen.svg)
30
+ ![License](https://img.shields.io/badge/license-GPL--3.0-orange.svg)
31
+ ![Tests](https://img.shields.io/badge/tests-235%20passed-brightgreen.svg)
32
+ ![Status](https://img.shields.io/badge/status-stable-brightgreen.svg)
33
+
34
+ **A lightweight, high-performance API framework for Python with the elegance of FastAPI and the speed of light.**
35
+
36
+ Tachyon API combines the intuitive decorator-based syntax you love with minimal dependencies and maximal performance. Built with Test-Driven Development from the ground up, it offers a cleaner, faster alternative with full ASGI compatibility.
37
+
38
+ ## ๐Ÿš€ Quick Start
39
+
40
+ ```python
41
+ from tachyon_api import Tachyon, Struct, Body, Query
42
+
43
+ app = Tachyon()
44
+
45
+ class User(Struct):
46
+ name: str
47
+ email: str
48
+
49
+ @app.get("/")
50
+ def hello():
51
+ return {"message": "Tachyon is running at lightspeed!"}
52
+
53
+ @app.post("/users")
54
+ def create_user(user: User = Body(...)):
55
+ return {"created": user.name}
56
+
57
+ @app.get("/search")
58
+ def search(q: str = Query(...), limit: int = Query(10)):
59
+ return {"query": q, "limit": limit}
60
+ ```
61
+
62
+ ```bash
63
+ pip install tachyon-api
64
+ uvicorn app:app --reload
65
+ ```
66
+
67
+ ๐Ÿ“– **Docs:** http://localhost:8000/docs
68
+
69
+ ---
70
+
71
+ ## โœจ Features
72
+
73
+ | Category | Features |
74
+ |----------|----------|
75
+ | **Core** | Decorators API, Routers, Middlewares, ASGI compatible |
76
+ | **Parameters** | Path, Query, Body, Header, Cookie, Form, File |
77
+ | **Validation** | msgspec Struct (ultra-fast), automatic 422 errors |
78
+ | **DI** | `@injectable` (implicit), `Depends()` (explicit) |
79
+ | **Security** | HTTPBearer, HTTPBasic, OAuth2, API Keys |
80
+ | **Async** | Background Tasks, WebSockets |
81
+ | **Performance** | orjson serialization, @cache decorator |
82
+ | **Docs** | OpenAPI 3.0, Scalar UI, Swagger, ReDoc |
83
+ | **CLI** | Project scaffolding, code generation, linting |
84
+ | **Testing** | TachyonTestClient, dependency_overrides |
85
+
86
+ ---
87
+
88
+ ## ๐Ÿ“š Documentation
89
+
90
+ Complete documentation is available in the [`docs/`](./docs/) folder:
91
+
92
+ | Guide | Description |
93
+ |-------|-------------|
94
+ | [Getting Started](./docs/01-getting-started.md) | Installation and first project |
95
+ | [Architecture](./docs/02-architecture.md) | Clean architecture patterns |
96
+ | [Dependency Injection](./docs/03-dependency-injection.md) | `@injectable` and `Depends()` |
97
+ | [Parameters](./docs/04-parameters.md) | Path, Query, Body, Header, Cookie, Form, File |
98
+ | [Validation](./docs/05-validation.md) | msgspec Struct validation |
99
+ | [Security](./docs/06-security.md) | JWT, Basic, OAuth2, API Keys |
100
+ | [Caching](./docs/07-caching.md) | `@cache` decorator |
101
+ | [Lifecycle Events](./docs/08-lifecycle.md) | Startup/Shutdown |
102
+ | [Background Tasks](./docs/09-background-tasks.md) | Async task processing |
103
+ | [WebSockets](./docs/10-websockets.md) | Real-time communication |
104
+ | [Testing](./docs/11-testing.md) | TachyonTestClient |
105
+ | [CLI Tools](./docs/12-cli.md) | Scaffolding and generation |
106
+ | [Request Lifecycle](./docs/13-request-lifecycle.md) | How requests are processed |
107
+ | [Migration from FastAPI](./docs/14-migration-fastapi.md) | Migration guide |
108
+ | [Best Practices](./docs/15-best-practices.md) | Recommended patterns |
109
+
110
+ ---
111
+
112
+ ## ๐Ÿฆ Example: KYC Demo API
113
+
114
+ A complete example demonstrating all Tachyon features is available in [`example/`](./example/):
115
+
116
+ ```bash
117
+ cd example
118
+ pip install -r requirements.txt
119
+ uvicorn example.app:app --reload
120
+ ```
121
+
122
+ The KYC Demo implements:
123
+ - ๐Ÿ” JWT Authentication
124
+ - ๐Ÿ‘ค Customer CRUD
125
+ - ๐Ÿ“‹ KYC Verification with Background Tasks
126
+ - ๐Ÿ“ Document Uploads
127
+ - ๐ŸŒ WebSocket Notifications
128
+ - ๐Ÿงช 12 Tests with Mocks
129
+
130
+ **Demo credentials:** `demo@example.com` / `demo123`
131
+
132
+ ๐Ÿ‘‰ See [example/README.md](./example/README.md) for full details.
133
+
134
+ ---
135
+
136
+ ## ๐Ÿ”Œ Core Dependencies
137
+
138
+ | Package | Purpose |
139
+ |---------|---------|
140
+ | `starlette` | ASGI framework |
141
+ | `msgspec` | Ultra-fast validation/serialization |
142
+ | `orjson` | High-performance JSON |
143
+ | `uvicorn` | ASGI server |
144
+
145
+ ---
146
+
147
+ ## ๐Ÿ’‰ Dependency Injection
148
+
149
+ ```python
150
+ from tachyon_api import injectable, Depends
151
+
152
+ @injectable
153
+ class UserService:
154
+ def get_user(self, id: str):
155
+ return {"id": id}
156
+
157
+ @app.get("/users/{id}")
158
+ def get_user(id: str, service: UserService = Depends()):
159
+ return service.get_user(id)
160
+ ```
161
+
162
+ ๐Ÿ‘‰ [Full DI documentation](./docs/03-dependency-injection.md)
163
+
164
+ ---
165
+
166
+ ## ๐Ÿ” Security
167
+
168
+ ```python
169
+ from tachyon_api.security import HTTPBearer, OAuth2PasswordBearer
170
+
171
+ bearer = HTTPBearer()
172
+
173
+ @app.get("/protected")
174
+ async def protected(credentials = Depends(bearer)):
175
+ return {"token": credentials.credentials}
176
+ ```
177
+
178
+ ๐Ÿ‘‰ [Full Security documentation](./docs/06-security.md)
179
+
180
+ ---
181
+
182
+ ## โšก Background Tasks
183
+
184
+ ```python
185
+ from tachyon_api.background import BackgroundTasks
186
+
187
+ @app.post("/notify")
188
+ def notify(background_tasks: BackgroundTasks):
189
+ background_tasks.add_task(send_email, "user@example.com")
190
+ return {"status": "queued"}
191
+ ```
192
+
193
+ ๐Ÿ‘‰ [Full Background Tasks documentation](./docs/09-background-tasks.md)
194
+
195
+ ---
196
+
197
+ ## ๐ŸŒ WebSockets
198
+
199
+ ```python
200
+ @app.websocket("/ws")
201
+ async def websocket(ws):
202
+ await ws.accept()
203
+ data = await ws.receive_text()
204
+ await ws.send_text(f"Echo: {data}")
205
+ ```
206
+
207
+ ๐Ÿ‘‰ [Full WebSockets documentation](./docs/10-websockets.md)
208
+
209
+ ---
210
+
211
+ ## ๐Ÿ”ง CLI Tools
212
+
213
+ ```bash
214
+ # Create new project
215
+ tachyon new my-api
216
+
217
+ # Generate module
218
+ tachyon generate service users --crud
219
+
220
+ # Code quality
221
+ tachyon lint all
222
+ ```
223
+
224
+ ๐Ÿ‘‰ [Full CLI documentation](./docs/12-cli.md)
225
+
226
+ ---
227
+
228
+ ## ๐Ÿงช Testing
229
+
230
+ ```python
231
+ from tachyon_api.testing import TachyonTestClient
232
+
233
+ def test_hello():
234
+ client = TachyonTestClient(app)
235
+ response = client.get("/")
236
+ assert response.status_code == 200
237
+ ```
238
+
239
+ ```bash
240
+ pytest tests/ -v
241
+ ```
242
+
243
+ ๐Ÿ‘‰ [Full Testing documentation](./docs/11-testing.md)
244
+
245
+ ---
246
+
247
+ ## ๐Ÿ“Š Why Tachyon?
248
+
249
+ | Feature | Tachyon | FastAPI |
250
+ |---------|---------|---------|
251
+ | **Serialization** | msgspec + orjson | pydantic |
252
+ | **Performance** | โšกโšกโšก Ultra-fast | โšก Fast |
253
+ | **Bundle Size** | Minimal | Larger |
254
+ | **Learning Curve** | Easy (FastAPI-like) | Easy |
255
+ | **Type Safety** | Full | Full |
256
+
257
+ ---
258
+
259
+ ## ๐Ÿ“ Contributing
260
+
261
+ Contributions are welcome! Please feel free to submit a Pull Request.
262
+
263
+ 1. Fork the repository
264
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
265
+ 3. Run tests (`pytest tests/ -v`)
266
+ 4. Commit your changes (`git commit -m 'Add some amazing feature'`)
267
+ 5. Push to the branch (`git push origin feature/amazing-feature`)
268
+ 6. Open a Pull Request
269
+
270
+ ---
271
+
272
+ ## ๐Ÿ“œ License
273
+
274
+ This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
275
+
276
+ ---
277
+
278
+ ## ๐Ÿ”ฎ What's Next
279
+
280
+ See [CHANGELOG.md](./CHANGELOG.md) for version history.
281
+
282
+ Upcoming features:
283
+ - Response streaming
284
+ - GraphQL support
285
+ - More deployment guides
286
+ - Performance benchmarks
287
+
288
+ ---
289
+
290
+ *Built with ๐Ÿ’œ by developers, for developers*
291
+