django-cfg 1.4.9__py3-none-any.whl → 1.4.11__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.
- django_cfg/apps/agents/management/commands/create_agent.py +1 -1
- django_cfg/apps/agents/management/commands/orchestrator_status.py +3 -3
- django_cfg/apps/newsletter/serializers.py +40 -3
- django_cfg/apps/newsletter/views/campaigns.py +12 -3
- django_cfg/apps/newsletter/views/emails.py +14 -3
- django_cfg/apps/newsletter/views/subscriptions.py +12 -2
- django_cfg/apps/payments/middleware/api_access.py +6 -2
- django_cfg/apps/payments/middleware/rate_limiting.py +2 -1
- django_cfg/apps/payments/middleware/usage_tracking.py +5 -1
- django_cfg/apps/payments/models/managers/api_key_managers.py +0 -1
- django_cfg/apps/payments/models/managers/subscription_managers.py +0 -1
- django_cfg/apps/payments/services/core/balance_service.py +5 -5
- django_cfg/apps/payments/services/core/subscription_service.py +1 -2
- django_cfg/apps/payments/views/api/balances.py +8 -7
- django_cfg/apps/payments/views/api/base.py +10 -6
- django_cfg/apps/payments/views/api/currencies.py +53 -10
- django_cfg/apps/payments/views/api/payments.py +3 -1
- django_cfg/apps/payments/views/api/subscriptions.py +2 -5
- django_cfg/apps/payments/views/api/webhooks.py +72 -7
- django_cfg/apps/payments/views/overview/serializers.py +34 -1
- django_cfg/apps/payments/views/overview/views.py +2 -1
- django_cfg/apps/payments/views/serializers/payments.py +6 -6
- django_cfg/apps/urls.py +106 -45
- django_cfg/core/base/config_model.py +2 -2
- django_cfg/core/constants.py +1 -1
- django_cfg/core/generation/integration_generators/__init__.py +1 -1
- django_cfg/core/generation/integration_generators/api.py +82 -41
- django_cfg/core/integration/display/startup.py +30 -22
- django_cfg/core/integration/url_integration.py +15 -16
- django_cfg/dashboard/sections/documentation.py +391 -0
- django_cfg/management/commands/check_endpoints.py +11 -160
- django_cfg/management/commands/check_settings.py +13 -265
- django_cfg/management/commands/clear_constance.py +13 -201
- django_cfg/management/commands/create_token.py +13 -321
- django_cfg/management/commands/generate_clients.py +23 -0
- django_cfg/management/commands/list_urls.py +13 -306
- django_cfg/management/commands/migrate_all.py +13 -126
- django_cfg/management/commands/migrator.py +13 -396
- django_cfg/management/commands/rundramatiq.py +15 -247
- django_cfg/management/commands/rundramatiq_simulator.py +12 -429
- django_cfg/management/commands/runserver_ngrok.py +15 -160
- django_cfg/management/commands/script.py +12 -488
- django_cfg/management/commands/show_config.py +12 -215
- django_cfg/management/commands/show_urls.py +12 -342
- django_cfg/management/commands/superuser.py +15 -295
- django_cfg/management/commands/task_clear.py +14 -217
- django_cfg/management/commands/task_status.py +13 -248
- django_cfg/management/commands/test_email.py +15 -86
- django_cfg/management/commands/test_telegram.py +14 -61
- django_cfg/management/commands/test_twilio.py +15 -105
- django_cfg/management/commands/tree.py +13 -383
- django_cfg/management/commands/validate_openapi.py +10 -0
- django_cfg/middleware/README.md +1 -1
- django_cfg/middleware/user_activity.py +3 -3
- django_cfg/models/__init__.py +2 -2
- django_cfg/models/api/drf/spectacular.py +6 -6
- django_cfg/models/django/__init__.py +2 -2
- django_cfg/models/django/openapi.py +238 -0
- django_cfg/models/django/{revolution.py → revolution_legacy.py} +8 -0
- django_cfg/modules/django_admin/management/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/__init__.py +0 -0
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +169 -0
- django_cfg/modules/django_admin/management/commands/check_settings.py +355 -0
- django_cfg/modules/django_admin/management/commands/clear_constance.py +208 -0
- django_cfg/modules/django_admin/management/commands/create_token.py +328 -0
- django_cfg/modules/django_admin/management/commands/list_urls.py +313 -0
- django_cfg/modules/django_admin/management/commands/migrate_all.py +133 -0
- django_cfg/modules/django_admin/management/commands/migrator.py +403 -0
- django_cfg/modules/django_admin/management/commands/script.py +496 -0
- django_cfg/modules/django_admin/management/commands/show_config.py +225 -0
- django_cfg/modules/django_admin/management/commands/show_urls.py +361 -0
- django_cfg/modules/django_admin/management/commands/superuser.py +302 -0
- django_cfg/modules/django_admin/management/commands/tree.py +390 -0
- django_cfg/modules/django_client/__init__.py +20 -0
- django_cfg/modules/django_client/apps.py +35 -0
- django_cfg/modules/django_client/core/__init__.py +56 -0
- django_cfg/modules/django_client/core/archive/__init__.py +11 -0
- django_cfg/modules/django_client/core/archive/manager.py +134 -0
- django_cfg/modules/django_client/core/cli/__init__.py +12 -0
- django_cfg/modules/django_client/core/cli/main.py +235 -0
- django_cfg/modules/django_client/core/config/__init__.py +18 -0
- django_cfg/modules/django_client/core/config/config.py +188 -0
- django_cfg/modules/django_client/core/config/group.py +101 -0
- django_cfg/modules/django_client/core/config/service.py +209 -0
- django_cfg/modules/django_client/core/generator/__init__.py +115 -0
- django_cfg/modules/django_client/core/generator/base.py +767 -0
- django_cfg/modules/django_client/core/generator/python.py +751 -0
- django_cfg/modules/django_client/core/generator/templates/python/__init__.py.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/python/api_wrapper.py.jinja +130 -0
- django_cfg/modules/django_client/core/generator/templates/python/app_init.py.jinja +6 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/app_client.py.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/flat_client.py.jinja +38 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/main_client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/operation_method.py.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/python/client/sub_client.py.jinja +11 -0
- django_cfg/modules/django_client/core/generator/templates/python/client_file.py.jinja +13 -0
- django_cfg/modules/django_client/core/generator/templates/python/main_init.py.jinja +50 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/app_models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enum_class.py.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/enums.py.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/models.py.jinja +17 -0
- django_cfg/modules/django_client/core/generator/templates/python/models/schema_class.py.jinja +19 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/logger.py.jinja +255 -0
- django_cfg/modules/django_client/core/generator/templates/python/utils/schema.py.jinja +12 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/app_index.ts.jinja +2 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/app_client.ts.jinja +18 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/client.ts.jinja +327 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/flat_client.ts.jinja +109 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/main_client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/operation.ts.jinja +61 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client/sub_client.ts.jinja +15 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/client_file.ts.jinja +9 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/index.ts.jinja +5 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/main_index.ts.jinja +206 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/app_models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/enums.ts.jinja +4 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/models/models.ts.jinja +8 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/errors.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/http.ts.jinja +98 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/logger.ts.jinja +251 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/schema.ts.jinja +7 -0
- django_cfg/modules/django_client/core/generator/templates/typescript/utils/storage.ts.jinja +114 -0
- django_cfg/modules/django_client/core/generator/typescript.py +872 -0
- django_cfg/modules/django_client/core/groups/__init__.py +13 -0
- django_cfg/modules/django_client/core/groups/detector.py +178 -0
- django_cfg/modules/django_client/core/groups/manager.py +314 -0
- django_cfg/modules/django_client/core/ir/__init__.py +57 -0
- django_cfg/modules/django_client/core/ir/context.py +387 -0
- django_cfg/modules/django_client/core/ir/operation.py +518 -0
- django_cfg/modules/django_client/core/ir/schema.py +353 -0
- django_cfg/modules/django_client/core/parser/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/base.py +648 -0
- django_cfg/modules/django_client/core/parser/models/__init__.py +74 -0
- django_cfg/modules/django_client/core/parser/models/base.py +212 -0
- django_cfg/modules/django_client/core/parser/models/components.py +160 -0
- django_cfg/modules/django_client/core/parser/models/openapi.py +203 -0
- django_cfg/modules/django_client/core/parser/models/operation.py +207 -0
- django_cfg/modules/django_client/core/parser/models/schema.py +266 -0
- django_cfg/modules/django_client/core/parser/openapi30.py +56 -0
- django_cfg/modules/django_client/core/parser/openapi31.py +64 -0
- django_cfg/modules/django_client/core/validation/__init__.py +22 -0
- django_cfg/modules/django_client/core/validation/checker.py +134 -0
- django_cfg/modules/django_client/core/validation/fixer.py +216 -0
- django_cfg/modules/django_client/core/validation/reporter.py +480 -0
- django_cfg/modules/django_client/core/validation/rules/__init__.py +11 -0
- django_cfg/modules/django_client/core/validation/rules/base.py +96 -0
- django_cfg/modules/django_client/core/validation/rules/type_hints.py +288 -0
- django_cfg/modules/django_client/core/validation/safety.py +266 -0
- django_cfg/modules/django_client/management/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/__init__.py +3 -0
- django_cfg/modules/django_client/management/commands/generate_client.py +422 -0
- django_cfg/modules/django_client/management/commands/validate_openapi.py +343 -0
- django_cfg/modules/django_client/spectacular/__init__.py +9 -0
- django_cfg/modules/django_client/spectacular/enum_naming.py +192 -0
- django_cfg/modules/django_client/urls.py +72 -0
- django_cfg/modules/django_email/management/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/__init__.py +0 -0
- django_cfg/modules/django_email/management/commands/test_email.py +93 -0
- django_cfg/modules/django_logging/django_logger.py +6 -6
- django_cfg/modules/django_ngrok/management/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/__init__.py +0 -0
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +167 -0
- django_cfg/modules/django_tasks/management/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/__init__.py +0 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +254 -0
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +437 -0
- django_cfg/modules/django_tasks/management/commands/task_clear.py +226 -0
- django_cfg/modules/django_tasks/management/commands/task_status.py +257 -0
- django_cfg/modules/django_telegram/management/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/__init__.py +0 -0
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +68 -0
- django_cfg/modules/django_twilio/management/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/__init__.py +0 -0
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +112 -0
- django_cfg/modules/django_unfold/callbacks/main.py +16 -5
- django_cfg/modules/django_unfold/callbacks/revolution.py +41 -36
- django_cfg/modules/django_unfold/dashboard.py +1 -1
- django_cfg/pyproject.toml +2 -6
- django_cfg/registry/third_party.py +5 -7
- django_cfg/routing/callbacks.py +1 -1
- django_cfg/static/admin/css/prose-unfold.css +666 -0
- django_cfg/templates/admin/index.html +8 -0
- django_cfg/templates/admin/index_new.html +13 -0
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +15 -3
- django_cfg/templates/admin/sections/documentation_section.html +172 -0
- django_cfg/templates/admin/snippets/tabs/documentation_tab.html +231 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/METADATA +2 -2
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/RECORD +192 -71
- django_cfg/management/commands/generate.py +0 -107
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.9.dist-info → django_cfg-1.4.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
"""
|
2
|
+
Django Client - Django integration for openapi_client.
|
3
|
+
|
4
|
+
Provides Django management commands and URL integration.
|
5
|
+
"""
|
6
|
+
|
7
|
+
# Django AppConfig
|
8
|
+
default_app_config = 'django_cfg.modules.django_client.apps.DjangoClientConfig'
|
9
|
+
|
10
|
+
# Re-export everything from openapi_client
|
11
|
+
from django_cfg.modules.django_client.core import * # noqa
|
12
|
+
|
13
|
+
# Django-specific
|
14
|
+
from .management.commands.generate_client import Command as GenerateClientCommand
|
15
|
+
from .urls import get_openapi_urls
|
16
|
+
|
17
|
+
__all__ = [
|
18
|
+
"GenerateClientCommand",
|
19
|
+
"get_openapi_urls",
|
20
|
+
]
|
@@ -0,0 +1,35 @@
|
|
1
|
+
"""
|
2
|
+
Django Client AppConfig.
|
3
|
+
|
4
|
+
Initializes OpenAPI service with configuration from Django settings.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django.apps import AppConfig
|
8
|
+
from django.conf import settings
|
9
|
+
|
10
|
+
|
11
|
+
class DjangoClientConfig(AppConfig):
|
12
|
+
"""AppConfig for django_client."""
|
13
|
+
|
14
|
+
name = 'django_cfg.modules.django_client'
|
15
|
+
verbose_name = 'Django OpenAPI Client'
|
16
|
+
default_auto_field = 'django.db.models.BigAutoField'
|
17
|
+
|
18
|
+
def ready(self):
|
19
|
+
"""Initialize OpenAPI service on app startup."""
|
20
|
+
# Import here to avoid AppRegistryNotReady
|
21
|
+
from django_cfg.modules.django_client.core import get_openapi_service
|
22
|
+
from django_cfg.core.state.registry import get_current_config
|
23
|
+
|
24
|
+
# Get config from django-cfg
|
25
|
+
django_config = get_current_config()
|
26
|
+
if not django_config or not hasattr(django_config, 'openapi_client'):
|
27
|
+
return
|
28
|
+
|
29
|
+
config = django_config.openapi_client
|
30
|
+
|
31
|
+
if config and config.enabled:
|
32
|
+
# Initialize service with config
|
33
|
+
service = get_openapi_service()
|
34
|
+
service.set_config(config)
|
35
|
+
print(f"✅ Django Client initialized with {len(config.groups)} groups")
|
@@ -0,0 +1,56 @@
|
|
1
|
+
"""
|
2
|
+
OpenAPI Client Generator.
|
3
|
+
|
4
|
+
Universal, pure Python OpenAPI client generator.
|
5
|
+
No Django dependencies - can be used standalone or with any framework.
|
6
|
+
"""
|
7
|
+
|
8
|
+
__version__ = "1.0.0"
|
9
|
+
|
10
|
+
# Configuration
|
11
|
+
from .config import (
|
12
|
+
OpenAPIConfig,
|
13
|
+
OpenAPIGroupConfig,
|
14
|
+
DjangoOpenAPI,
|
15
|
+
OpenAPIError,
|
16
|
+
get_openapi_service,
|
17
|
+
)
|
18
|
+
|
19
|
+
# Groups
|
20
|
+
from .groups import GroupManager, GroupDetector
|
21
|
+
|
22
|
+
# Archive
|
23
|
+
from .archive import ArchiveManager
|
24
|
+
|
25
|
+
# IR Models
|
26
|
+
from .ir import (
|
27
|
+
IRContext,
|
28
|
+
IROperationObject,
|
29
|
+
IRSchemaObject,
|
30
|
+
)
|
31
|
+
|
32
|
+
# Parsers
|
33
|
+
from .parser import parse_openapi, OpenAPI30Parser, OpenAPI31Parser
|
34
|
+
|
35
|
+
# Generators
|
36
|
+
from .generator import PythonGenerator, TypeScriptGenerator
|
37
|
+
|
38
|
+
__all__ = [
|
39
|
+
"__version__",
|
40
|
+
"OpenAPIConfig",
|
41
|
+
"OpenAPIGroupConfig",
|
42
|
+
"DjangoOpenAPI",
|
43
|
+
"OpenAPIError",
|
44
|
+
"get_openapi_service",
|
45
|
+
"GroupManager",
|
46
|
+
"GroupDetector",
|
47
|
+
"ArchiveManager",
|
48
|
+
"IRContext",
|
49
|
+
"IROperationObject",
|
50
|
+
"IRSchemaObject",
|
51
|
+
"parse_openapi",
|
52
|
+
"OpenAPI30Parser",
|
53
|
+
"OpenAPI31Parser",
|
54
|
+
"PythonGenerator",
|
55
|
+
"TypeScriptGenerator",
|
56
|
+
]
|
@@ -0,0 +1,134 @@
|
|
1
|
+
"""
|
2
|
+
Simple Archive Manager.
|
3
|
+
|
4
|
+
Lightweight client archiving without complex dependencies.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import shutil
|
8
|
+
import json
|
9
|
+
from datetime import datetime
|
10
|
+
from pathlib import Path
|
11
|
+
from typing import Optional, Dict
|
12
|
+
|
13
|
+
|
14
|
+
class ArchiveManager:
|
15
|
+
"""
|
16
|
+
Simple archive manager for generated clients.
|
17
|
+
|
18
|
+
Creates timestamped copies + 'latest' symlink.
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(self, base_dir: Path):
|
22
|
+
"""
|
23
|
+
Initialize archive manager.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
base_dir: Base directory for archives
|
27
|
+
"""
|
28
|
+
self.base_dir = Path(base_dir)
|
29
|
+
self.archive_dir = self.base_dir / "archive"
|
30
|
+
self.archive_dir.mkdir(parents=True, exist_ok=True)
|
31
|
+
|
32
|
+
def archive_clients(
|
33
|
+
self,
|
34
|
+
group_name: str,
|
35
|
+
python_dir: Optional[Path] = None,
|
36
|
+
typescript_dir: Optional[Path] = None,
|
37
|
+
) -> Dict:
|
38
|
+
"""
|
39
|
+
Archive generated clients.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
group_name: Name of the group
|
43
|
+
python_dir: Python client directory
|
44
|
+
typescript_dir: TypeScript client directory
|
45
|
+
|
46
|
+
Returns:
|
47
|
+
Archive result dictionary
|
48
|
+
"""
|
49
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
50
|
+
|
51
|
+
# Create timestamped directory
|
52
|
+
archive_path = self.archive_dir / timestamp / group_name
|
53
|
+
archive_path.mkdir(parents=True, exist_ok=True)
|
54
|
+
|
55
|
+
# Copy clients
|
56
|
+
copied = {}
|
57
|
+
|
58
|
+
if python_dir and python_dir.exists():
|
59
|
+
dest = archive_path / "python"
|
60
|
+
shutil.copytree(python_dir, dest)
|
61
|
+
copied["python"] = str(dest)
|
62
|
+
|
63
|
+
if typescript_dir and typescript_dir.exists():
|
64
|
+
dest = archive_path / "typescript"
|
65
|
+
shutil.copytree(typescript_dir, dest)
|
66
|
+
copied["typescript"] = str(dest)
|
67
|
+
|
68
|
+
# Create metadata
|
69
|
+
metadata = {
|
70
|
+
"group": group_name,
|
71
|
+
"timestamp": timestamp,
|
72
|
+
"datetime": datetime.now().isoformat(),
|
73
|
+
"clients": copied,
|
74
|
+
}
|
75
|
+
|
76
|
+
metadata_file = archive_path / "metadata.json"
|
77
|
+
metadata_file.write_text(json.dumps(metadata, indent=2))
|
78
|
+
|
79
|
+
# Create/update 'latest' symlink
|
80
|
+
latest_link = self.archive_dir / "latest" / group_name
|
81
|
+
latest_link.parent.mkdir(parents=True, exist_ok=True)
|
82
|
+
|
83
|
+
if latest_link.exists() or latest_link.is_symlink():
|
84
|
+
latest_link.unlink()
|
85
|
+
|
86
|
+
try:
|
87
|
+
latest_link.symlink_to(archive_path, target_is_directory=True)
|
88
|
+
except OSError:
|
89
|
+
# Fallback: copy instead of symlink (Windows)
|
90
|
+
if latest_link.exists():
|
91
|
+
shutil.rmtree(latest_link)
|
92
|
+
shutil.copytree(archive_path, latest_link)
|
93
|
+
|
94
|
+
return {
|
95
|
+
"success": True,
|
96
|
+
"archive_path": str(archive_path),
|
97
|
+
"timestamp": timestamp,
|
98
|
+
"clients": list(copied.keys()),
|
99
|
+
}
|
100
|
+
|
101
|
+
def list_archives(self, group_name: Optional[str] = None) -> list:
|
102
|
+
"""
|
103
|
+
List available archives.
|
104
|
+
|
105
|
+
Args:
|
106
|
+
group_name: Optional group filter
|
107
|
+
|
108
|
+
Returns:
|
109
|
+
List of archive info dictionaries
|
110
|
+
"""
|
111
|
+
archives = []
|
112
|
+
|
113
|
+
for timestamp_dir in sorted(self.archive_dir.iterdir()):
|
114
|
+
if timestamp_dir.name == "latest":
|
115
|
+
continue
|
116
|
+
|
117
|
+
if not timestamp_dir.is_dir():
|
118
|
+
continue
|
119
|
+
|
120
|
+
for group_dir in timestamp_dir.iterdir():
|
121
|
+
if group_name and group_dir.name != group_name:
|
122
|
+
continue
|
123
|
+
|
124
|
+
metadata_file = group_dir / "metadata.json"
|
125
|
+
if metadata_file.exists():
|
126
|
+
metadata = json.loads(metadata_file.read_text())
|
127
|
+
archives.append(metadata)
|
128
|
+
|
129
|
+
return archives
|
130
|
+
|
131
|
+
|
132
|
+
__all__ = [
|
133
|
+
"ArchiveManager",
|
134
|
+
]
|
@@ -0,0 +1,235 @@
|
|
1
|
+
"""
|
2
|
+
Django Client CLI - Command-line interface with click.
|
3
|
+
|
4
|
+
Provides intuitive CLI for client generation.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import sys
|
8
|
+
from pathlib import Path
|
9
|
+
from typing import Optional, List
|
10
|
+
|
11
|
+
try:
|
12
|
+
import click
|
13
|
+
CLICK_AVAILABLE = True
|
14
|
+
except ImportError:
|
15
|
+
CLICK_AVAILABLE = False
|
16
|
+
click = None
|
17
|
+
|
18
|
+
try:
|
19
|
+
from rich.console import Console
|
20
|
+
from rich.table import Table
|
21
|
+
RICH_AVAILABLE = True
|
22
|
+
except ImportError:
|
23
|
+
RICH_AVAILABLE = False
|
24
|
+
Console = None
|
25
|
+
|
26
|
+
|
27
|
+
console = Console() if RICH_AVAILABLE else None
|
28
|
+
|
29
|
+
|
30
|
+
def print_message(message: str, style: str = ""):
|
31
|
+
"""Print message with optional styling."""
|
32
|
+
if console:
|
33
|
+
console.print(message, style=style)
|
34
|
+
else:
|
35
|
+
print(message)
|
36
|
+
|
37
|
+
|
38
|
+
def print_error(message: str):
|
39
|
+
"""Print error message."""
|
40
|
+
if console:
|
41
|
+
console.print(f"❌ {message}", style="bold red")
|
42
|
+
else:
|
43
|
+
print(f"ERROR: {message}")
|
44
|
+
|
45
|
+
|
46
|
+
def print_success(message: str):
|
47
|
+
"""Print success message."""
|
48
|
+
if console:
|
49
|
+
console.print(f"✅ {message}", style="bold green")
|
50
|
+
else:
|
51
|
+
print(f"SUCCESS: {message}")
|
52
|
+
|
53
|
+
|
54
|
+
def print_info(message: str):
|
55
|
+
"""Print info message."""
|
56
|
+
if console:
|
57
|
+
console.print(f"ℹ️ {message}", style="bold blue")
|
58
|
+
else:
|
59
|
+
print(f"INFO: {message}")
|
60
|
+
|
61
|
+
|
62
|
+
def print_warning(message: str):
|
63
|
+
"""Print warning message."""
|
64
|
+
if console:
|
65
|
+
console.print(f"⚠️ {message}", style="bold yellow")
|
66
|
+
else:
|
67
|
+
print(f"WARNING: {message}")
|
68
|
+
|
69
|
+
|
70
|
+
@click.group(invoke_without_command=True)
|
71
|
+
@click.option('--version', is_flag=True, help='Show version')
|
72
|
+
@click.pass_context
|
73
|
+
def cli(ctx, version):
|
74
|
+
"""
|
75
|
+
Django Client - Universal OpenAPI Client Generator.
|
76
|
+
|
77
|
+
Fast, pure Python implementation with TypeScript and Python support.
|
78
|
+
"""
|
79
|
+
if version:
|
80
|
+
print_message("Django Client v1.0.0", style="bold cyan")
|
81
|
+
ctx.exit(0)
|
82
|
+
|
83
|
+
if ctx.invoked_subcommand is None:
|
84
|
+
click.echo(ctx.get_help())
|
85
|
+
|
86
|
+
|
87
|
+
@cli.command()
|
88
|
+
@click.option('--groups', '-g', multiple=True, help='Specific groups to generate')
|
89
|
+
@click.option('--python/--no-python', default=True, help='Generate Python client')
|
90
|
+
@click.option('--typescript/--no-typescript', default=True, help='Generate TypeScript client')
|
91
|
+
@click.option('--dry-run', is_flag=True, help='Validate without generating files')
|
92
|
+
@click.option('--config', type=click.Path(exists=True), help='Path to config file')
|
93
|
+
def generate(groups, python, typescript, dry_run, config):
|
94
|
+
"""Generate API clients for configured groups."""
|
95
|
+
try:
|
96
|
+
if dry_run:
|
97
|
+
print_info("DRY RUN MODE - No files will be generated")
|
98
|
+
|
99
|
+
groups_list = list(groups) if groups else None
|
100
|
+
print_info(f"Generating clients for groups: {groups_list or 'all'}")
|
101
|
+
|
102
|
+
if python:
|
103
|
+
print_message(" → Python client", style="cyan")
|
104
|
+
if typescript:
|
105
|
+
print_message(" → TypeScript client", style="cyan")
|
106
|
+
|
107
|
+
# TODO: Actual generation logic
|
108
|
+
|
109
|
+
if not dry_run:
|
110
|
+
print_success("Client generation completed!")
|
111
|
+
else:
|
112
|
+
print_info("Dry run completed - no files generated")
|
113
|
+
|
114
|
+
except Exception as e:
|
115
|
+
print_error(f"Generation failed: {e}")
|
116
|
+
sys.exit(1)
|
117
|
+
|
118
|
+
|
119
|
+
@cli.command('list-groups')
|
120
|
+
@click.option('--config', type=click.Path(exists=True), help='Path to config file')
|
121
|
+
def list_groups(config):
|
122
|
+
"""List configured application groups."""
|
123
|
+
try:
|
124
|
+
from django_cfg.modules.django_client.core import get_openapi_service
|
125
|
+
|
126
|
+
service = get_openapi_service()
|
127
|
+
|
128
|
+
if not service.config:
|
129
|
+
print_warning("No configuration found")
|
130
|
+
return
|
131
|
+
|
132
|
+
groups = service.get_groups()
|
133
|
+
|
134
|
+
if not groups:
|
135
|
+
print_warning("No groups configured")
|
136
|
+
return
|
137
|
+
|
138
|
+
print_info(f"Configured groups ({len(groups)}):")
|
139
|
+
|
140
|
+
if console:
|
141
|
+
table = Table(title="Application Groups")
|
142
|
+
table.add_column("Group", style="cyan", no_wrap=True)
|
143
|
+
table.add_column("Title", style="green")
|
144
|
+
table.add_column("Apps", style="yellow")
|
145
|
+
|
146
|
+
for name, group_config in groups.items():
|
147
|
+
table.add_row(
|
148
|
+
name,
|
149
|
+
group_config.title,
|
150
|
+
str(len(group_config.apps))
|
151
|
+
)
|
152
|
+
|
153
|
+
console.print(table)
|
154
|
+
else:
|
155
|
+
for name, group_config in groups.items():
|
156
|
+
print(f"\n • {name}")
|
157
|
+
print(f" Title: {group_config.title}")
|
158
|
+
print(f" Apps: {len(group_config.apps)} pattern(s)")
|
159
|
+
|
160
|
+
except Exception as e:
|
161
|
+
print_error(f"Failed to list groups: {e}")
|
162
|
+
sys.exit(1)
|
163
|
+
|
164
|
+
|
165
|
+
@cli.command()
|
166
|
+
@click.option('--config', type=click.Path(exists=True), help='Path to config file')
|
167
|
+
def validate(config):
|
168
|
+
"""Validate configuration."""
|
169
|
+
try:
|
170
|
+
from django_cfg.modules.django_client.core import get_openapi_service
|
171
|
+
|
172
|
+
print_info("Validating configuration...")
|
173
|
+
|
174
|
+
service = get_openapi_service()
|
175
|
+
|
176
|
+
if not service.config:
|
177
|
+
print_error("No configuration found")
|
178
|
+
sys.exit(1)
|
179
|
+
|
180
|
+
service.validate_config()
|
181
|
+
print_success("Configuration is valid!")
|
182
|
+
|
183
|
+
except Exception as e:
|
184
|
+
print_error(f"Validation failed: {e}")
|
185
|
+
sys.exit(1)
|
186
|
+
|
187
|
+
|
188
|
+
@cli.command()
|
189
|
+
@click.option('--config', type=click.Path(exists=True), help='Path to config file')
|
190
|
+
def status(config):
|
191
|
+
"""Show current status and configuration."""
|
192
|
+
try:
|
193
|
+
from django_cfg.modules.django_client.core import get_openapi_service
|
194
|
+
|
195
|
+
service = get_openapi_service()
|
196
|
+
|
197
|
+
if not service.config:
|
198
|
+
print_warning("No configuration found")
|
199
|
+
return
|
200
|
+
|
201
|
+
status_info = service.get_status()
|
202
|
+
|
203
|
+
print_info("Django Client Status:")
|
204
|
+
print(f"\n Enabled: {status_info.get('enabled', False)}")
|
205
|
+
print(f" Groups: {status_info.get('groups', 0)}")
|
206
|
+
print(f" Output: {status_info.get('output_dir', 'N/A')}")
|
207
|
+
print(f" Python: {status_info.get('generate_python', False)}")
|
208
|
+
print(f" TypeScript: {status_info.get('generate_typescript', False)}")
|
209
|
+
|
210
|
+
if status_info.get('group_names'):
|
211
|
+
print(f"\n Configured groups:")
|
212
|
+
for name in status_info['group_names']:
|
213
|
+
print(f" • {name}")
|
214
|
+
|
215
|
+
except Exception as e:
|
216
|
+
print_error(f"Failed to get status: {e}")
|
217
|
+
sys.exit(1)
|
218
|
+
|
219
|
+
|
220
|
+
def main():
|
221
|
+
"""Main entry point."""
|
222
|
+
if not CLICK_AVAILABLE:
|
223
|
+
print("ERROR: click is required. Install with: pip install click")
|
224
|
+
sys.exit(1)
|
225
|
+
|
226
|
+
cli()
|
227
|
+
|
228
|
+
|
229
|
+
def run_cli():
|
230
|
+
"""Run CLI (alias for main)."""
|
231
|
+
main()
|
232
|
+
|
233
|
+
|
234
|
+
if __name__ == "__main__":
|
235
|
+
main()
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"""
|
2
|
+
Django Client Configuration.
|
3
|
+
|
4
|
+
Configuration models and service for OpenAPI client generation.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from .config import OpenAPIConfig
|
8
|
+
from .group import OpenAPIGroupConfig
|
9
|
+
from .service import DjangoOpenAPI, OpenAPIError, get_openapi_service, reset_service
|
10
|
+
|
11
|
+
__all__ = [
|
12
|
+
"OpenAPIConfig",
|
13
|
+
"OpenAPIGroupConfig",
|
14
|
+
"DjangoOpenAPI",
|
15
|
+
"OpenAPIError",
|
16
|
+
"get_openapi_service",
|
17
|
+
"reset_service",
|
18
|
+
]
|