django-bolt 0.1.0__cp310-abi3-win_amd64.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.
Potentially problematic release.
This version of django-bolt might be problematic. Click here for more details.
- django_bolt/__init__.py +147 -0
- django_bolt/_core.pyd +0 -0
- django_bolt/admin/__init__.py +25 -0
- django_bolt/admin/admin_detection.py +179 -0
- django_bolt/admin/asgi_bridge.py +267 -0
- django_bolt/admin/routes.py +91 -0
- django_bolt/admin/static.py +155 -0
- django_bolt/admin/static_routes.py +111 -0
- django_bolt/api.py +1011 -0
- django_bolt/apps.py +7 -0
- django_bolt/async_collector.py +228 -0
- django_bolt/auth/README.md +464 -0
- django_bolt/auth/REVOCATION_EXAMPLE.md +391 -0
- django_bolt/auth/__init__.py +84 -0
- django_bolt/auth/backends.py +236 -0
- django_bolt/auth/guards.py +224 -0
- django_bolt/auth/jwt_utils.py +212 -0
- django_bolt/auth/revocation.py +286 -0
- django_bolt/auth/token.py +335 -0
- django_bolt/binding.py +363 -0
- django_bolt/bootstrap.py +77 -0
- django_bolt/cli.py +133 -0
- django_bolt/compression.py +104 -0
- django_bolt/decorators.py +159 -0
- django_bolt/dependencies.py +128 -0
- django_bolt/error_handlers.py +305 -0
- django_bolt/exceptions.py +294 -0
- django_bolt/health.py +129 -0
- django_bolt/logging/__init__.py +6 -0
- django_bolt/logging/config.py +357 -0
- django_bolt/logging/middleware.py +296 -0
- django_bolt/management/__init__.py +1 -0
- django_bolt/management/commands/__init__.py +0 -0
- django_bolt/management/commands/runbolt.py +427 -0
- django_bolt/middleware/__init__.py +32 -0
- django_bolt/middleware/compiler.py +131 -0
- django_bolt/middleware/middleware.py +247 -0
- django_bolt/openapi/__init__.py +23 -0
- django_bolt/openapi/config.py +196 -0
- django_bolt/openapi/plugins.py +439 -0
- django_bolt/openapi/routes.py +152 -0
- django_bolt/openapi/schema_generator.py +581 -0
- django_bolt/openapi/spec/__init__.py +68 -0
- django_bolt/openapi/spec/base.py +74 -0
- django_bolt/openapi/spec/callback.py +24 -0
- django_bolt/openapi/spec/components.py +72 -0
- django_bolt/openapi/spec/contact.py +21 -0
- django_bolt/openapi/spec/discriminator.py +25 -0
- django_bolt/openapi/spec/encoding.py +67 -0
- django_bolt/openapi/spec/enums.py +41 -0
- django_bolt/openapi/spec/example.py +36 -0
- django_bolt/openapi/spec/external_documentation.py +21 -0
- django_bolt/openapi/spec/header.py +132 -0
- django_bolt/openapi/spec/info.py +50 -0
- django_bolt/openapi/spec/license.py +28 -0
- django_bolt/openapi/spec/link.py +66 -0
- django_bolt/openapi/spec/media_type.py +51 -0
- django_bolt/openapi/spec/oauth_flow.py +36 -0
- django_bolt/openapi/spec/oauth_flows.py +28 -0
- django_bolt/openapi/spec/open_api.py +87 -0
- django_bolt/openapi/spec/operation.py +105 -0
- django_bolt/openapi/spec/parameter.py +147 -0
- django_bolt/openapi/spec/path_item.py +78 -0
- django_bolt/openapi/spec/paths.py +27 -0
- django_bolt/openapi/spec/reference.py +38 -0
- django_bolt/openapi/spec/request_body.py +38 -0
- django_bolt/openapi/spec/response.py +48 -0
- django_bolt/openapi/spec/responses.py +44 -0
- django_bolt/openapi/spec/schema.py +678 -0
- django_bolt/openapi/spec/security_requirement.py +28 -0
- django_bolt/openapi/spec/security_scheme.py +69 -0
- django_bolt/openapi/spec/server.py +34 -0
- django_bolt/openapi/spec/server_variable.py +32 -0
- django_bolt/openapi/spec/tag.py +32 -0
- django_bolt/openapi/spec/xml.py +44 -0
- django_bolt/pagination.py +669 -0
- django_bolt/param_functions.py +49 -0
- django_bolt/params.py +337 -0
- django_bolt/request_parsing.py +128 -0
- django_bolt/responses.py +214 -0
- django_bolt/router.py +48 -0
- django_bolt/serialization.py +193 -0
- django_bolt/status_codes.py +321 -0
- django_bolt/testing/__init__.py +10 -0
- django_bolt/testing/client.py +274 -0
- django_bolt/testing/helpers.py +93 -0
- django_bolt/tests/__init__.py +0 -0
- django_bolt/tests/admin_tests/__init__.py +1 -0
- django_bolt/tests/admin_tests/conftest.py +6 -0
- django_bolt/tests/admin_tests/test_admin_with_django.py +278 -0
- django_bolt/tests/admin_tests/urls.py +9 -0
- django_bolt/tests/cbv/__init__.py +0 -0
- django_bolt/tests/cbv/test_class_views.py +570 -0
- django_bolt/tests/cbv/test_class_views_django_orm.py +703 -0
- django_bolt/tests/cbv/test_class_views_features.py +1173 -0
- django_bolt/tests/cbv/test_class_views_with_client.py +622 -0
- django_bolt/tests/conftest.py +165 -0
- django_bolt/tests/test_action_decorator.py +399 -0
- django_bolt/tests/test_auth_secret_key.py +83 -0
- django_bolt/tests/test_decorator_syntax.py +159 -0
- django_bolt/tests/test_error_handling.py +481 -0
- django_bolt/tests/test_file_response.py +192 -0
- django_bolt/tests/test_global_cors.py +172 -0
- django_bolt/tests/test_guards_auth.py +441 -0
- django_bolt/tests/test_guards_integration.py +303 -0
- django_bolt/tests/test_health.py +283 -0
- django_bolt/tests/test_integration_validation.py +400 -0
- django_bolt/tests/test_json_validation.py +536 -0
- django_bolt/tests/test_jwt_auth.py +327 -0
- django_bolt/tests/test_jwt_token.py +458 -0
- django_bolt/tests/test_logging.py +837 -0
- django_bolt/tests/test_logging_merge.py +419 -0
- django_bolt/tests/test_middleware.py +492 -0
- django_bolt/tests/test_middleware_server.py +230 -0
- django_bolt/tests/test_model_viewset.py +323 -0
- django_bolt/tests/test_models.py +24 -0
- django_bolt/tests/test_pagination.py +1258 -0
- django_bolt/tests/test_parameter_validation.py +178 -0
- django_bolt/tests/test_syntax.py +626 -0
- django_bolt/tests/test_testing_utilities.py +163 -0
- django_bolt/tests/test_testing_utilities_simple.py +123 -0
- django_bolt/tests/test_viewset_unified.py +346 -0
- django_bolt/typing.py +273 -0
- django_bolt/views.py +1110 -0
- django_bolt-0.1.0.dist-info/METADATA +629 -0
- django_bolt-0.1.0.dist-info/RECORD +128 -0
- django_bolt-0.1.0.dist-info/WHEEL +4 -0
- django_bolt-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Django admin route registration for BoltAPI.
|
|
3
|
+
|
|
4
|
+
This module handles the registration of Django admin routes via ASGI bridge,
|
|
5
|
+
keeping the BoltAPI class lean and focused.
|
|
6
|
+
"""
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from django_bolt.api import BoltAPI
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AdminRouteRegistrar:
|
|
14
|
+
"""Handles registration of Django admin routes via ASGI bridge."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, api: 'BoltAPI'):
|
|
17
|
+
"""Initialize the registrar with a BoltAPI instance.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
api: The BoltAPI instance to register routes on
|
|
21
|
+
"""
|
|
22
|
+
self.api = api
|
|
23
|
+
|
|
24
|
+
def register_routes(self, host: str = "localhost", port: int = 8000) -> None:
|
|
25
|
+
"""Register Django admin routes via ASGI bridge.
|
|
26
|
+
|
|
27
|
+
This method auto-registers routes for Django admin if it's installed
|
|
28
|
+
and enabled. The routes use an ASGI bridge to handle Django's middleware
|
|
29
|
+
stack (sessions, CSRF, auth, etc.).
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
host: Server hostname for ASGI scope
|
|
33
|
+
port: Server port for ASGI scope
|
|
34
|
+
"""
|
|
35
|
+
if self.api._admin_routes_registered:
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
# Check if admin should be enabled
|
|
39
|
+
from django_bolt.admin.admin_detection import should_enable_admin, get_admin_route_patterns
|
|
40
|
+
|
|
41
|
+
if not should_enable_admin():
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
# Get admin route patterns
|
|
45
|
+
route_patterns = get_admin_route_patterns()
|
|
46
|
+
if not route_patterns:
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
# Lazy-load ASGI handler
|
|
50
|
+
if self.api._asgi_handler is None:
|
|
51
|
+
from django_bolt.admin.asgi_bridge import ASGIFallbackHandler
|
|
52
|
+
self.api._asgi_handler = ASGIFallbackHandler(host, port)
|
|
53
|
+
|
|
54
|
+
# Register admin routes for each method
|
|
55
|
+
for path_pattern, methods in route_patterns:
|
|
56
|
+
for method in methods:
|
|
57
|
+
self._register_admin_route(method, path_pattern)
|
|
58
|
+
|
|
59
|
+
self.api._admin_routes_registered = True
|
|
60
|
+
|
|
61
|
+
def _register_admin_route(self, method: str, path_pattern: str) -> None:
|
|
62
|
+
"""Register a single admin route.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
method: HTTP method (GET, POST, etc.)
|
|
66
|
+
path_pattern: URL path pattern
|
|
67
|
+
"""
|
|
68
|
+
# Create handler that delegates to ASGI bridge
|
|
69
|
+
# NOTE: We need to create a new function for each route to avoid closure issues
|
|
70
|
+
def make_admin_handler(asgi_handler):
|
|
71
|
+
async def admin_handler(request):
|
|
72
|
+
return await asgi_handler.handle_request(request)
|
|
73
|
+
return admin_handler
|
|
74
|
+
|
|
75
|
+
admin_handler = make_admin_handler(self.api._asgi_handler)
|
|
76
|
+
|
|
77
|
+
# Register the route using internal route registration
|
|
78
|
+
# This bypasses the decorator to avoid async enforcement issues
|
|
79
|
+
handler_id = self.api._next_handler_id
|
|
80
|
+
self.api._next_handler_id += 1
|
|
81
|
+
|
|
82
|
+
self.api._routes.append((method, path_pattern, handler_id, admin_handler))
|
|
83
|
+
self.api._handlers[handler_id] = admin_handler
|
|
84
|
+
|
|
85
|
+
# Create minimal metadata for admin handlers
|
|
86
|
+
meta = {
|
|
87
|
+
"mode": "request_only",
|
|
88
|
+
"sig": None,
|
|
89
|
+
"fields": [],
|
|
90
|
+
}
|
|
91
|
+
self.api._handler_meta[admin_handler] = meta
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Static file serving utilities for Django-Bolt.
|
|
3
|
+
|
|
4
|
+
Provides static file serving for Django admin and other static assets.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional, Tuple, List, Dict, Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def find_static_file(path: str) -> Optional[str]:
|
|
13
|
+
"""
|
|
14
|
+
Find a static file using Django's static file finders.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
path: Relative path to static file (e.g., 'admin/css/base.css')
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Absolute path to file if found, None otherwise
|
|
21
|
+
"""
|
|
22
|
+
try:
|
|
23
|
+
from django.conf import settings
|
|
24
|
+
|
|
25
|
+
# First try STATIC_ROOT (collected static files in production)
|
|
26
|
+
if hasattr(settings, 'STATIC_ROOT') and settings.STATIC_ROOT:
|
|
27
|
+
static_root = Path(settings.STATIC_ROOT)
|
|
28
|
+
file_path = static_root / path
|
|
29
|
+
if file_path.exists() and file_path.is_file():
|
|
30
|
+
return str(file_path)
|
|
31
|
+
|
|
32
|
+
# Try using Django's static file finders (development mode)
|
|
33
|
+
try:
|
|
34
|
+
from django.contrib.staticfiles.finders import find
|
|
35
|
+
found_path = find(path)
|
|
36
|
+
if found_path:
|
|
37
|
+
return found_path
|
|
38
|
+
except ImportError:
|
|
39
|
+
# staticfiles not installed
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
# Fallback: check STATICFILES_DIRS
|
|
43
|
+
if hasattr(settings, 'STATICFILES_DIRS'):
|
|
44
|
+
for static_dir in settings.STATICFILES_DIRS:
|
|
45
|
+
if isinstance(static_dir, tuple):
|
|
46
|
+
static_dir = static_dir[1] # (prefix, path) tuple
|
|
47
|
+
file_path = Path(static_dir) / path
|
|
48
|
+
if file_path.exists() and file_path.is_file():
|
|
49
|
+
return str(file_path)
|
|
50
|
+
|
|
51
|
+
except Exception as e:
|
|
52
|
+
import sys
|
|
53
|
+
print(f"[django-bolt] Warning: Error finding static file {path}: {e}", file=sys.stderr)
|
|
54
|
+
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def guess_content_type(file_path: str) -> str:
|
|
59
|
+
"""
|
|
60
|
+
Guess content type from file extension.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
file_path: Path to file
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
MIME type string
|
|
67
|
+
"""
|
|
68
|
+
import mimetypes
|
|
69
|
+
|
|
70
|
+
content_type, _ = mimetypes.guess_type(file_path)
|
|
71
|
+
if content_type:
|
|
72
|
+
return content_type
|
|
73
|
+
|
|
74
|
+
# Fallback for common static file types
|
|
75
|
+
ext = os.path.splitext(file_path)[1].lower()
|
|
76
|
+
type_map = {
|
|
77
|
+
'.css': 'text/css',
|
|
78
|
+
'.js': 'application/javascript',
|
|
79
|
+
'.json': 'application/json',
|
|
80
|
+
'.png': 'image/png',
|
|
81
|
+
'.jpg': 'image/jpeg',
|
|
82
|
+
'.jpeg': 'image/jpeg',
|
|
83
|
+
'.gif': 'image/gif',
|
|
84
|
+
'.svg': 'image/svg+xml',
|
|
85
|
+
'.ico': 'image/x-icon',
|
|
86
|
+
'.woff': 'font/woff',
|
|
87
|
+
'.woff2': 'font/woff2',
|
|
88
|
+
'.ttf': 'font/ttf',
|
|
89
|
+
'.eot': 'application/vnd.ms-fontobject',
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return type_map.get(ext, 'application/octet-stream')
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
async def serve_static_file(path: str) -> Tuple[int, List[Tuple[str, str]], bytes]:
|
|
96
|
+
"""
|
|
97
|
+
Serve a static file using Django's static file system.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
path: Relative path to static file
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Response tuple: (status_code, headers, body)
|
|
104
|
+
"""
|
|
105
|
+
from ..exceptions import HTTPException
|
|
106
|
+
|
|
107
|
+
# Security: prevent directory traversal
|
|
108
|
+
if '..' in path or path.startswith('/'):
|
|
109
|
+
raise HTTPException(400, "Invalid static file path")
|
|
110
|
+
|
|
111
|
+
# Find the static file
|
|
112
|
+
file_path = find_static_file(path)
|
|
113
|
+
|
|
114
|
+
if not file_path:
|
|
115
|
+
raise HTTPException(404, f"Static file not found: {path}")
|
|
116
|
+
|
|
117
|
+
# Return FileResponse (Rust will handle streaming)
|
|
118
|
+
from ..responses import FileResponse
|
|
119
|
+
content_type = guess_content_type(file_path)
|
|
120
|
+
|
|
121
|
+
# Use FileResponse which returns the special file response format
|
|
122
|
+
return FileResponse(
|
|
123
|
+
file_path,
|
|
124
|
+
headers={"content-type": content_type}
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def register_static_routes(api, static_url: Optional[str] = None):
|
|
129
|
+
"""
|
|
130
|
+
Register static file serving routes on a BoltAPI instance.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
api: BoltAPI instance
|
|
134
|
+
static_url: Static URL prefix (default: from settings.STATIC_URL)
|
|
135
|
+
"""
|
|
136
|
+
from django.conf import settings
|
|
137
|
+
|
|
138
|
+
if static_url is None:
|
|
139
|
+
if not hasattr(settings, 'STATIC_URL') or not settings.STATIC_URL:
|
|
140
|
+
# Static files not configured
|
|
141
|
+
return
|
|
142
|
+
static_url = settings.STATIC_URL.strip('/')
|
|
143
|
+
|
|
144
|
+
if not static_url:
|
|
145
|
+
static_url = 'static'
|
|
146
|
+
|
|
147
|
+
# Register catch-all route for static files
|
|
148
|
+
route_pattern = f'/{static_url}/{{path:path}}'
|
|
149
|
+
|
|
150
|
+
@api.get(route_pattern)
|
|
151
|
+
async def serve_static(path: str):
|
|
152
|
+
"""Serve static files for Django admin and other apps."""
|
|
153
|
+
return await serve_static_file(path)
|
|
154
|
+
|
|
155
|
+
return serve_static
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Static file route registration for Django admin.
|
|
3
|
+
|
|
4
|
+
This module handles the registration of static file serving routes
|
|
5
|
+
needed by Django admin and other Django apps.
|
|
6
|
+
"""
|
|
7
|
+
import inspect
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from django_bolt.api import BoltAPI
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class StaticRouteRegistrar:
|
|
15
|
+
"""Handles registration of static file serving routes."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, api: 'BoltAPI'):
|
|
18
|
+
"""Initialize the registrar with a BoltAPI instance.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
api: The BoltAPI instance to register routes on
|
|
22
|
+
"""
|
|
23
|
+
self.api = api
|
|
24
|
+
|
|
25
|
+
def register_routes(self) -> None:
|
|
26
|
+
"""Register static file serving routes for Django admin.
|
|
27
|
+
|
|
28
|
+
This enables serving of CSS, JS, and other static assets needed
|
|
29
|
+
by Django admin and other Django apps.
|
|
30
|
+
"""
|
|
31
|
+
if self.api._static_routes_registered:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
# Only register static routes if admin routes were registered
|
|
35
|
+
# (admin needs static files for CSS/JS)
|
|
36
|
+
if not self.api._admin_routes_registered:
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
from django.conf import settings
|
|
41
|
+
|
|
42
|
+
# Check if static files are configured
|
|
43
|
+
if not hasattr(settings, 'STATIC_URL') or not settings.STATIC_URL:
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
static_url = settings.STATIC_URL.strip('/')
|
|
47
|
+
if not static_url:
|
|
48
|
+
static_url = 'static'
|
|
49
|
+
|
|
50
|
+
# Register catch-all route for static files
|
|
51
|
+
route_pattern = f'/{static_url}/{{path:path}}'
|
|
52
|
+
|
|
53
|
+
# Import here to avoid circular dependency
|
|
54
|
+
from django_bolt.admin.static import serve_static_file
|
|
55
|
+
|
|
56
|
+
# Create static file handler
|
|
57
|
+
async def static_handler(path: str):
|
|
58
|
+
"""Serve static files for Django admin and other apps."""
|
|
59
|
+
return await serve_static_file(path)
|
|
60
|
+
|
|
61
|
+
# Register the route
|
|
62
|
+
self._register_static_route(route_pattern, static_handler)
|
|
63
|
+
|
|
64
|
+
self.api._static_routes_registered = True
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
import sys
|
|
68
|
+
print(f"[django-bolt] Warning: Failed to register static routes: {e}", file=sys.stderr)
|
|
69
|
+
|
|
70
|
+
def _register_static_route(self, route_pattern: str, handler) -> None:
|
|
71
|
+
"""Register a static file serving route.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
route_pattern: URL path pattern (e.g., /static/{path:path})
|
|
75
|
+
handler: Async handler function for serving static files
|
|
76
|
+
"""
|
|
77
|
+
handler_id = self.api._next_handler_id
|
|
78
|
+
self.api._next_handler_id += 1
|
|
79
|
+
|
|
80
|
+
self.api._routes.append(("GET", route_pattern, handler_id, handler))
|
|
81
|
+
self.api._handlers[handler_id] = handler
|
|
82
|
+
|
|
83
|
+
# Create metadata for static handler
|
|
84
|
+
# Extract path parameter metadata
|
|
85
|
+
sig = inspect.signature(handler)
|
|
86
|
+
meta = {
|
|
87
|
+
"mode": "mixed",
|
|
88
|
+
"sig": sig,
|
|
89
|
+
"fields": [{
|
|
90
|
+
"name": "path",
|
|
91
|
+
"annotation": str,
|
|
92
|
+
"default": inspect.Parameter.empty,
|
|
93
|
+
"kind": inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
94
|
+
"source": "path",
|
|
95
|
+
"alias": None,
|
|
96
|
+
"embed": False,
|
|
97
|
+
"dependency": None,
|
|
98
|
+
}],
|
|
99
|
+
"path_params": {"path"},
|
|
100
|
+
"params": [{
|
|
101
|
+
"name": "path",
|
|
102
|
+
"annotation": str,
|
|
103
|
+
"default": inspect.Parameter.empty,
|
|
104
|
+
"kind": inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
105
|
+
"source": "path",
|
|
106
|
+
"alias": None,
|
|
107
|
+
"embed": False,
|
|
108
|
+
"dependency": None,
|
|
109
|
+
}],
|
|
110
|
+
}
|
|
111
|
+
self.api._handler_meta[handler] = meta
|