archiforge 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
archiforge/__init__.py ADDED
File without changes
archiforge/cli/main.py ADDED
@@ -0,0 +1,102 @@
1
+ import click
2
+ import os
3
+ import subprocess
4
+ import time
5
+ from archiforge.core.engine import ForgeEngine
6
+
7
+ @click.group()
8
+ def cli():
9
+ """Archiforge: أداة بناء المشاريع الذكية المتعددة اللغات 🛠️"""
10
+ pass
11
+
12
+ @cli.command()
13
+ @click.option('--name', prompt='Project Name', help='اسم المشروع الجديد')
14
+ @click.option('--author', prompt='Author Name', help='اسم المبرمج')
15
+ @click.option('--description', prompt='Description', help='وصف مختصر للمشروع')
16
+ @click.option('--lang', default='python', help='اللغة المستخدمة')
17
+ @click.option('--git-init', is_flag=True, help='تهيئة مستودع Git تلقائياً')
18
+ @click.option('--include-tests', prompt='Include tests directory?', is_flag=True, default=False)
19
+ @click.option('--with-db', prompt='Include Database (SQLAlchemy)?', is_flag=True, default=False)
20
+
21
+ @click.option('--code', is_flag=True, help='Open the project in VS Code after forging')
22
+ def create(name, author, description, lang, git_init, include_tests, with_db, code):
23
+
24
+ """إنشاء مشروع جديد مع شريط تقدم وتفاعل ذكي"""
25
+
26
+ base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
27
+ template_path = os.path.join(base_dir, "blueprints", lang)
28
+ output_path = os.path.join(os.getcwd(), name)
29
+
30
+ if not os.path.exists(template_path):
31
+ click.secho(f"❌ Error: Template '{lang}' not found!", fg="red", bold=True)
32
+ return
33
+
34
+ if os.path.exists(output_path):
35
+
36
+ if not click.confirm(click.style(f"⚠️ The directory '{name}' already exists. Overwrite?", fg="yellow")):
37
+ click.echo("❌ Operation cancelled.")
38
+ return
39
+ if code:
40
+ click.echo(click.style("🖥️ Opening VS Code...", fg="cyan"))
41
+ try:
42
+ # أمر 'code .' يفتح المجلد الحالي في VS Code
43
+ subprocess.run(['code', output_path], shell=True)
44
+ except Exception as e:
45
+ click.secho(f"⚠️ Could not open VS Code: {e}", fg="yellow")
46
+ context = {
47
+ "project_name": name,
48
+ "author": author,
49
+ "description": description,
50
+ "include_tests": include_tests
51
+ }
52
+
53
+ try:
54
+ engine = ForgeEngine(template_path, output_path, context)
55
+
56
+ # --- شريط التحميل الجمالي ---
57
+ click.echo(click.style(f"\n🚀 Starting the forge for '{name}'...", fg="magenta", bold=True))
58
+
59
+ with click.progressbar(length=100, label='⚒️ Forging project structure') as bar:
60
+ # محاكاة خطوات العمل لجعل الشريط يبدو واقعياً
61
+ time.sleep(0.3)
62
+ bar.update(20)
63
+
64
+ engine.forge() # العملية الحقيقية تحدث هنا
65
+
66
+ time.sleep(0.3)
67
+ bar.update(80)
68
+ # ---------------------------
69
+
70
+ if git_init:
71
+ click.echo(click.style("⚓ Integrating Git repository...", fg="blue"))
72
+ os.chdir(output_path)
73
+ subprocess.run(['git', 'init'], check=True, capture_output=True)
74
+ subprocess.run(['git', 'add', '.'], check=True)
75
+ subprocess.run(['git', 'commit', '-m', 'Initial commit by Archiforge'], check=True, capture_output=True)
76
+ click.secho("✅ Git integration complete!", fg="green")
77
+
78
+ click.echo(click.style(f"\n✨ Project '{name}' is ready at: ", fg="green") + click.style(output_path, underline=True))
79
+
80
+ except Exception as e:
81
+ click.secho(f"💥 An unexpected error occurred: {e}", fg="red", bold=True)
82
+
83
+ @cli.command()
84
+ def list():
85
+ """عرض كافة القوالب المتاحة"""
86
+ current_dir = os.path.dirname(os.path.abspath(__file__))
87
+ base_dir = os.path.dirname(current_dir) # سيعود لمجلد archiforge داخل src
88
+ blueprints_path = os.path.join(base_dir, "blueprints")
89
+
90
+ if not os.path.exists(blueprints_path):
91
+ click.secho("📂 No blueprints directory found.", fg="yellow")
92
+ return
93
+
94
+ blueprints = [d for d in os.listdir(blueprints_path)
95
+ if os.path.isdir(os.path.join(blueprints_path, d))]
96
+
97
+ click.secho("📂 Available Blueprints in Archiforge:", fg="cyan", bold=True)
98
+ for bp in blueprints:
99
+ click.echo(f" - {bp}")
100
+
101
+ if __name__ == "__main__":
102
+ cli()
@@ -0,0 +1,81 @@
1
+ import os
2
+ import yaml
3
+ import subprocess
4
+ from jinja2 import Template
5
+
6
+ class ForgeEngine:
7
+ def __init__(self, template_path, output_path, context):
8
+ """
9
+ template_path: مسار مجلد القالب
10
+ output_path: مسار المشروع الجديد المراد إنشاؤه
11
+ context: البيانات (الاسم، المؤلف، الوصف)
12
+ """
13
+ self.template_path = template_path
14
+ self.output_path = output_path
15
+ self.context = context
16
+
17
+ def load_structure(self):
18
+ """تحميل ومعالجة ملف structure.yaml كقالب Jinja2 أولاً"""
19
+ yaml_file = os.path.join(self.template_path, "structure.yaml")
20
+ if not os.path.exists(yaml_file):
21
+ raise FileNotFoundError(f"Missing structure.yaml in {self.template_path}")
22
+
23
+ with open(yaml_file, 'r', encoding='utf-8') as f:
24
+ raw_yaml = f.read()
25
+
26
+ # السحر هنا: معالجة الـ YAML نفسه كقالب قبل تحويله لبيانات
27
+ rendered_yaml = Template(raw_yaml).render(self.context)
28
+ return yaml.safe_load(rendered_yaml)
29
+
30
+ def forge(self):
31
+ """الوظيفة الأساسية لبناء المشروع"""
32
+ structure = self.load_structure()
33
+
34
+ # التأكد من إنشاء المجلد الرئيسي للمشروع أولاً
35
+ if not os.path.exists(self.output_path):
36
+ os.makedirs(self.output_path, exist_ok=True)
37
+ print(f"🏗️ Created project root: {self.output_path}")
38
+
39
+ # 1. إنشاء المجلدات الفرعية المذكورة في القالب
40
+ for folder in structure.get('directories', []):
41
+ rendered_folder = Template(folder).render(self.context)
42
+ path = os.path.join(self.output_path, rendered_folder)
43
+ os.makedirs(path, exist_ok=True)
44
+ print(f"📁 Created directory: {path}")
45
+
46
+ # 2. إنشاء الملفات وتعبئة محتواها
47
+ for file_info in structure.get('files', []):
48
+ rendered_path = Template(file_info['path']).render(self.context)
49
+ rendered_content = Template(file_info['content']).render(self.context)
50
+
51
+ full_path = os.path.join(self.output_path, rendered_path)
52
+
53
+ # التأكد من وجود المجلد الأب للملف (في حال كان ملفاً عميقاً)
54
+ os.makedirs(os.path.dirname(full_path), exist_ok=True)
55
+
56
+ with open(full_path, 'w', encoding='utf-8') as f:
57
+ f.write(rendered_content)
58
+ print(f"📄 Created file: {full_path}")
59
+
60
+ # 3. تنفيذ أوامر ما بعد البناء
61
+ self.run_post_commands(structure.get('post_commands', []))
62
+
63
+ print(f"\n✅ Archiforge: Project '{self.context['project_name']}' forged successfully!")
64
+
65
+ def run_post_commands(self, commands):
66
+ """تنفيذ أوامر مثل git init أو npm install"""
67
+ if not commands:
68
+ return
69
+
70
+ original_dir = os.getcwd()
71
+ os.chdir(self.output_path)
72
+
73
+ for cmd in commands:
74
+ rendered_cmd = Template(cmd).render(self.context)
75
+ print(f"⚡ Running: {rendered_cmd}...")
76
+ try:
77
+ subprocess.run(rendered_cmd, shell=True, check=True)
78
+ except subprocess.CalledProcessError as e:
79
+ print(f"⚠️ Command failed: {e}")
80
+
81
+ os.chdir(original_dir)
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: archiforge
3
+ Version: 0.1.0
4
+ Summary: A smart project scaffolding tool for developers
5
+ Author-email: Abdullah <your-email@example.com>
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: click
9
+ Requires-Dist: jinja2
10
+ Requires-Dist: pyyaml
11
+
12
+ # Archiforge 🛠️
13
+
14
+ **Archiforge** is a multi-language project scaffolding engine. It helps developers "forge" standardized project structures for Python, JavaScript, Go, and more.
15
+
16
+ ## 🎯 Key Goals
17
+ - **Multi-language Support**: Generate blueprints for any stack.
18
+ - **Customizable**: Users can create their own project templates.
19
+ - **CLI Driven**: Fast and intuitive command-line interface.
20
+
21
+ ## 📂 Structure
22
+ - `src/archiforge/core`: The logic that builds the files.
23
+ - `src/archiforge/blueprints`: Templates for different languages.
@@ -0,0 +1,8 @@
1
+ archiforge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ archiforge/cli/main.py,sha256=wvXdpb3KHylH4bdFQROgvXvnhQZdNAPEIvIzaPGeq8o,4455
3
+ archiforge/core/engine.py,sha256=2LYAX9pCFeH2XiWWoWy6wtRRhHQ6Iv0gXm-jMPjPGnQ,3619
4
+ archiforge-0.1.0.dist-info/METADATA,sha256=sSOT_dNgByLtBzBv1domenk80wMmDNg0Y3SePy7zmdc,848
5
+ archiforge-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
6
+ archiforge-0.1.0.dist-info/entry_points.txt,sha256=jyl3CpcHKlBPvThMieY_kf2ANsd5-c6mggUzRa-Xasw,55
7
+ archiforge-0.1.0.dist-info/top_level.txt,sha256=M4KFcxERVwOYzoKnhzJzwtuBHHglemyN_KSU7sfup6k,11
8
+ archiforge-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ archiforge = archiforge.cli.main:cli
@@ -0,0 +1 @@
1
+ archiforge