clapp-pm 1.0.9__py3-none-any.whl → 1.0.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.
- backup_current/build_index.py +132 -0
- backup_current/check_env.py +133 -0
- backup_current/clapp_core.py +61 -0
- backup_current/clean_command.py +214 -0
- backup_current/cli_commands.py +404 -0
- backup_current/dependency_resolver.py +272 -0
- backup_current/doctor_command.py +239 -0
- backup_current/info_command.py +194 -0
- backup_current/install_command.py +236 -0
- backup_current/installer.py +323 -0
- backup_current/list_command.py +262 -0
- backup_current/main.py +294 -0
- backup_current/manifest_schema.py +84 -0
- backup_current/manifest_validator.py +245 -0
- backup_current/package_registry.py +127 -0
- backup_current/package_runner.py +85 -0
- backup_current/post_install_hint.py +144 -0
- backup_current/publish_command.py +253 -0
- backup_current/remote_registry.py +285 -0
- backup_current/setup.py +160 -0
- backup_current/system_test.py +477 -0
- backup_current/uninstall_command.py +215 -0
- backup_current/validate_command.py +225 -0
- backup_current/version.py +8 -0
- backup_current/version_command.py +145 -0
- backup_current/where_command.py +207 -0
- check_env.py +1 -8
- clapp-packages-repo/packages/hello-python/main.py +0 -49
- clapp-packages-repo/packages/hello-python/manifest.json +0 -8
- {clapp_pm-1.0.9.data → clapp_pm-1.0.11.data}/data/version.json +1 -1
- {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/METADATA +1 -1
- clapp_pm-1.0.11.dist-info/RECORD +71 -0
- {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/top_level.txt +2 -0
- doctor_command.py +0 -1
- install_command.py +3 -0
- version.py +8 -0
- clapp_pm-1.0.9.dist-info/RECORD +0 -44
- {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/WHEEL +0 -0
- {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/entry_points.txt +0 -0
- {clapp_pm-1.0.9.dist-info → clapp_pm-1.0.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,323 @@
|
|
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 find_app_folder(extract_path, app_name):
|
11
|
+
"""
|
12
|
+
Zip çıkarıldıktan sonra, extract_path altında **/packages/{app_name} klasörünü bulur.
|
13
|
+
"""
|
14
|
+
for root, dirs, files in os.walk(extract_path):
|
15
|
+
if os.path.basename(root) == app_name and os.path.basename(os.path.dirname(root)) == "packages":
|
16
|
+
return root
|
17
|
+
return None
|
18
|
+
|
19
|
+
|
20
|
+
def install_package(source, force=False):
|
21
|
+
"""
|
22
|
+
Bir .clapp paketini zip dosyasından veya URL'den yükler.
|
23
|
+
"""
|
24
|
+
temp_dir = None
|
25
|
+
try:
|
26
|
+
temp_dir = tempfile.mkdtemp()
|
27
|
+
if source.startswith(('http://', 'https://')):
|
28
|
+
zip_path = download_package(source, temp_dir)
|
29
|
+
if not zip_path:
|
30
|
+
return False, "Paket indirilemedi"
|
31
|
+
else:
|
32
|
+
if not os.path.exists(source):
|
33
|
+
return False, f"Dosya bulunamadı: {source}"
|
34
|
+
zip_path = source
|
35
|
+
extract_path = os.path.join(temp_dir, "extracted")
|
36
|
+
success, message = extract_package(zip_path, extract_path)
|
37
|
+
if not success:
|
38
|
+
return False, message
|
39
|
+
|
40
|
+
# --- YENİ: Doğru app klasörünü bul ---
|
41
|
+
# Önce manifesti bulmak için tüm app klasörlerini tara
|
42
|
+
app_folder = None
|
43
|
+
manifest = None
|
44
|
+
manifest_path = None
|
45
|
+
# Tüm packages altındaki app klasörlerini bul
|
46
|
+
for root, dirs, files in os.walk(extract_path):
|
47
|
+
if "manifest.json" in files:
|
48
|
+
with open(os.path.join(root, "manifest.json"), 'r', encoding='utf-8') as f:
|
49
|
+
try:
|
50
|
+
m = json.load(f)
|
51
|
+
if 'name' in m:
|
52
|
+
app_folder = root
|
53
|
+
manifest = m
|
54
|
+
manifest_path = os.path.join(root, "manifest.json")
|
55
|
+
break
|
56
|
+
except Exception:
|
57
|
+
continue
|
58
|
+
if not app_folder or not manifest:
|
59
|
+
return False, "Uygulama klasörü bulunamadı: manifest.json"
|
60
|
+
app_name = manifest['name']
|
61
|
+
|
62
|
+
# --- YENİ: Sadece packages/{app_name} klasörünü bul ve kopyala ---
|
63
|
+
app_real_folder = find_app_folder(extract_path, app_name)
|
64
|
+
if not app_real_folder:
|
65
|
+
return False, f"Uygulama klasörü bulunamadı: packages/{app_name}"
|
66
|
+
|
67
|
+
# Manifesti doğrula
|
68
|
+
is_valid, errors = validate_manifest_file(os.path.join(app_real_folder, "manifest.json"))
|
69
|
+
if not is_valid:
|
70
|
+
error_msg = "Manifest doğrulama hatası:\n" + "\n".join(errors)
|
71
|
+
return False, error_msg
|
72
|
+
|
73
|
+
# Giriş dosyasının varlığını kontrol et
|
74
|
+
entry_file = manifest['entry']
|
75
|
+
entry_path = os.path.join(app_real_folder, entry_file)
|
76
|
+
if not os.path.exists(entry_path):
|
77
|
+
return False, f"Giriş dosyası bulunamadı: {entry_file}"
|
78
|
+
|
79
|
+
# Hedef dizini oluştur
|
80
|
+
target_dir = os.path.join("apps", app_name)
|
81
|
+
if os.path.exists(target_dir):
|
82
|
+
shutil.rmtree(target_dir)
|
83
|
+
shutil.copytree(app_real_folder, target_dir)
|
84
|
+
return True, f"✅ '{app_name}' başarıyla yüklendi!"
|
85
|
+
except Exception as e:
|
86
|
+
return False, f"Yükleme hatası: {e}"
|
87
|
+
finally:
|
88
|
+
if temp_dir and os.path.exists(temp_dir):
|
89
|
+
shutil.rmtree(temp_dir)
|
90
|
+
|
91
|
+
def download_package(url, temp_dir):
|
92
|
+
"""
|
93
|
+
Paketi URL'den indirir.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
url (str): İndirilecek URL
|
97
|
+
temp_dir (str): Geçici dizin
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
str or None: İndirilen dosyanın yolu veya None
|
101
|
+
"""
|
102
|
+
try:
|
103
|
+
print(f"Paket indiriliyor: {url}")
|
104
|
+
|
105
|
+
# Dosya adını URL'den çıkar
|
106
|
+
filename = os.path.basename(url)
|
107
|
+
if not filename.endswith('.zip'):
|
108
|
+
filename += '.zip'
|
109
|
+
|
110
|
+
zip_path = os.path.join(temp_dir, filename)
|
111
|
+
|
112
|
+
# Dosyayı indir
|
113
|
+
urllib.request.urlretrieve(url, zip_path)
|
114
|
+
|
115
|
+
print(f"✅ İndirme tamamlandı: {filename}")
|
116
|
+
return zip_path
|
117
|
+
|
118
|
+
except Exception as e:
|
119
|
+
print(f"❌ İndirme hatası: {e}")
|
120
|
+
return None
|
121
|
+
|
122
|
+
def extract_package(zip_path, extract_path):
|
123
|
+
"""
|
124
|
+
Zip dosyasını çıkarır.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
zip_path (str): Zip dosyasının yolu
|
128
|
+
extract_path (str): Çıkarılacak dizin
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
tuple: (success: bool, message: str)
|
132
|
+
"""
|
133
|
+
try:
|
134
|
+
# Çıkarma dizinini oluştur
|
135
|
+
os.makedirs(extract_path, exist_ok=True)
|
136
|
+
|
137
|
+
# Zip dosyasını aç ve çıkar
|
138
|
+
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
139
|
+
zip_ref.extractall(extract_path)
|
140
|
+
|
141
|
+
print(f"✅ Paket çıkarıldı: {extract_path}")
|
142
|
+
return True, "Paket başarıyla çıkarıldı"
|
143
|
+
|
144
|
+
except zipfile.BadZipFile:
|
145
|
+
return False, "Geçersiz zip dosyası"
|
146
|
+
except Exception as e:
|
147
|
+
return False, f"Çıkarma hatası: {e}"
|
148
|
+
|
149
|
+
def validate_manifest_file(manifest_path):
|
150
|
+
"""
|
151
|
+
Manifest dosyasını doğrular.
|
152
|
+
|
153
|
+
Args:
|
154
|
+
manifest_path (str): Manifest dosyasının yolu
|
155
|
+
|
156
|
+
Returns:
|
157
|
+
tuple: (is_valid: bool, errors: list)
|
158
|
+
"""
|
159
|
+
if not os.path.exists(manifest_path):
|
160
|
+
return False, ["Manifest dosyası bulunamadı"]
|
161
|
+
|
162
|
+
try:
|
163
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
164
|
+
manifest = json.load(f)
|
165
|
+
|
166
|
+
return validate_manifest_verbose(manifest)
|
167
|
+
|
168
|
+
except json.JSONDecodeError as e:
|
169
|
+
return False, [f"JSON formatı hatalı: {e}"]
|
170
|
+
except Exception as e:
|
171
|
+
return False, [f"Dosya okuma hatası: {e}"]
|
172
|
+
|
173
|
+
def create_package_from_directory(source_dir, output_path=None):
|
174
|
+
"""
|
175
|
+
Dizinden .clapp paketi oluşturur.
|
176
|
+
|
177
|
+
Args:
|
178
|
+
source_dir (str): Kaynak dizin
|
179
|
+
output_path (str): Çıktı dosyası yolu (opsiyonel)
|
180
|
+
|
181
|
+
Returns:
|
182
|
+
tuple: (success: bool, message: str, output_file: str)
|
183
|
+
"""
|
184
|
+
try:
|
185
|
+
# Manifest dosyasını kontrol et
|
186
|
+
manifest_path = os.path.join(source_dir, "manifest.json")
|
187
|
+
is_valid, errors = validate_manifest_file(manifest_path)
|
188
|
+
|
189
|
+
if not is_valid:
|
190
|
+
error_msg = "Manifest doğrulama hatası:\n" + "\n".join(errors)
|
191
|
+
return False, error_msg, None
|
192
|
+
|
193
|
+
# Manifest'i yükle
|
194
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
195
|
+
manifest = json.load(f)
|
196
|
+
|
197
|
+
app_name = manifest['name']
|
198
|
+
|
199
|
+
# Çıktı dosyası yolunu belirle
|
200
|
+
if not output_path:
|
201
|
+
output_path = f"{app_name}.clapp.zip"
|
202
|
+
|
203
|
+
# Zip dosyasını oluştur
|
204
|
+
with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zip_ref:
|
205
|
+
for root, dirs, files in os.walk(source_dir):
|
206
|
+
for file in files:
|
207
|
+
file_path = os.path.join(root, file)
|
208
|
+
arc_path = os.path.relpath(file_path, source_dir)
|
209
|
+
zip_ref.write(file_path, arc_path)
|
210
|
+
|
211
|
+
return True, f"✅ Paket oluşturuldu: {output_path}", output_path
|
212
|
+
|
213
|
+
except Exception as e:
|
214
|
+
return False, f"Paket oluşturma hatası: {e}", None
|
215
|
+
|
216
|
+
def install_from_directory(source_dir, force=False):
|
217
|
+
"""
|
218
|
+
Dizinden doğrudan uygulama yükler.
|
219
|
+
|
220
|
+
Args:
|
221
|
+
source_dir (str): Kaynak dizin
|
222
|
+
force (bool): Mevcut uygulamanın üzerine yazılmasına izin ver
|
223
|
+
|
224
|
+
Returns:
|
225
|
+
tuple: (success: bool, message: str)
|
226
|
+
"""
|
227
|
+
try:
|
228
|
+
# Manifest dosyasını kontrol et
|
229
|
+
manifest_path = os.path.join(source_dir, "manifest.json")
|
230
|
+
is_valid, errors = validate_manifest_file(manifest_path)
|
231
|
+
|
232
|
+
if not is_valid:
|
233
|
+
error_msg = "Manifest doğrulama hatası:\n" + "\n".join(errors)
|
234
|
+
return False, error_msg
|
235
|
+
|
236
|
+
# Manifest'i yükle
|
237
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
238
|
+
manifest = json.load(f)
|
239
|
+
|
240
|
+
app_name = manifest['name']
|
241
|
+
|
242
|
+
# Uygulama zaten var mı kontrol et
|
243
|
+
if app_exists(app_name) and not force:
|
244
|
+
return False, f"Uygulama '{app_name}' zaten yüklü. --force kullanarak üzerine yazabilirsiniz."
|
245
|
+
|
246
|
+
# Giriş dosyasının varlığını kontrol et
|
247
|
+
entry_file = manifest['entry']
|
248
|
+
entry_path = os.path.join(source_dir, entry_file)
|
249
|
+
if not os.path.exists(entry_path):
|
250
|
+
return False, f"Giriş dosyası bulunamadı: {entry_file}"
|
251
|
+
|
252
|
+
# Hedef dizini oluştur
|
253
|
+
target_dir = os.path.join("apps", app_name)
|
254
|
+
|
255
|
+
# Mevcut dizini sil (eğer varsa)
|
256
|
+
if os.path.exists(target_dir):
|
257
|
+
shutil.rmtree(target_dir)
|
258
|
+
|
259
|
+
# Dosyaları kopyala
|
260
|
+
shutil.copytree(source_dir, target_dir)
|
261
|
+
|
262
|
+
return True, f"✅ '{app_name}' başarıyla yüklendi!"
|
263
|
+
|
264
|
+
except Exception as e:
|
265
|
+
return False, f"Yükleme hatası: {e}"
|
266
|
+
|
267
|
+
def uninstall_package(app_name):
|
268
|
+
"""
|
269
|
+
Uygulamayı kaldırır.
|
270
|
+
|
271
|
+
Args:
|
272
|
+
app_name (str): Kaldırılacak uygulama adı
|
273
|
+
|
274
|
+
Returns:
|
275
|
+
tuple: (success: bool, message: str)
|
276
|
+
"""
|
277
|
+
try:
|
278
|
+
if not app_exists(app_name):
|
279
|
+
return False, f"Uygulama '{app_name}' bulunamadı"
|
280
|
+
|
281
|
+
# Uygulama dizinini sil
|
282
|
+
app_dir = os.path.join("apps", app_name)
|
283
|
+
shutil.rmtree(app_dir)
|
284
|
+
|
285
|
+
return True, f"✅ '{app_name}' başarıyla kaldırıldı!"
|
286
|
+
|
287
|
+
except Exception as e:
|
288
|
+
return False, f"Kaldırma hatası: {e}"
|
289
|
+
|
290
|
+
def list_installable_files(directory="."):
|
291
|
+
"""
|
292
|
+
Dizindeki yüklenebilir .clapp dosyalarını listeler.
|
293
|
+
|
294
|
+
Args:
|
295
|
+
directory (str): Aranacak dizin
|
296
|
+
|
297
|
+
Returns:
|
298
|
+
list: .clapp dosyalarının listesi
|
299
|
+
"""
|
300
|
+
clapp_files = []
|
301
|
+
|
302
|
+
for file in os.listdir(directory):
|
303
|
+
if file.endswith('.clapp.zip') or file.endswith('.zip'):
|
304
|
+
file_path = os.path.join(directory, file)
|
305
|
+
clapp_files.append(file_path)
|
306
|
+
|
307
|
+
return clapp_files
|
308
|
+
|
309
|
+
if __name__ == "__main__":
|
310
|
+
# Test için örnek kullanım
|
311
|
+
print("clapp Installer Test")
|
312
|
+
print("=" * 30)
|
313
|
+
|
314
|
+
# Mevcut dizindeki .clapp dosyalarını listele
|
315
|
+
installable = list_installable_files()
|
316
|
+
if installable:
|
317
|
+
print("Yüklenebilir dosyalar:")
|
318
|
+
for file in installable:
|
319
|
+
print(f" - {file}")
|
320
|
+
else:
|
321
|
+
print("Yüklenebilir dosya bulunamadı")
|
322
|
+
|
323
|
+
print("\nTest tamamlandı.")
|
@@ -0,0 +1,262 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
list_command.py - clapp List Command
|
4
|
+
|
5
|
+
Bu modül 'clapp list' komutunu uygular.
|
6
|
+
Kurulu uygulamaları farklı formatlarda listeler.
|
7
|
+
"""
|
8
|
+
|
9
|
+
import os
|
10
|
+
import json
|
11
|
+
import sys
|
12
|
+
from pathlib import Path
|
13
|
+
from typing import List, Dict, Any, Optional
|
14
|
+
|
15
|
+
def get_apps_directory() -> str:
|
16
|
+
"""Uygulamaların kurulu olduğu dizini döndürür"""
|
17
|
+
# Kullanıcının home dizininde .clapp klasörü
|
18
|
+
home_dir = Path.home()
|
19
|
+
clapp_dir = home_dir / ".clapp"
|
20
|
+
apps_dir = clapp_dir / "apps"
|
21
|
+
|
22
|
+
return str(apps_dir)
|
23
|
+
|
24
|
+
def load_app_manifest(app_path: str) -> Optional[Dict[str, Any]]:
|
25
|
+
"""Uygulama manifest'ini yükler"""
|
26
|
+
manifest_path = os.path.join(app_path, "manifest.json")
|
27
|
+
|
28
|
+
if not os.path.exists(manifest_path):
|
29
|
+
return None
|
30
|
+
|
31
|
+
try:
|
32
|
+
with open(manifest_path, 'r', encoding='utf-8') as f:
|
33
|
+
return json.load(f)
|
34
|
+
except Exception:
|
35
|
+
return None
|
36
|
+
|
37
|
+
def get_installed_apps_with_info() -> List[Dict[str, Any]]:
|
38
|
+
"""Kurulu uygulamaların detaylı bilgilerini döndürür"""
|
39
|
+
apps_dir = get_apps_directory()
|
40
|
+
apps = []
|
41
|
+
|
42
|
+
if not os.path.exists(apps_dir):
|
43
|
+
return apps
|
44
|
+
|
45
|
+
for item in os.listdir(apps_dir):
|
46
|
+
item_path = os.path.join(apps_dir, item)
|
47
|
+
|
48
|
+
if not os.path.isdir(item_path) or item.startswith('.'):
|
49
|
+
continue
|
50
|
+
|
51
|
+
manifest = load_app_manifest(item_path)
|
52
|
+
|
53
|
+
if manifest:
|
54
|
+
app_info = {
|
55
|
+
'name': manifest.get('name', item),
|
56
|
+
'version': manifest.get('version', '?'),
|
57
|
+
'language': manifest.get('language', '?'),
|
58
|
+
'description': manifest.get('description', 'Açıklama yok'),
|
59
|
+
'entry': manifest.get('entry', '?'),
|
60
|
+
'dependencies': manifest.get('dependencies', []),
|
61
|
+
'folder': item,
|
62
|
+
'path': item_path
|
63
|
+
}
|
64
|
+
else:
|
65
|
+
app_info = {
|
66
|
+
'name': item,
|
67
|
+
'version': '?',
|
68
|
+
'language': '?',
|
69
|
+
'description': 'Manifest bulunamadı',
|
70
|
+
'entry': '?',
|
71
|
+
'dependencies': [],
|
72
|
+
'folder': item,
|
73
|
+
'path': item_path
|
74
|
+
}
|
75
|
+
|
76
|
+
apps.append(app_info)
|
77
|
+
|
78
|
+
return apps
|
79
|
+
|
80
|
+
def format_table_output(apps: List[Dict[str, Any]]) -> str:
|
81
|
+
"""Uygulamaları tablo formatında formatlar"""
|
82
|
+
if not apps:
|
83
|
+
return "📭 Hiç uygulama kurulu değil."
|
84
|
+
|
85
|
+
# Başlık
|
86
|
+
output = []
|
87
|
+
output.append(f"📦 Kurulu Uygulamalar ({len(apps)})")
|
88
|
+
output.append("=" * 80)
|
89
|
+
|
90
|
+
# Sütun başlıkları
|
91
|
+
output.append(f"{'Ad':<20} {'Sürüm':<10} {'Dil':<10} {'Açıklama':<30}")
|
92
|
+
output.append("-" * 80)
|
93
|
+
|
94
|
+
# Uygulamalar
|
95
|
+
for app in sorted(apps, key=lambda x: x['name'].lower()):
|
96
|
+
name = app['name'][:19]
|
97
|
+
version = app['version'][:9]
|
98
|
+
language = app['language'][:9]
|
99
|
+
description = app['description'][:29]
|
100
|
+
|
101
|
+
output.append(f"{name:<20} {version:<10} {language:<10} {description:<30}")
|
102
|
+
|
103
|
+
return "\n".join(output)
|
104
|
+
|
105
|
+
def format_simple_output(apps: List[Dict[str, Any]]) -> str:
|
106
|
+
"""Uygulamaları basit liste formatında formatlar"""
|
107
|
+
if not apps:
|
108
|
+
return "📭 Hiç uygulama kurulu değil."
|
109
|
+
|
110
|
+
output = []
|
111
|
+
output.append(f"📦 Kurulu Uygulamalar ({len(apps)}):")
|
112
|
+
|
113
|
+
for app in sorted(apps, key=lambda x: x['name'].lower()):
|
114
|
+
name = app['name']
|
115
|
+
version = app['version']
|
116
|
+
language = app['language']
|
117
|
+
output.append(f" • {name} (v{version}) - {language}")
|
118
|
+
|
119
|
+
return "\n".join(output)
|
120
|
+
|
121
|
+
def format_json_output(apps: List[Dict[str, Any]]) -> str:
|
122
|
+
"""Uygulamaları JSON formatında formatlar"""
|
123
|
+
return json.dumps(apps, indent=2, ensure_ascii=False)
|
124
|
+
|
125
|
+
def format_detailed_output(apps: List[Dict[str, Any]]) -> str:
|
126
|
+
"""Uygulamaları detaylı formatda formatlar"""
|
127
|
+
if not apps:
|
128
|
+
return "📭 Hiç uygulama kurulu değil."
|
129
|
+
|
130
|
+
output = []
|
131
|
+
output.append(f"📦 Kurulu Uygulamalar ({len(apps)})")
|
132
|
+
output.append("=" * 60)
|
133
|
+
|
134
|
+
for i, app in enumerate(sorted(apps, key=lambda x: x['name'].lower()), 1):
|
135
|
+
output.append(f"\n{i}. {app['name']}")
|
136
|
+
output.append(f" Sürüm: {app['version']}")
|
137
|
+
output.append(f" Dil: {app['language']}")
|
138
|
+
output.append(f" Açıklama: {app['description']}")
|
139
|
+
output.append(f" Entry: {app['entry']}")
|
140
|
+
output.append(f" Klasör: {app['folder']}")
|
141
|
+
output.append(f" Yol: {app['path']}")
|
142
|
+
|
143
|
+
if app['dependencies']:
|
144
|
+
output.append(f" Bağımlılıklar: {', '.join(app['dependencies'])}")
|
145
|
+
else:
|
146
|
+
output.append(f" Bağımlılıklar: Yok")
|
147
|
+
|
148
|
+
return "\n".join(output)
|
149
|
+
|
150
|
+
def filter_apps_by_language(apps: List[Dict[str, Any]], language: str) -> List[Dict[str, Any]]:
|
151
|
+
"""Uygulamaları dile göre filtreler"""
|
152
|
+
return [app for app in apps if app['language'].lower() == language.lower()]
|
153
|
+
|
154
|
+
def filter_apps_by_name(apps: List[Dict[str, Any]], search_term: str) -> List[Dict[str, Any]]:
|
155
|
+
"""Uygulamaları isme göre filtreler"""
|
156
|
+
search_term = search_term.lower()
|
157
|
+
return [app for app in apps if search_term in app['name'].lower() or search_term in app['description'].lower()]
|
158
|
+
|
159
|
+
def list_apps(format_type: str = "table", language_filter: str = None, search_term: str = None) -> str:
|
160
|
+
"""
|
161
|
+
Ana list fonksiyonu
|
162
|
+
|
163
|
+
Args:
|
164
|
+
format_type: Çıktı formatı (table, simple, json, detailed)
|
165
|
+
language_filter: Dil filtresi (python, lua, vb.)
|
166
|
+
search_term: Arama terimi
|
167
|
+
|
168
|
+
Returns:
|
169
|
+
Formatlanmış çıktı
|
170
|
+
"""
|
171
|
+
apps = get_installed_apps_with_info()
|
172
|
+
|
173
|
+
# Filtreleri uygula
|
174
|
+
if language_filter:
|
175
|
+
apps = filter_apps_by_language(apps, language_filter)
|
176
|
+
|
177
|
+
if search_term:
|
178
|
+
apps = filter_apps_by_name(apps, search_term)
|
179
|
+
|
180
|
+
# Formatı uygula
|
181
|
+
if format_type == "json":
|
182
|
+
return format_json_output(apps)
|
183
|
+
elif format_type == "simple":
|
184
|
+
return format_simple_output(apps)
|
185
|
+
elif format_type == "detailed":
|
186
|
+
return format_detailed_output(apps)
|
187
|
+
else: # table (default)
|
188
|
+
return format_table_output(apps)
|
189
|
+
|
190
|
+
def show_help():
|
191
|
+
"""Yardım mesajını gösterir"""
|
192
|
+
help_text = """
|
193
|
+
clapp list - Kurulu uygulamaları listeler
|
194
|
+
|
195
|
+
Kullanım:
|
196
|
+
python list_command.py [seçenekler]
|
197
|
+
|
198
|
+
Seçenekler:
|
199
|
+
--format FORMAT Çıktı formatı (table, simple, json, detailed)
|
200
|
+
--language LANG Dil filtresi (python, lua, vb.)
|
201
|
+
--search TERM Arama terimi (ad veya açıklamada)
|
202
|
+
--help Bu yardım mesajını göster
|
203
|
+
|
204
|
+
Örnekler:
|
205
|
+
python list_command.py
|
206
|
+
python list_command.py --format json
|
207
|
+
python list_command.py --format simple
|
208
|
+
python list_command.py --format detailed
|
209
|
+
python list_command.py --language python
|
210
|
+
python list_command.py --search calculator
|
211
|
+
python list_command.py --language python --format detailed
|
212
|
+
"""
|
213
|
+
print(help_text.strip())
|
214
|
+
|
215
|
+
def main():
|
216
|
+
"""CLI entry point"""
|
217
|
+
# Komut satırı argümanlarını parse et
|
218
|
+
args = sys.argv[1:]
|
219
|
+
|
220
|
+
if "--help" in args or "-h" in args:
|
221
|
+
show_help()
|
222
|
+
sys.exit(0)
|
223
|
+
|
224
|
+
format_type = "table"
|
225
|
+
language_filter = None
|
226
|
+
search_term = None
|
227
|
+
|
228
|
+
i = 0
|
229
|
+
while i < len(args):
|
230
|
+
arg = args[i]
|
231
|
+
|
232
|
+
if arg == "--format" and i + 1 < len(args):
|
233
|
+
format_type = args[i + 1]
|
234
|
+
i += 2
|
235
|
+
elif arg == "--language" and i + 1 < len(args):
|
236
|
+
language_filter = args[i + 1]
|
237
|
+
i += 2
|
238
|
+
elif arg == "--search" and i + 1 < len(args):
|
239
|
+
search_term = args[i + 1]
|
240
|
+
i += 2
|
241
|
+
else:
|
242
|
+
print(f"❌ Bilinmeyen argüman: {arg}")
|
243
|
+
print("Yardım için: python list_command.py --help")
|
244
|
+
sys.exit(1)
|
245
|
+
|
246
|
+
# Format kontrolü
|
247
|
+
valid_formats = ["table", "simple", "json", "detailed"]
|
248
|
+
if format_type not in valid_formats:
|
249
|
+
print(f"❌ Geçersiz format: {format_type}")
|
250
|
+
print(f"Geçerli formatlar: {', '.join(valid_formats)}")
|
251
|
+
sys.exit(1)
|
252
|
+
|
253
|
+
# Uygulamaları listele
|
254
|
+
try:
|
255
|
+
output = list_apps(format_type, language_filter, search_term)
|
256
|
+
print(output)
|
257
|
+
except Exception as e:
|
258
|
+
print(f"❌ Hata: {e}")
|
259
|
+
sys.exit(1)
|
260
|
+
|
261
|
+
if __name__ == "__main__":
|
262
|
+
main()
|