aipostify 1.0.1__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.
- aipostify/__init__.py +22 -0
- aipostify/cli.py +167 -0
- aipostify/project_template/.env.example +23 -0
- aipostify/project_template/.gitattributes +2 -0
- aipostify/project_template/.gitignore +73 -0
- aipostify/project_template/app/__init__.py +1 -0
- aipostify/project_template/app/apps.py +12 -0
- aipostify/project_template/app/http/controllers/__init__.py +4 -0
- aipostify/project_template/app/http/controllers/controller.py +11 -0
- aipostify/project_template/app/http/controllers/welcome_controller.py +10 -0
- aipostify/project_template/app/models/__init__.py +3 -0
- aipostify/project_template/app/models/user.py +22 -0
- aipostify/project_template/artisan +22 -0
- aipostify/project_template/config/app.py +11 -0
- aipostify/project_template/config/database.py +21 -0
- aipostify/project_template/config/mail.py +14 -0
- aipostify/project_template/config/queue.py +7 -0
- aipostify/project_template/database/migrations/0001_initial.py +29 -0
- aipostify/project_template/database/migrations/__init__.py +1 -0
- aipostify/project_template/database/seeders/database_seeder.py +10 -0
- aipostify/project_template/database/seeders/user_seeder.py +21 -0
- aipostify/project_template/framework/__init__.py +10 -0
- aipostify/project_template/framework/apps.py +6 -0
- aipostify/project_template/framework/auto_discovery.py +46 -0
- aipostify/project_template/framework/console/__init__.py +4 -0
- aipostify/project_template/framework/console/artisan.py +213 -0
- aipostify/project_template/framework/console/command.py +59 -0
- aipostify/project_template/framework/console/commands/cache_clear.py +35 -0
- aipostify/project_template/framework/console/commands/config_cache.py +36 -0
- aipostify/project_template/framework/console/commands/db_check.py +61 -0
- aipostify/project_template/framework/console/commands/db_create.py +36 -0
- aipostify/project_template/framework/console/commands/db_seed.py +34 -0
- aipostify/project_template/framework/console/commands/db_show.py +52 -0
- aipostify/project_template/framework/console/commands/db_transfer.py +37 -0
- aipostify/project_template/framework/console/commands/key_generate.py +36 -0
- aipostify/project_template/framework/console/commands/make_auth.py +268 -0
- aipostify/project_template/framework/console/commands/make_command.py +45 -0
- aipostify/project_template/framework/console/commands/make_component.py +39 -0
- aipostify/project_template/framework/console/commands/make_controller.py +77 -0
- aipostify/project_template/framework/console/commands/make_crud.py +236 -0
- aipostify/project_template/framework/console/commands/make_job.py +42 -0
- aipostify/project_template/framework/console/commands/make_layout.py +38 -0
- aipostify/project_template/framework/console/commands/make_middleware.py +39 -0
- aipostify/project_template/framework/console/commands/make_migration.py +32 -0
- aipostify/project_template/framework/console/commands/make_model.py +57 -0
- aipostify/project_template/framework/console/commands/make_request.py +39 -0
- aipostify/project_template/framework/console/commands/make_seeder.py +42 -0
- aipostify/project_template/framework/console/commands/make_service.py +39 -0
- aipostify/project_template/framework/console/commands/make_view.py +42 -0
- aipostify/project_template/framework/console/commands/migrate.py +30 -0
- aipostify/project_template/framework/console/commands/migrate_fresh.py +48 -0
- aipostify/project_template/framework/console/commands/migrate_refresh.py +19 -0
- aipostify/project_template/framework/console/commands/migrate_rollback.py +20 -0
- aipostify/project_template/framework/console/commands/migrate_status.py +33 -0
- aipostify/project_template/framework/console/commands/ptl_format.py +146 -0
- aipostify/project_template/framework/console/commands/ptl_install_vscode.py +106 -0
- aipostify/project_template/framework/console/commands/pypi_publish.py +93 -0
- aipostify/project_template/framework/console/commands/queue_work.py +38 -0
- aipostify/project_template/framework/console/commands/route_list.py +38 -0
- aipostify/project_template/framework/console/commands/schedule_run.py +38 -0
- aipostify/project_template/framework/console/commands/serve.py +39 -0
- aipostify/project_template/framework/console/commands/storage_link.py +41 -0
- aipostify/project_template/framework/console/commands/test_command.py +20 -0
- aipostify/project_template/framework/console/commands/tinker.py +48 -0
- aipostify/project_template/framework/console/commands/view_cache.py +33 -0
- aipostify/project_template/framework/console/commands/view_check.py +26 -0
- aipostify/project_template/framework/console/commands/view_clear.py +16 -0
- aipostify/project_template/framework/database/__init__.py +13 -0
- aipostify/project_template/framework/database/connector.py +90 -0
- aipostify/project_template/framework/database/fields.py +51 -0
- aipostify/project_template/framework/database/model.py +93 -0
- aipostify/project_template/framework/database/seeder.py +20 -0
- aipostify/project_template/framework/http/__init__.py +17 -0
- aipostify/project_template/framework/http/controller.py +39 -0
- aipostify/project_template/framework/http/middleware.py +50 -0
- aipostify/project_template/framework/http/request.py +61 -0
- aipostify/project_template/framework/http/response.py +76 -0
- aipostify/project_template/framework/http/validator.py +253 -0
- aipostify/project_template/framework/kernel.py +71 -0
- aipostify/project_template/framework/queue/__init__.py +3 -0
- aipostify/project_template/framework/queue/queue.py +111 -0
- aipostify/project_template/framework/routing/__init__.py +4 -0
- aipostify/project_template/framework/routing/resolver.py +149 -0
- aipostify/project_template/framework/routing/route.py +172 -0
- aipostify/project_template/framework/routing/templatetags/__init__.py +1 -0
- aipostify/project_template/framework/routing/templatetags/aipostify.py +69 -0
- aipostify/project_template/framework/routing/urls.py +45 -0
- aipostify/project_template/framework/schedule/__init__.py +3 -0
- aipostify/project_template/framework/schedule/schedule.py +101 -0
- aipostify/project_template/framework/settings.py +139 -0
- aipostify/project_template/framework/stubs/command.stub +8 -0
- aipostify/project_template/framework/stubs/component.stub +4 -0
- aipostify/project_template/framework/stubs/controller.resource.stub +40 -0
- aipostify/project_template/framework/stubs/controller.stub +5 -0
- aipostify/project_template/framework/stubs/job.stub +12 -0
- aipostify/project_template/framework/stubs/layout.stub +15 -0
- aipostify/project_template/framework/stubs/middleware.stub +7 -0
- aipostify/project_template/framework/stubs/model.stub +10 -0
- aipostify/project_template/framework/stubs/request.stub +12 -0
- aipostify/project_template/framework/stubs/seeder.stub +6 -0
- aipostify/project_template/framework/stubs/service.stub +5 -0
- aipostify/project_template/framework/stubs/view.stub +10 -0
- aipostify/project_template/framework/view/__init__.py +28 -0
- aipostify/project_template/framework/view/compiler.py +738 -0
- aipostify/project_template/framework/view/engine.py +403 -0
- aipostify/project_template/framework/view/exceptions.py +35 -0
- aipostify/project_template/framework/view/filters.py +145 -0
- aipostify/project_template/framework/view/formatter.py +222 -0
- aipostify/project_template/framework/view/helpers.py +114 -0
- aipostify/project_template/framework/view/sandbox.py +136 -0
- aipostify/project_template/public/css/app.css +234 -0
- aipostify/project_template/public/js/app.js +19 -0
- aipostify/project_template/pytest.ini +3 -0
- aipostify/project_template/requirements.txt +6 -0
- aipostify/project_template/resources/lang/en.json +14 -0
- aipostify/project_template/resources/lang/gu.json +14 -0
- aipostify/project_template/resources/lang/hi.json +14 -0
- aipostify/project_template/resources/views/components/alert.ptl +8 -0
- aipostify/project_template/resources/views/errors/404.html +16 -0
- aipostify/project_template/resources/views/errors/500.html +16 -0
- aipostify/project_template/resources/views/layouts/app.ptl +57 -0
- aipostify/project_template/resources/views/welcome.ptl +708 -0
- aipostify/project_template/routes/api.py +9 -0
- aipostify/project_template/routes/console.py +10 -0
- aipostify/project_template/routes/web.py +8 -0
- aipostify/project_template/storage/app/public/.gitkeep +1 -0
- aipostify/project_template/storage/framework/cache/.gitkeep +1 -0
- aipostify/project_template/storage/framework/sessions/.gitkeep +1 -0
- aipostify/project_template/storage/framework/views/521f046fdcb33fd1c337ff0e276264052596e53a7f71bde9b60b28eb339ca64f.py +43 -0
- aipostify/project_template/storage/logs/.gitkeep +1 -0
- aipostify/project_template/tools/vscode-postify/README.md +46 -0
- aipostify/project_template/tools/vscode-postify/extension.js +1171 -0
- aipostify/project_template/tools/vscode-postify/icons/icon-theme.json +13 -0
- aipostify/project_template/tools/vscode-postify/icons/ptl.svg +18 -0
- aipostify/project_template/tools/vscode-postify/language-configuration.json +26 -0
- aipostify/project_template/tools/vscode-postify/package.json +78 -0
- aipostify/project_template/tools/vscode-postify/snippets/postify.code-snippets +314 -0
- aipostify/project_template/tools/vscode-postify/syntaxes/postify.tmLanguage.json +54 -0
- aipostify-1.0.1.dist-info/METADATA +162 -0
- aipostify-1.0.1.dist-info/RECORD +233 -0
- aipostify-1.0.1.dist-info/WHEEL +5 -0
- aipostify-1.0.1.dist-info/entry_points.txt +4 -0
- aipostify-1.0.1.dist-info/licenses/LICENSE +21 -0
- aipostify-1.0.1.dist-info/top_level.txt +2 -0
- framework/__init__.py +10 -0
- framework/apps.py +6 -0
- framework/auto_discovery.py +46 -0
- framework/console/__init__.py +4 -0
- framework/console/artisan.py +213 -0
- framework/console/command.py +59 -0
- framework/console/commands/cache_clear.py +35 -0
- framework/console/commands/config_cache.py +36 -0
- framework/console/commands/db_check.py +61 -0
- framework/console/commands/db_create.py +36 -0
- framework/console/commands/db_seed.py +34 -0
- framework/console/commands/db_show.py +52 -0
- framework/console/commands/db_transfer.py +37 -0
- framework/console/commands/key_generate.py +36 -0
- framework/console/commands/make_auth.py +268 -0
- framework/console/commands/make_command.py +45 -0
- framework/console/commands/make_component.py +39 -0
- framework/console/commands/make_controller.py +77 -0
- framework/console/commands/make_crud.py +236 -0
- framework/console/commands/make_job.py +42 -0
- framework/console/commands/make_layout.py +38 -0
- framework/console/commands/make_middleware.py +39 -0
- framework/console/commands/make_migration.py +32 -0
- framework/console/commands/make_model.py +57 -0
- framework/console/commands/make_request.py +39 -0
- framework/console/commands/make_seeder.py +42 -0
- framework/console/commands/make_service.py +39 -0
- framework/console/commands/make_view.py +42 -0
- framework/console/commands/migrate.py +30 -0
- framework/console/commands/migrate_fresh.py +48 -0
- framework/console/commands/migrate_refresh.py +19 -0
- framework/console/commands/migrate_rollback.py +20 -0
- framework/console/commands/migrate_status.py +33 -0
- framework/console/commands/ptl_format.py +146 -0
- framework/console/commands/ptl_install_vscode.py +106 -0
- framework/console/commands/pypi_publish.py +93 -0
- framework/console/commands/queue_work.py +38 -0
- framework/console/commands/route_list.py +38 -0
- framework/console/commands/schedule_run.py +38 -0
- framework/console/commands/serve.py +39 -0
- framework/console/commands/storage_link.py +41 -0
- framework/console/commands/test_command.py +20 -0
- framework/console/commands/tinker.py +48 -0
- framework/console/commands/view_cache.py +33 -0
- framework/console/commands/view_check.py +26 -0
- framework/console/commands/view_clear.py +16 -0
- framework/database/__init__.py +13 -0
- framework/database/connector.py +90 -0
- framework/database/fields.py +51 -0
- framework/database/model.py +93 -0
- framework/database/seeder.py +20 -0
- framework/http/__init__.py +17 -0
- framework/http/controller.py +39 -0
- framework/http/middleware.py +50 -0
- framework/http/request.py +61 -0
- framework/http/response.py +76 -0
- framework/http/validator.py +253 -0
- framework/kernel.py +71 -0
- framework/queue/__init__.py +3 -0
- framework/queue/queue.py +111 -0
- framework/routing/__init__.py +4 -0
- framework/routing/resolver.py +149 -0
- framework/routing/route.py +172 -0
- framework/routing/templatetags/__init__.py +1 -0
- framework/routing/templatetags/aipostify.py +69 -0
- framework/routing/urls.py +45 -0
- framework/schedule/__init__.py +3 -0
- framework/schedule/schedule.py +101 -0
- framework/settings.py +139 -0
- framework/stubs/command.stub +8 -0
- framework/stubs/component.stub +4 -0
- framework/stubs/controller.resource.stub +40 -0
- framework/stubs/controller.stub +5 -0
- framework/stubs/job.stub +12 -0
- framework/stubs/layout.stub +15 -0
- framework/stubs/middleware.stub +7 -0
- framework/stubs/model.stub +10 -0
- framework/stubs/request.stub +12 -0
- framework/stubs/seeder.stub +6 -0
- framework/stubs/service.stub +5 -0
- framework/stubs/view.stub +10 -0
- framework/view/__init__.py +28 -0
- framework/view/compiler.py +738 -0
- framework/view/engine.py +403 -0
- framework/view/exceptions.py +35 -0
- framework/view/filters.py +145 -0
- framework/view/formatter.py +222 -0
- framework/view/helpers.py +114 -0
- framework/view/sandbox.py +136 -0
aipostify/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
AIPostify
|
|
4
|
+
Laravel-Style Python MVC Framework with PTL (Postify Template Language).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__title__ = "aipostify"
|
|
8
|
+
__version__ = "1.0.1"
|
|
9
|
+
__author__ = "AIPostify Contributors"
|
|
10
|
+
__license__ = "MIT"
|
|
11
|
+
__description__ = "Laravel-Style Python MVC Starter Framework with PTL Template Engine"
|
|
12
|
+
|
|
13
|
+
from framework.kernel import bootstrap, get_wsgi_application, get_asgi_application
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"bootstrap",
|
|
17
|
+
"get_wsgi_application",
|
|
18
|
+
"get_asgi_application",
|
|
19
|
+
"__version__",
|
|
20
|
+
"__author__",
|
|
21
|
+
"__license__",
|
|
22
|
+
]
|
aipostify/cli.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
AIPostify CLI Entry Point
|
|
4
|
+
Provides global 'aipostify' and 'artisan' command-line tools.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import os
|
|
9
|
+
import shutil
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
BANNER = r"""
|
|
14
|
+
___ ____ ___ __ _ ____
|
|
15
|
+
/ | / _/ / _ \___ ___ / /_ (_)/ __/__ __
|
|
16
|
+
/ /| | / / / ___/ _ \ (_-< / __// // _/ / / / /
|
|
17
|
+
/_/ |_|_/___//_/ \___//___//_/ /_//_/ \__, /
|
|
18
|
+
/____/
|
|
19
|
+
Laravel-Style Python MVC Framework • v1.0.1
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _find_project_root():
|
|
24
|
+
"""Look up directory tree for an artisan file to identify AIPostify project root."""
|
|
25
|
+
current = Path.cwd().resolve()
|
|
26
|
+
while current != current.parent:
|
|
27
|
+
if (current / "artisan").exists() and (current / "framework").exists():
|
|
28
|
+
return current
|
|
29
|
+
current = current.parent
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _create_new_project(project_name: str):
|
|
34
|
+
"""Scaffold a brand new AIPostify project in the specified directory."""
|
|
35
|
+
target_dir = Path.cwd() / project_name
|
|
36
|
+
if target_dir.exists() and any(target_dir.iterdir()):
|
|
37
|
+
print(f"\033[91m[Error]\033[0m Directory [{project_name}] already exists and is not empty.")
|
|
38
|
+
return 1
|
|
39
|
+
|
|
40
|
+
print(f"\033[95m{BANNER}\033[0m")
|
|
41
|
+
print(f"\033[96mCreating a new AIPostify application in:\033[0m {target_dir}\n")
|
|
42
|
+
|
|
43
|
+
# Locate package template / source directory
|
|
44
|
+
cli_dir = Path(__file__).resolve().parent
|
|
45
|
+
template_dir = cli_dir / "project_template"
|
|
46
|
+
if not template_dir.exists():
|
|
47
|
+
# Fall back to repository root during development
|
|
48
|
+
template_dir = cli_dir.parent
|
|
49
|
+
|
|
50
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
51
|
+
|
|
52
|
+
# 1. Copy complete project structure from template
|
|
53
|
+
if template_dir.exists():
|
|
54
|
+
shutil.copytree(
|
|
55
|
+
template_dir,
|
|
56
|
+
target_dir,
|
|
57
|
+
dirs_exist_ok=True,
|
|
58
|
+
ignore=shutil.ignore_patterns(
|
|
59
|
+
"__pycache__",
|
|
60
|
+
"*.pyc",
|
|
61
|
+
"*.sqlite",
|
|
62
|
+
"*.sqlite3",
|
|
63
|
+
"*.log",
|
|
64
|
+
".tmp*",
|
|
65
|
+
"dist",
|
|
66
|
+
"build",
|
|
67
|
+
"*.egg-info",
|
|
68
|
+
".pytest_cache",
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
print(" \033[92m+\033[0m Created application core and directories (app, config, database, framework, resources, routes, storage, tools)")
|
|
72
|
+
|
|
73
|
+
# 2. Create .env from .env.example
|
|
74
|
+
env_example = target_dir / ".env.example"
|
|
75
|
+
env_file = target_dir / ".env"
|
|
76
|
+
if env_example.exists() and not env_file.exists():
|
|
77
|
+
shutil.copy2(env_example, env_file)
|
|
78
|
+
print(" \033[92m+\033[0m Generated .env configuration")
|
|
79
|
+
|
|
80
|
+
# 3. Ensure all storage subdirectories exist with .gitkeep
|
|
81
|
+
storage_dirs = [
|
|
82
|
+
"logs",
|
|
83
|
+
"app/public",
|
|
84
|
+
"framework/cache",
|
|
85
|
+
"framework/sessions",
|
|
86
|
+
"framework/views",
|
|
87
|
+
]
|
|
88
|
+
for sub in storage_dirs:
|
|
89
|
+
sub_path = target_dir / "storage" / sub
|
|
90
|
+
sub_path.mkdir(parents=True, exist_ok=True)
|
|
91
|
+
gitkeep = sub_path / ".gitkeep"
|
|
92
|
+
if not gitkeep.exists():
|
|
93
|
+
gitkeep.touch()
|
|
94
|
+
|
|
95
|
+
print("\n\033[92m[Success] AIPostify application created successfully!\033[0m")
|
|
96
|
+
print("\n\033[93mNext Steps:\033[0m")
|
|
97
|
+
print(f" cd {project_name}")
|
|
98
|
+
print(" python artisan key:generate")
|
|
99
|
+
print(" python artisan migrate")
|
|
100
|
+
print(" python artisan serve\n")
|
|
101
|
+
return 0
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def main():
|
|
105
|
+
"""Main CLI handler for 'aipostify' command."""
|
|
106
|
+
args = sys.argv[1:]
|
|
107
|
+
|
|
108
|
+
if not args or args[0] in ["-h", "--help", "help"]:
|
|
109
|
+
print(f"\033[95m{BANNER}\033[0m")
|
|
110
|
+
print("Usage:")
|
|
111
|
+
print(" aipostify new <project_name> Create a new AIPostify project")
|
|
112
|
+
print(" aipostify --version, -v Display AIPostify version")
|
|
113
|
+
print(" aipostify <command> Run artisan command in current project")
|
|
114
|
+
print("\nExamples:")
|
|
115
|
+
print(" aipostify new myapp")
|
|
116
|
+
print(" aipostify serve")
|
|
117
|
+
print(" aipostify route:list")
|
|
118
|
+
return 0
|
|
119
|
+
|
|
120
|
+
if args[0] in ["-v", "--version", "version"]:
|
|
121
|
+
from . import __version__
|
|
122
|
+
print(f"AIPostify Framework v{__version__}")
|
|
123
|
+
return 0
|
|
124
|
+
|
|
125
|
+
if args[0] == "new":
|
|
126
|
+
if len(args) < 2:
|
|
127
|
+
print("\033[91m[Error]\033[0m Please provide a project name:")
|
|
128
|
+
print(" aipostify new <project_name>")
|
|
129
|
+
return 1
|
|
130
|
+
return _create_new_project(args[1])
|
|
131
|
+
|
|
132
|
+
# Check if we are inside an AIPostify project
|
|
133
|
+
project_root = _find_project_root()
|
|
134
|
+
if project_root:
|
|
135
|
+
artisan_path = project_root / "artisan"
|
|
136
|
+
cmd = [sys.executable, str(artisan_path)] + args
|
|
137
|
+
import subprocess
|
|
138
|
+
return subprocess.run(cmd).returncode
|
|
139
|
+
else:
|
|
140
|
+
print(f"\033[91m[Error]\033[0m Could not find an AIPostify project with an 'artisan' file.")
|
|
141
|
+
print("Run \033[96maipostify new <project_name>\033[0m to create a new application.")
|
|
142
|
+
return 1
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def artisan_main():
|
|
146
|
+
"""Entry point for standalone 'artisan' command."""
|
|
147
|
+
project_root = _find_project_root()
|
|
148
|
+
if not project_root:
|
|
149
|
+
# Fall back to current working directory
|
|
150
|
+
project_root = Path.cwd().resolve()
|
|
151
|
+
|
|
152
|
+
if str(project_root) not in sys.path:
|
|
153
|
+
sys.path.insert(0, str(project_root))
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
from framework.kernel import bootstrap
|
|
157
|
+
bootstrap(project_root)
|
|
158
|
+
from framework.console import Artisan
|
|
159
|
+
exit_code = Artisan.handle(sys.argv[1:])
|
|
160
|
+
return exit_code or 0
|
|
161
|
+
except Exception as e:
|
|
162
|
+
print(f"\033[91m[Artisan Error]\033[0m {e}")
|
|
163
|
+
return 1
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
sys.exit(main())
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
APP_NAME=aipostify
|
|
2
|
+
APP_ENV=local
|
|
3
|
+
APP_DEBUG=true
|
|
4
|
+
APP_KEY=
|
|
5
|
+
APP_URL=http://127.0.0.1:8000
|
|
6
|
+
APP_LOCALE=en
|
|
7
|
+
|
|
8
|
+
# Database Connection: sqlite | mysql
|
|
9
|
+
DB_CONNECTION=sqlite
|
|
10
|
+
|
|
11
|
+
# --- SQLite (default) ---
|
|
12
|
+
DB_SQLITE_PATH=database/database.sqlite
|
|
13
|
+
|
|
14
|
+
# --- MySQL (Set DB_CONNECTION=mysql to use) ---
|
|
15
|
+
DB_HOST=127.0.0.1
|
|
16
|
+
DB_PORT=3306
|
|
17
|
+
DB_DATABASE=aipostify
|
|
18
|
+
DB_USERNAME=root
|
|
19
|
+
DB_PASSWORD=
|
|
20
|
+
|
|
21
|
+
QUEUE_CONNECTION=database
|
|
22
|
+
CACHE_DRIVER=file
|
|
23
|
+
SESSION_DRIVER=file
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# AIPostify Git Ignore
|
|
2
|
+
|
|
3
|
+
# Environment & Secrets (Crucial: Never commit .env)
|
|
4
|
+
.env
|
|
5
|
+
.env.backup
|
|
6
|
+
.env.production
|
|
7
|
+
|
|
8
|
+
# Python & Bytecode
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
*$py.class
|
|
12
|
+
*.so
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
|
|
30
|
+
# Virtual Environments
|
|
31
|
+
venv/
|
|
32
|
+
.venv/
|
|
33
|
+
env/
|
|
34
|
+
ENV/
|
|
35
|
+
env.bak/
|
|
36
|
+
venv.bak/
|
|
37
|
+
|
|
38
|
+
# Databases (Crucial: Keep local SQLite and transfer dumps out of git)
|
|
39
|
+
*.sqlite
|
|
40
|
+
*.sqlite3
|
|
41
|
+
*.db
|
|
42
|
+
database/*.sqlite
|
|
43
|
+
database/*.sqlite3
|
|
44
|
+
*.sql
|
|
45
|
+
storage/app/db_transfer_dump.json
|
|
46
|
+
|
|
47
|
+
# Storage Logs, Sessions, and Caches
|
|
48
|
+
storage/logs/*.log
|
|
49
|
+
storage/framework/cache/*
|
|
50
|
+
storage/framework/sessions/*
|
|
51
|
+
!storage/framework/cache/.gitkeep
|
|
52
|
+
!storage/framework/sessions/.gitkeep
|
|
53
|
+
!storage/logs/.gitkeep
|
|
54
|
+
!storage/app/public/.gitkeep
|
|
55
|
+
|
|
56
|
+
# Public Storage Symlink
|
|
57
|
+
public/storage
|
|
58
|
+
|
|
59
|
+
# Testing & Coverage
|
|
60
|
+
.pytest_cache/
|
|
61
|
+
.coverage
|
|
62
|
+
htmlcov/
|
|
63
|
+
.tox/
|
|
64
|
+
.nox/
|
|
65
|
+
|
|
66
|
+
# IDE & Editor specific
|
|
67
|
+
.idea/
|
|
68
|
+
.vscode/
|
|
69
|
+
*.swp
|
|
70
|
+
*.swo
|
|
71
|
+
*~
|
|
72
|
+
.DS_Store
|
|
73
|
+
Thumbs.db
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
default_app_config = "app.apps.UserAppConfig"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from django.apps import AppConfig
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
class UserAppConfig(AppConfig):
|
|
5
|
+
default_auto_field = "django.db.models.BigAutoField"
|
|
6
|
+
name = "app"
|
|
7
|
+
verbose_name = "Application"
|
|
8
|
+
|
|
9
|
+
def ready(self):
|
|
10
|
+
from framework.auto_discovery import discover_models
|
|
11
|
+
from django.conf import settings
|
|
12
|
+
discover_models(settings.BASE_DIR)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
User Model
|
|
3
|
+
Default Laravel-style User Model
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from framework.database.model import Model
|
|
7
|
+
from framework.database.fields import String, Email, DateTime
|
|
8
|
+
|
|
9
|
+
class User(Model):
|
|
10
|
+
name = String(max_length=255)
|
|
11
|
+
email = Email(unique=True)
|
|
12
|
+
password = String(max_length=255)
|
|
13
|
+
email_verified_at = DateTime(null=True, blank=True)
|
|
14
|
+
remember_token = String(max_length=100, null=True, blank=True)
|
|
15
|
+
created_at = DateTime(auto_now_add=True)
|
|
16
|
+
updated_at = DateTime(auto_now=True)
|
|
17
|
+
|
|
18
|
+
class Meta:
|
|
19
|
+
db_table = "users"
|
|
20
|
+
|
|
21
|
+
def __str__(self):
|
|
22
|
+
return self.name or self.email or f"User #{self.id}"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
AIPostify - Laravel-style Python MVC Starter Framework CLI
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
# Ensure project root is in python path
|
|
11
|
+
ROOT_DIR = Path(__file__).resolve().parent
|
|
12
|
+
if str(ROOT_DIR) not in sys.path:
|
|
13
|
+
sys.path.insert(0, str(ROOT_DIR))
|
|
14
|
+
|
|
15
|
+
from framework.kernel import bootstrap
|
|
16
|
+
bootstrap(ROOT_DIR)
|
|
17
|
+
|
|
18
|
+
from framework.console import Artisan
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
exit_code = Artisan.handle(sys.argv[1:])
|
|
22
|
+
sys.exit(exit_code or 0)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Application Configuration
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
APP_NAME = os.getenv("APP_NAME", "AIPostify")
|
|
8
|
+
APP_ENV = os.getenv("APP_ENV", "local")
|
|
9
|
+
APP_DEBUG = os.getenv("APP_DEBUG", "true").lower() in ("true", "1", "yes")
|
|
10
|
+
APP_URL = os.getenv("APP_URL", "http://127.0.0.1:8000")
|
|
11
|
+
APP_LOCALE = os.getenv("APP_LOCALE", "en")
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database Configuration
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
DB_CONNECTION = os.getenv("DB_CONNECTION", "sqlite")
|
|
8
|
+
|
|
9
|
+
DATABASES = {
|
|
10
|
+
"sqlite": {
|
|
11
|
+
"database": os.getenv("DB_DATABASE", "database/database.sqlite"),
|
|
12
|
+
},
|
|
13
|
+
"mysql": {
|
|
14
|
+
"host": os.getenv("DB_HOST", "127.0.0.1"),
|
|
15
|
+
"port": int(os.getenv("DB_PORT", "3306")),
|
|
16
|
+
"database": os.getenv("DB_DATABASE", "aipostify"),
|
|
17
|
+
"username": os.getenv("DB_USERNAME", "root"),
|
|
18
|
+
"password": os.getenv("DB_PASSWORD", ""),
|
|
19
|
+
"charset": "utf8mb4",
|
|
20
|
+
},
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Mail Configuration
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
MAIL_MAILER = os.getenv("MAIL_MAILER", "smtp")
|
|
8
|
+
MAIL_HOST = os.getenv("MAIL_HOST", "127.0.0.1")
|
|
9
|
+
MAIL_PORT = int(os.getenv("MAIL_PORT", "1025"))
|
|
10
|
+
MAIL_USERNAME = os.getenv("MAIL_USERNAME", "")
|
|
11
|
+
MAIL_PASSWORD = os.getenv("MAIL_PASSWORD", "")
|
|
12
|
+
MAIL_ENCRYPTION = os.getenv("MAIL_ENCRYPTION", "tls")
|
|
13
|
+
MAIL_FROM_ADDRESS = os.getenv("MAIL_FROM_ADDRESS", "hello@aipostify.test")
|
|
14
|
+
MAIL_FROM_NAME = os.getenv("APP_NAME", "AIPostify")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Generated for default Laravel database schema
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
initial = True
|
|
9
|
+
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.CreateModel(
|
|
14
|
+
name='User',
|
|
15
|
+
fields=[
|
|
16
|
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
17
|
+
('name', models.CharField(max_length=255)),
|
|
18
|
+
('email', models.EmailField(max_length=254, unique=True)),
|
|
19
|
+
('password', models.CharField(max_length=255)),
|
|
20
|
+
('email_verified_at', models.DateTimeField(blank=True, null=True)),
|
|
21
|
+
('remember_token', models.CharField(blank=True, max_length=100, null=True)),
|
|
22
|
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
23
|
+
('updated_at', models.DateTimeField(auto_now=True)),
|
|
24
|
+
],
|
|
25
|
+
options={
|
|
26
|
+
'db_table': 'users',
|
|
27
|
+
},
|
|
28
|
+
),
|
|
29
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Database Migrations
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
User Seeder
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from framework.database import Seeder
|
|
7
|
+
from django.contrib.auth import get_user_model
|
|
8
|
+
|
|
9
|
+
class UserSeeder(Seeder):
|
|
10
|
+
def run(self):
|
|
11
|
+
env = os.getenv("APP_ENV", "local").lower()
|
|
12
|
+
if env in ("production", "prod"):
|
|
13
|
+
print("Skipping default demo/admin user creation in production environment.")
|
|
14
|
+
return
|
|
15
|
+
|
|
16
|
+
User = get_user_model()
|
|
17
|
+
if not User.objects.filter(username="admin").exists():
|
|
18
|
+
User.objects.create_superuser("admin", "admin@aipostify.test", "admin123")
|
|
19
|
+
|
|
20
|
+
if not User.objects.filter(username="demo").exists():
|
|
21
|
+
User.objects.create_user("demo", "demo@aipostify.test", "demo123")
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
AIPostify Framework Core
|
|
4
|
+
Laravel-Style Python MVC Framework with PTL Template Engine.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .kernel import bootstrap, get_wsgi_application, get_asgi_application
|
|
8
|
+
|
|
9
|
+
__version__ = "1.0.0"
|
|
10
|
+
__all__ = ["bootstrap", "get_wsgi_application", "get_asgi_application", "__version__"]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AIPostify Auto-Discovery Engine
|
|
3
|
+
Discovers Models, Controllers, Commands, Seeders, and Middleware without manual registration
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import importlib
|
|
9
|
+
import pkgutil
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
def discover_models(base_dir: Path):
|
|
13
|
+
"""Import all model modules in app/models to register them with Django ORM."""
|
|
14
|
+
models_dir = base_dir / "app" / "models"
|
|
15
|
+
if not models_dir.exists():
|
|
16
|
+
return
|
|
17
|
+
|
|
18
|
+
for _, module_name, _ in pkgutil.iter_modules([str(models_dir)]):
|
|
19
|
+
if module_name.startswith("__"):
|
|
20
|
+
continue
|
|
21
|
+
try:
|
|
22
|
+
importlib.import_module(f"app.models.{module_name}")
|
|
23
|
+
except Exception as e:
|
|
24
|
+
# Silently catch or log during initial discovery
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
def discover_commands(base_dir: Path) -> dict:
|
|
28
|
+
"""Discover user custom commands in app/console/commands."""
|
|
29
|
+
commands_dir = base_dir / "app" / "console" / "commands"
|
|
30
|
+
commands = {}
|
|
31
|
+
if not commands_dir.exists():
|
|
32
|
+
return commands
|
|
33
|
+
|
|
34
|
+
for _, module_name, _ in pkgutil.iter_modules([str(commands_dir)]):
|
|
35
|
+
if module_name.startswith("__"):
|
|
36
|
+
continue
|
|
37
|
+
try:
|
|
38
|
+
mod = importlib.import_module(f"app.console.commands.{module_name}")
|
|
39
|
+
for attr_name in dir(mod):
|
|
40
|
+
attr = getattr(mod, attr_name)
|
|
41
|
+
if isinstance(attr, type) and hasattr(attr, "signature") and attr.signature:
|
|
42
|
+
commands[attr.signature] = attr
|
|
43
|
+
except Exception:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
return commands
|