clapp-pm 1.0.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.
info_command.py ADDED
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ info_command.py - Uygulama bilgi görüntüleme modülü
4
+
5
+ Bu modül `clapp info <app_name>` komutunu destekler ve
6
+ yüklü uygulamaların detaylı bilgilerini gösterir.
7
+ """
8
+
9
+ import os
10
+ import json
11
+ from pathlib import Path
12
+ from package_registry import get_manifest
13
+
14
+ def format_field(name, value, width=20):
15
+ """Alanı formatlar"""
16
+ if value is None or value == "":
17
+ value = "Belirtilmemiş"
18
+ return f"{name:<{width}}: {value}"
19
+
20
+ def format_list(items, indent=22):
21
+ """Liste öğelerini formatlar"""
22
+ if not items:
23
+ return "Yok"
24
+
25
+ if len(items) == 1:
26
+ return items[0]
27
+
28
+ result = items[0]
29
+ for item in items[1:]:
30
+ result += f"\n{' ' * indent}{item}"
31
+ return result
32
+
33
+ def get_app_file_info(app_name):
34
+ """Uygulama dosya bilgilerini toplar"""
35
+ apps_dir = Path("apps")
36
+ app_dir = apps_dir / app_name
37
+
38
+ if not app_dir.exists():
39
+ return None
40
+
41
+ info = {
42
+ "path": str(app_dir.absolute()),
43
+ "size": 0,
44
+ "file_count": 0,
45
+ "files": []
46
+ }
47
+
48
+ try:
49
+ for file_path in app_dir.rglob("*"):
50
+ if file_path.is_file():
51
+ info["file_count"] += 1
52
+ info["size"] += file_path.stat().st_size
53
+ info["files"].append(file_path.name)
54
+ except Exception:
55
+ pass
56
+
57
+ return info
58
+
59
+ def format_size(size_bytes):
60
+ """Dosya boyutunu formatlar"""
61
+ if size_bytes == 0:
62
+ return "0 B"
63
+
64
+ for unit in ['B', 'KB', 'MB', 'GB']:
65
+ if size_bytes < 1024.0:
66
+ return f"{size_bytes:.1f} {unit}"
67
+ size_bytes /= 1024.0
68
+
69
+ return f"{size_bytes:.1f} TB"
70
+
71
+ def show_app_info(app_name):
72
+ """Uygulama bilgilerini gösterir"""
73
+ print(f"📋 {app_name} - Uygulama Bilgileri")
74
+ print("=" * 50)
75
+
76
+ # Manifest bilgilerini al
77
+ manifest = get_manifest(app_name)
78
+
79
+ if not manifest:
80
+ print(f"❌ '{app_name}' uygulaması bulunamadı veya manifest.json eksik.")
81
+ print()
82
+ print("🔧 Öneriler:")
83
+ print("• Uygulama adını kontrol edin")
84
+ print("• apps/ dizininde uygulama klasörünün var olduğundan emin olun")
85
+ print("• manifest.json dosyasının mevcut olduğundan emin olun")
86
+ print("• Doğrulama için: clapp validate apps/[app_name]")
87
+ return False
88
+
89
+ # Temel bilgiler
90
+ print("📦 Temel Bilgiler:")
91
+ print(format_field("Ad", manifest.get("name", app_name)))
92
+ print(format_field("Sürüm", manifest.get("version", "Belirtilmemiş")))
93
+ print(format_field("Dil", manifest.get("language", "Belirtilmemiş")))
94
+ print(format_field("Giriş Dosyası", manifest.get("entry", "Belirtilmemiş")))
95
+ print()
96
+
97
+ # Açıklama
98
+ description = manifest.get("description", "")
99
+ if description:
100
+ print("📝 Açıklama:")
101
+ print(f" {description}")
102
+ print()
103
+
104
+ # Bağımlılıklar
105
+ dependencies = manifest.get("dependencies", [])
106
+ print("🔗 Bağımlılıklar:")
107
+ if dependencies:
108
+ for dep in dependencies:
109
+ print(f" • {dep}")
110
+ else:
111
+ print(" Bağımlılık yok")
112
+ print()
113
+
114
+ # Dosya bilgileri
115
+ file_info = get_app_file_info(app_name)
116
+ if file_info:
117
+ print("📁 Dosya Bilgileri:")
118
+ print(format_field("Konum", file_info["path"]))
119
+ print(format_field("Dosya Sayısı", file_info["file_count"]))
120
+ print(format_field("Toplam Boyut", format_size(file_info["size"])))
121
+ print()
122
+
123
+ # Dosya listesi (ilk 10 dosya)
124
+ if file_info["files"]:
125
+ print("📄 Dosyalar:")
126
+ files_to_show = file_info["files"][:10]
127
+ for file_name in files_to_show:
128
+ print(f" • {file_name}")
129
+
130
+ if len(file_info["files"]) > 10:
131
+ print(f" ... ve {len(file_info['files']) - 10} dosya daha")
132
+ print()
133
+
134
+ # Ek bilgiler
135
+ extra_fields = ["author", "license", "homepage", "repository"]
136
+ extra_info = []
137
+
138
+ for field in extra_fields:
139
+ if field in manifest:
140
+ extra_info.append((field.title(), manifest[field]))
141
+
142
+ if extra_info:
143
+ print("ℹ️ Ek Bilgiler:")
144
+ for field_name, value in extra_info:
145
+ print(format_field(field_name, value))
146
+ print()
147
+
148
+ # Çalıştırma bilgisi
149
+ print("🚀 Çalıştırma:")
150
+ print(f" clapp run {app_name}")
151
+
152
+ # Doğrulama önerisi
153
+ print()
154
+ print("🔧 Doğrulama:")
155
+ print(f" clapp validate apps/{app_name}")
156
+
157
+ return True
158
+
159
+ def list_all_apps_info():
160
+ """Tüm uygulamaların kısa bilgilerini listeler"""
161
+ from package_registry import list_packages
162
+
163
+ packages = list_packages()
164
+
165
+ if not packages:
166
+ print("📦 Yüklü uygulama bulunamadı.")
167
+ return
168
+
169
+ print("📋 Yüklü Uygulamalar - Özet Bilgiler")
170
+ print("=" * 60)
171
+
172
+ for package in packages:
173
+ name = package.get("name", "Bilinmiyor")
174
+ version = package.get("version", "?")
175
+ language = package.get("language", "?")
176
+ description = package.get("description", "Açıklama yok")
177
+
178
+ # Açıklamayı kısalt
179
+ if len(description) > 40:
180
+ description = description[:37] + "..."
181
+
182
+ print(f"📦 {name} (v{version})")
183
+ print(f" 🔧 Dil: {language}")
184
+ print(f" 📝 {description}")
185
+ print()
186
+
187
+ if __name__ == "__main__":
188
+ import sys
189
+
190
+ if len(sys.argv) > 1:
191
+ app_name = sys.argv[1]
192
+ show_app_info(app_name)
193
+ else:
194
+ list_all_apps_info()
installer.py ADDED
@@ -0,0 +1,320 @@
1
+ import os
2
+ import zipfile
3
+ import urllib.request
4
+ import tempfile
5
+ import shutil
6
+ import json
7
+ from manifest_validator import validate_manifest_verbose
8
+ from package_registry import app_exists
9
+
10
+ def install_package(source, force=False):
11
+ """
12
+ Bir .clapp paketini zip dosyasından veya URL'den yükler.
13
+
14
+ Args:
15
+ source (str): Yerel zip dosya yolu veya uzak URL
16
+ force (bool): Mevcut uygulamanın üzerine yazılmasına izin ver
17
+
18
+ Returns:
19
+ tuple: (success: bool, message: str)
20
+ """
21
+ temp_dir = None
22
+
23
+ try:
24
+ # Geçici dizin oluştur
25
+ temp_dir = tempfile.mkdtemp()
26
+
27
+ # Kaynak türünü belirle (URL mu dosya yolu mu)
28
+ if source.startswith(('http://', 'https://')):
29
+ # URL'den indir
30
+ zip_path = download_package(source, temp_dir)
31
+ if not zip_path:
32
+ return False, "Paket indirilemedi"
33
+ else:
34
+ # Yerel dosya
35
+ if not os.path.exists(source):
36
+ return False, f"Dosya bulunamadı: {source}"
37
+ zip_path = source
38
+
39
+ # Zip dosyasını çıkart
40
+ extract_path = os.path.join(temp_dir, "extracted")
41
+ success, message = extract_package(zip_path, extract_path)
42
+ if not success:
43
+ return False, message
44
+
45
+ # Manifest'i yükle ve doğrula
46
+ manifest_path = os.path.join(extract_path, "manifest.json")
47
+ is_valid, errors = validate_manifest_file(manifest_path)
48
+ if not is_valid:
49
+ error_msg = "Manifest doğrulama hatası:\n" + "\n".join(errors)
50
+ return False, error_msg
51
+
52
+ # Manifest'i yükle
53
+ with open(manifest_path, 'r', encoding='utf-8') as f:
54
+ manifest = json.load(f)
55
+
56
+ app_name = manifest['name']
57
+
58
+ # Uygulama zaten var mı kontrol et
59
+ if app_exists(app_name) and not force:
60
+ return False, f"Uygulama '{app_name}' zaten yüklü. --force kullanarak üzerine yazabilirsiniz."
61
+
62
+ # Giriş dosyasının varlığını kontrol et
63
+ entry_file = manifest['entry']
64
+ entry_path = os.path.join(extract_path, entry_file)
65
+ if not os.path.exists(entry_path):
66
+ return False, f"Giriş dosyası bulunamadı: {entry_file}"
67
+
68
+ # Hedef dizini oluştur
69
+ target_dir = os.path.join("apps", app_name)
70
+
71
+ # Mevcut dizini sil (eğer varsa)
72
+ if os.path.exists(target_dir):
73
+ shutil.rmtree(target_dir)
74
+
75
+ # Dosyaları kopyala
76
+ shutil.copytree(extract_path, target_dir)
77
+
78
+ return True, f"✅ '{app_name}' başarıyla yüklendi!"
79
+
80
+ except Exception as e:
81
+ return False, f"Yükleme hatası: {e}"
82
+
83
+ finally:
84
+ # Geçici dizini temizle
85
+ if temp_dir and os.path.exists(temp_dir):
86
+ shutil.rmtree(temp_dir)
87
+
88
+ def download_package(url, temp_dir):
89
+ """
90
+ Paketi URL'den indirir.
91
+
92
+ Args:
93
+ url (str): İndirilecek URL
94
+ temp_dir (str): Geçici dizin
95
+
96
+ Returns:
97
+ str or None: İndirilen dosyanın yolu veya None
98
+ """
99
+ try:
100
+ print(f"Paket indiriliyor: {url}")
101
+
102
+ # Dosya adını URL'den çıkar
103
+ filename = os.path.basename(url)
104
+ if not filename.endswith('.zip'):
105
+ filename += '.zip'
106
+
107
+ zip_path = os.path.join(temp_dir, filename)
108
+
109
+ # Dosyayı indir
110
+ urllib.request.urlretrieve(url, zip_path)
111
+
112
+ print(f"✅ İndirme tamamlandı: {filename}")
113
+ return zip_path
114
+
115
+ except Exception as e:
116
+ print(f"❌ İndirme hatası: {e}")
117
+ return None
118
+
119
+ def extract_package(zip_path, extract_path):
120
+ """
121
+ Zip dosyasını çıkarır.
122
+
123
+ Args:
124
+ zip_path (str): Zip dosyasının yolu
125
+ extract_path (str): Çıkarılacak dizin
126
+
127
+ Returns:
128
+ tuple: (success: bool, message: str)
129
+ """
130
+ try:
131
+ # Çıkarma dizinini oluştur
132
+ os.makedirs(extract_path, exist_ok=True)
133
+
134
+ # Zip dosyasını aç ve çıkar
135
+ with zipfile.ZipFile(zip_path, 'r') as zip_ref:
136
+ zip_ref.extractall(extract_path)
137
+
138
+ print(f"✅ Paket çıkarıldı: {extract_path}")
139
+ return True, "Paket başarıyla çıkarıldı"
140
+
141
+ except zipfile.BadZipFile:
142
+ return False, "Geçersiz zip dosyası"
143
+ except Exception as e:
144
+ return False, f"Çıkarma hatası: {e}"
145
+
146
+ def validate_manifest_file(manifest_path):
147
+ """
148
+ Manifest dosyasını doğrular.
149
+
150
+ Args:
151
+ manifest_path (str): Manifest dosyasının yolu
152
+
153
+ Returns:
154
+ tuple: (is_valid: bool, errors: list)
155
+ """
156
+ if not os.path.exists(manifest_path):
157
+ return False, ["Manifest dosyası bulunamadı"]
158
+
159
+ try:
160
+ with open(manifest_path, 'r', encoding='utf-8') as f:
161
+ manifest = json.load(f)
162
+
163
+ return validate_manifest_verbose(manifest)
164
+
165
+ except json.JSONDecodeError as e:
166
+ return False, [f"JSON formatı hatalı: {e}"]
167
+ except Exception as e:
168
+ return False, [f"Dosya okuma hatası: {e}"]
169
+
170
+ def create_package_from_directory(source_dir, output_path=None):
171
+ """
172
+ Dizinden .clapp paketi oluşturur.
173
+
174
+ Args:
175
+ source_dir (str): Kaynak dizin
176
+ output_path (str): Çıktı dosyası yolu (opsiyonel)
177
+
178
+ Returns:
179
+ tuple: (success: bool, message: str, output_file: str)
180
+ """
181
+ try:
182
+ # Manifest dosyasını kontrol et
183
+ manifest_path = os.path.join(source_dir, "manifest.json")
184
+ is_valid, errors = validate_manifest_file(manifest_path)
185
+
186
+ if not is_valid:
187
+ error_msg = "Manifest doğrulama hatası:\n" + "\n".join(errors)
188
+ return False, error_msg, None
189
+
190
+ # Manifest'i yükle
191
+ with open(manifest_path, 'r', encoding='utf-8') as f:
192
+ manifest = json.load(f)
193
+
194
+ app_name = manifest['name']
195
+
196
+ # Çıktı dosyası yolunu belirle
197
+ if not output_path:
198
+ output_path = f"{app_name}.clapp.zip"
199
+
200
+ # Zip dosyasını oluştur
201
+ with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zip_ref:
202
+ for root, dirs, files in os.walk(source_dir):
203
+ for file in files:
204
+ file_path = os.path.join(root, file)
205
+ arc_path = os.path.relpath(file_path, source_dir)
206
+ zip_ref.write(file_path, arc_path)
207
+
208
+ return True, f"✅ Paket oluşturuldu: {output_path}", output_path
209
+
210
+ except Exception as e:
211
+ return False, f"Paket oluşturma hatası: {e}", None
212
+
213
+ def install_from_directory(source_dir, force=False):
214
+ """
215
+ Dizinden doğrudan uygulama yükler.
216
+
217
+ Args:
218
+ source_dir (str): Kaynak dizin
219
+ force (bool): Mevcut uygulamanın üzerine yazılmasına izin ver
220
+
221
+ Returns:
222
+ tuple: (success: bool, message: str)
223
+ """
224
+ try:
225
+ # Manifest dosyasını kontrol et
226
+ manifest_path = os.path.join(source_dir, "manifest.json")
227
+ is_valid, errors = validate_manifest_file(manifest_path)
228
+
229
+ if not is_valid:
230
+ error_msg = "Manifest doğrulama hatası:\n" + "\n".join(errors)
231
+ return False, error_msg
232
+
233
+ # Manifest'i yükle
234
+ with open(manifest_path, 'r', encoding='utf-8') as f:
235
+ manifest = json.load(f)
236
+
237
+ app_name = manifest['name']
238
+
239
+ # Uygulama zaten var mı kontrol et
240
+ if app_exists(app_name) and not force:
241
+ return False, f"Uygulama '{app_name}' zaten yüklü. --force kullanarak üzerine yazabilirsiniz."
242
+
243
+ # Giriş dosyasının varlığını kontrol et
244
+ entry_file = manifest['entry']
245
+ entry_path = os.path.join(source_dir, entry_file)
246
+ if not os.path.exists(entry_path):
247
+ return False, f"Giriş dosyası bulunamadı: {entry_file}"
248
+
249
+ # Hedef dizini oluştur
250
+ target_dir = os.path.join("apps", app_name)
251
+
252
+ # Mevcut dizini sil (eğer varsa)
253
+ if os.path.exists(target_dir):
254
+ shutil.rmtree(target_dir)
255
+
256
+ # Dosyaları kopyala
257
+ shutil.copytree(source_dir, target_dir)
258
+
259
+ return True, f"✅ '{app_name}' başarıyla yüklendi!"
260
+
261
+ except Exception as e:
262
+ return False, f"Yükleme hatası: {e}"
263
+
264
+ def uninstall_package(app_name):
265
+ """
266
+ Uygulamayı kaldırır.
267
+
268
+ Args:
269
+ app_name (str): Kaldırılacak uygulama adı
270
+
271
+ Returns:
272
+ tuple: (success: bool, message: str)
273
+ """
274
+ try:
275
+ if not app_exists(app_name):
276
+ return False, f"Uygulama '{app_name}' bulunamadı"
277
+
278
+ # Uygulama dizinini sil
279
+ app_dir = os.path.join("apps", app_name)
280
+ shutil.rmtree(app_dir)
281
+
282
+ return True, f"✅ '{app_name}' başarıyla kaldırıldı!"
283
+
284
+ except Exception as e:
285
+ return False, f"Kaldırma hatası: {e}"
286
+
287
+ def list_installable_files(directory="."):
288
+ """
289
+ Dizindeki yüklenebilir .clapp dosyalarını listeler.
290
+
291
+ Args:
292
+ directory (str): Aranacak dizin
293
+
294
+ Returns:
295
+ list: .clapp dosyalarının listesi
296
+ """
297
+ clapp_files = []
298
+
299
+ for file in os.listdir(directory):
300
+ if file.endswith('.clapp.zip') or file.endswith('.zip'):
301
+ file_path = os.path.join(directory, file)
302
+ clapp_files.append(file_path)
303
+
304
+ return clapp_files
305
+
306
+ if __name__ == "__main__":
307
+ # Test için örnek kullanım
308
+ print("clapp Installer Test")
309
+ print("=" * 30)
310
+
311
+ # Mevcut dizindeki .clapp dosyalarını listele
312
+ installable = list_installable_files()
313
+ if installable:
314
+ print("Yüklenebilir dosyalar:")
315
+ for file in installable:
316
+ print(f" - {file}")
317
+ else:
318
+ print("Yüklenebilir dosya bulunamadı")
319
+
320
+ print("\nTest tamamlandı.")