clapp-pm 1.0.17__tar.gz → 1.0.18__tar.gz

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.
Files changed (91) hide show
  1. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/PKG-INFO +1 -1
  2. clapp_pm-1.0.18/cache_manager.py +376 -0
  3. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp_pm.egg-info/SOURCES.txt +8 -0
  4. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp_pm.egg-info/top_level.txt +4 -0
  5. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/main.py +183 -0
  6. clapp_pm-1.0.18/package_signing.py +370 -0
  7. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/requirements.txt +7 -1
  8. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/setup.py +4 -0
  9. clapp_pm-1.0.18/smart_search.py +451 -0
  10. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/version.json +1 -1
  11. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/version.py +1 -1
  12. clapp_pm-1.0.18/version_manager.py +351 -0
  13. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/CHANGELOG.md +0 -0
  14. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/GITHUB_SETUP.md +0 -0
  15. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/LICENSE +0 -0
  16. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/MANIFEST.in +0 -0
  17. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/PYPI_UPLOAD.md +0 -0
  18. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/README.md +0 -0
  19. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/advanced_test.py +0 -0
  20. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/build_index.py +0 -0
  21. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/check_env.py +0 -0
  22. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/clapp_core.py +0 -0
  23. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/clean_command.py +0 -0
  24. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/cli_commands.py +0 -0
  25. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/dependency_resolver.py +0 -0
  26. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/doctor_command.py +0 -0
  27. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/info_command.py +0 -0
  28. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/install_command.py +0 -0
  29. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/installer.py +0 -0
  30. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/list_command.py +0 -0
  31. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/main.py +0 -0
  32. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/manifest_schema.py +0 -0
  33. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/manifest_validator.py +0 -0
  34. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/package_registry.py +0 -0
  35. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/package_runner.py +0 -0
  36. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/post_install_hint.py +0 -0
  37. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/publish_command.py +0 -0
  38. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/remote_registry.py +0 -0
  39. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/setup.py +0 -0
  40. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/system_test.py +0 -0
  41. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/uninstall_command.py +0 -0
  42. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/validate_command.py +0 -0
  43. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/version.py +0 -0
  44. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/version_command.py +0 -0
  45. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/backup_current/where_command.py +0 -0
  46. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/build_index.py +0 -0
  47. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/check_env.py +0 -0
  48. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/README.md +0 -0
  49. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/index.json +0 -0
  50. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/packages/hello-python/main.py +0 -0
  51. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/packages/hello-python/manifest.json +0 -0
  52. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/packages/test-app/main.py +0 -0
  53. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/packages/test-app/manifest.json +0 -0
  54. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/packages/test-app2/main.py +0 -0
  55. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/packages/test-app2/manifest.json +0 -0
  56. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp-packages-repo/packages.json +0 -0
  57. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp_app_structure.md +0 -0
  58. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp_core.py +0 -0
  59. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp_pm.egg-info/dependency_links.txt +0 -0
  60. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp_pm.egg-info/entry_points.txt +0 -0
  61. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clapp_pm.egg-info/requires.txt +0 -0
  62. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/clean_command.py +0 -0
  63. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/cli_commands.py +0 -0
  64. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/dependency_resolver.py +0 -0
  65. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/deploy.py +0 -0
  66. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/doctor_command.py +0 -0
  67. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/index.json +0 -0
  68. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/info_command.py +0 -0
  69. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/install_command.py +0 -0
  70. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/installer.py +0 -0
  71. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/list_command.py +0 -0
  72. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/manifest_schema.py +0 -0
  73. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/manifest_validator.py +0 -0
  74. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/package_registry.py +0 -0
  75. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/package_runner.py +0 -0
  76. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/packages/hello-python/main.py +0 -0
  77. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/packages/hello-python/manifest.json +0 -0
  78. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/packages/test-app/main.py +0 -0
  79. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/packages/test-app/manifest.json +0 -0
  80. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/packages/test-app2/main.py +0 -0
  81. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/packages/test-app2/manifest.json +0 -0
  82. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/post_install_hint.py +0 -0
  83. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/publish_command.py +0 -0
  84. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/pyproject.toml +0 -0
  85. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/remote_registry.py +0 -0
  86. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/setup.cfg +0 -0
  87. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/system_test.py +0 -0
  88. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/uninstall_command.py +0 -0
  89. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/validate_command.py +0 -0
  90. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/version_command.py +0 -0
  91. {clapp_pm-1.0.17 → clapp_pm-1.0.18}/where_command.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clapp-pm
3
- Version: 1.0.17
3
+ Version: 1.0.18
4
4
  Summary: Lightweight cross-language app manager for Python and Lua
5
5
  Home-page: https://github.com/mburakmmm/clapp
6
6
  Author: Melih Burak Memiş
@@ -0,0 +1,376 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ cache_manager.py - Performans Optimizasyonu ve Önbellekleme Sistemi
4
+
5
+ Bu modül clapp'in performansını artırmak için:
6
+ - Paket meta verilerini önbellekleme
7
+ - Registry verilerini önbellekleme
8
+ - Dosya checksum'larını önbellekleme
9
+ - Akıllı cache yönetimi
10
+ - Paralel indirme desteği
11
+ """
12
+
13
+ import os
14
+ import json
15
+ import hashlib
16
+ import pickle
17
+ import threading
18
+ import time
19
+ from pathlib import Path
20
+ from typing import Dict, Any, Optional, List, Tuple
21
+ from datetime import datetime, timedelta
22
+ import concurrent.futures
23
+ import requests
24
+ from functools import wraps
25
+
26
+ class CacheManager:
27
+ """Akıllı önbellekleme yöneticisi"""
28
+
29
+ def __init__(self, cache_dir: Optional[str] = None):
30
+ """
31
+ CacheManager başlatıcısı
32
+
33
+ Args:
34
+ cache_dir: Cache dizini (varsayılan: ~/.clapp/cache)
35
+ """
36
+ if cache_dir is None:
37
+ cache_dir = os.path.join(os.path.expanduser("~"), ".clapp", "cache")
38
+
39
+ self.cache_dir = Path(cache_dir)
40
+ self.cache_dir.mkdir(parents=True, exist_ok=True)
41
+
42
+ # Cache türleri
43
+ self.metadata_cache = self.cache_dir / "metadata"
44
+ self.registry_cache = self.cache_dir / "registry"
45
+ self.checksum_cache = self.cache_dir / "checksums"
46
+ self.download_cache = self.cache_dir / "downloads"
47
+
48
+ # Cache dizinlerini oluştur
49
+ for cache_path in [self.metadata_cache, self.registry_cache,
50
+ self.checksum_cache, self.download_cache]:
51
+ cache_path.mkdir(exist_ok=True)
52
+
53
+ # Cache istatistikleri
54
+ self.stats = {
55
+ "hits": 0,
56
+ "misses": 0,
57
+ "evictions": 0,
58
+ "size": 0
59
+ }
60
+
61
+ # Thread-safe cache
62
+ self._lock = threading.Lock()
63
+
64
+ def _get_cache_key(self, key: str, cache_type: str = "metadata") -> Path:
65
+ """Cache anahtarı için dosya yolu oluşturur"""
66
+ if cache_type == "metadata":
67
+ return self.metadata_cache / f"{key}.json"
68
+ elif cache_type == "registry":
69
+ return self.registry_cache / f"{key}.json"
70
+ elif cache_type == "checksum":
71
+ return self.checksum_cache / f"{key}.txt"
72
+ elif cache_type == "download":
73
+ return self.download_cache / f"{key}.zip"
74
+ else:
75
+ raise ValueError(f"Geçersiz cache türü: {cache_type}")
76
+
77
+ def get(self, key: str, cache_type: str = "metadata", max_age: int = 3600) -> Optional[Any]:
78
+ """
79
+ Cache'den veri alır
80
+
81
+ Args:
82
+ key: Cache anahtarı
83
+ cache_type: Cache türü
84
+ max_age: Maksimum yaş (saniye)
85
+
86
+ Returns:
87
+ Cache'lenmiş veri veya None
88
+ """
89
+ cache_file = self._get_cache_key(key, cache_type)
90
+
91
+ if not cache_file.exists():
92
+ self.stats["misses"] += 1
93
+ return None
94
+
95
+ # Dosya yaşını kontrol et
96
+ file_age = time.time() - cache_file.stat().st_mtime
97
+ if file_age > max_age:
98
+ cache_file.unlink()
99
+ self.stats["misses"] += 1
100
+ return None
101
+
102
+ try:
103
+ with self._lock:
104
+ if cache_type in ["metadata", "registry"]:
105
+ with open(cache_file, 'r', encoding='utf-8') as f:
106
+ data = json.load(f)
107
+ elif cache_type == "checksum":
108
+ with open(cache_file, 'r', encoding='utf-8') as f:
109
+ data = f.read().strip()
110
+ else:
111
+ # Binary dosyalar için pickle kullan
112
+ with open(cache_file, 'rb') as f:
113
+ data = pickle.load(f)
114
+
115
+ self.stats["hits"] += 1
116
+ return data
117
+
118
+ except Exception as e:
119
+ print(f"Cache okuma hatası: {e}")
120
+ cache_file.unlink()
121
+ self.stats["misses"] += 1
122
+ return None
123
+
124
+ def set(self, key: str, data: Any, cache_type: str = "metadata") -> bool:
125
+ """
126
+ Cache'e veri kaydeder
127
+
128
+ Args:
129
+ key: Cache anahtarı
130
+ data: Kaydedilecek veri
131
+ cache_type: Cache türü
132
+
133
+ Returns:
134
+ Başarılıysa True
135
+ """
136
+ cache_file = self._get_cache_key(key, cache_type)
137
+
138
+ try:
139
+ with self._lock:
140
+ if cache_type in ["metadata", "registry"]:
141
+ with open(cache_file, 'w', encoding='utf-8') as f:
142
+ json.dump(data, f, indent=2, ensure_ascii=False)
143
+ elif cache_type == "checksum":
144
+ with open(cache_file, 'w', encoding='utf-8') as f:
145
+ f.write(str(data))
146
+ else:
147
+ # Binary dosyalar için pickle kullan
148
+ with open(cache_file, 'wb') as f:
149
+ pickle.dump(data, f)
150
+
151
+ return True
152
+
153
+ except Exception as e:
154
+ print(f"Cache yazma hatası: {e}")
155
+ return False
156
+
157
+ def delete(self, key: str, cache_type: str = "metadata") -> bool:
158
+ """Cache'den veri siler"""
159
+ cache_file = self._get_cache_key(key, cache_type)
160
+
161
+ try:
162
+ if cache_file.exists():
163
+ cache_file.unlink()
164
+ return True
165
+ return False
166
+ except Exception:
167
+ return False
168
+
169
+ def clear(self, cache_type: Optional[str] = None) -> int:
170
+ """
171
+ Cache'i temizler
172
+
173
+ Args:
174
+ cache_type: Temizlenecek cache türü (None ise tümü)
175
+
176
+ Returns:
177
+ Silinen dosya sayısı
178
+ """
179
+ deleted_count = 0
180
+
181
+ if cache_type:
182
+ cache_path = self._get_cache_key("", cache_type).parent
183
+ if cache_path.exists():
184
+ for file in cache_path.iterdir():
185
+ if file.is_file():
186
+ file.unlink()
187
+ deleted_count += 1
188
+ else:
189
+ # Tüm cache'leri temizle
190
+ for cache_path in [self.metadata_cache, self.registry_cache,
191
+ self.checksum_cache, self.download_cache]:
192
+ if cache_path.exists():
193
+ for file in cache_path.iterdir():
194
+ if file.is_file():
195
+ file.unlink()
196
+ deleted_count += 1
197
+
198
+ return deleted_count
199
+
200
+ def get_stats(self) -> Dict[str, Any]:
201
+ """Cache istatistiklerini döndürür"""
202
+ total_size = 0
203
+
204
+ # Cache boyutunu hesapla
205
+ for cache_path in [self.metadata_cache, self.registry_cache,
206
+ self.checksum_cache, self.download_cache]:
207
+ if cache_path.exists():
208
+ for file in cache_path.iterdir():
209
+ if file.is_file():
210
+ total_size += file.stat().st_size
211
+
212
+ return {
213
+ **self.stats,
214
+ "size_bytes": total_size,
215
+ "size_mb": round(total_size / (1024 * 1024), 2),
216
+ "hit_rate": round(self.stats["hits"] / max(1, self.stats["hits"] + self.stats["misses"]) * 100, 2)
217
+ }
218
+
219
+ def calculate_checksum(self, file_path: str) -> str:
220
+ """Dosyanın SHA-256 checksum'unu hesaplar ve cache'ler"""
221
+ cache_key = hashlib.md5(file_path.encode()).hexdigest()
222
+ cached_checksum = self.get(cache_key, "checksum", max_age=86400) # 24 saat
223
+
224
+ if cached_checksum:
225
+ return cached_checksum
226
+
227
+ # Checksum hesapla
228
+ sha256_hash = hashlib.sha256()
229
+ with open(file_path, "rb") as f:
230
+ for chunk in iter(lambda: f.read(4096), b""):
231
+ sha256_hash.update(chunk)
232
+
233
+ checksum = sha256_hash.hexdigest()
234
+ self.set(cache_key, checksum, "checksum")
235
+
236
+ return checksum
237
+
238
+ def cache_package_metadata(self, package_path: str, metadata: Dict[str, Any]) -> bool:
239
+ """Paket meta verilerini cache'ler"""
240
+ cache_key = hashlib.md5(package_path.encode()).hexdigest()
241
+ return self.set(cache_key, metadata, "metadata")
242
+
243
+ def get_cached_package_metadata(self, package_path: str) -> Optional[Dict[str, Any]]:
244
+ """Cache'lenmiş paket meta verilerini alır"""
245
+ cache_key = hashlib.md5(package_path.encode()).hexdigest()
246
+ return self.get(cache_key, "metadata", max_age=3600) # 1 saat
247
+
248
+ def cache_registry_data(self, registry_url: str, data: List[Dict[str, Any]]) -> bool:
249
+ """Registry verilerini cache'ler"""
250
+ cache_key = hashlib.md5(registry_url.encode()).hexdigest()
251
+ return self.set(cache_key, data, "registry")
252
+
253
+ def get_cached_registry_data(self, registry_url: str) -> Optional[List[Dict[str, Any]]]:
254
+ """Cache'lenmiş registry verilerini alır"""
255
+ cache_key = hashlib.md5(registry_url.encode()).hexdigest()
256
+ return self.get(cache_key, "registry", max_age=1800) # 30 dakika
257
+
258
+ class ParallelDownloader:
259
+ """Paralel indirme yöneticisi"""
260
+
261
+ def __init__(self, max_workers: int = 4):
262
+ """
263
+ ParallelDownloader başlatıcısı
264
+
265
+ Args:
266
+ max_workers: Maksimum paralel işçi sayısı
267
+ """
268
+ self.max_workers = max_workers
269
+ self.session = requests.Session()
270
+ self.session.headers.update({
271
+ 'User-Agent': 'clapp-package-manager/1.0'
272
+ })
273
+
274
+ def download_file(self, url: str, destination: str) -> Tuple[bool, str]:
275
+ """Tek dosya indirir"""
276
+ try:
277
+ response = self.session.get(url, stream=True, timeout=30)
278
+ response.raise_for_status()
279
+
280
+ with open(destination, 'wb') as f:
281
+ for chunk in response.iter_content(chunk_size=8192):
282
+ f.write(chunk)
283
+
284
+ return True, f"Dosya indirildi: {destination}"
285
+
286
+ except Exception as e:
287
+ return False, f"İndirme hatası: {str(e)}"
288
+
289
+ def download_files_parallel(self, download_tasks: List[Tuple[str, str]]) -> List[Tuple[bool, str]]:
290
+ """
291
+ Birden fazla dosyayı paralel indirir
292
+
293
+ Args:
294
+ download_tasks: [(url, destination), ...] listesi
295
+
296
+ Returns:
297
+ [(success, message), ...] listesi
298
+ """
299
+ results = []
300
+
301
+ with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:
302
+ # İndirme görevlerini başlat
303
+ future_to_task = {
304
+ executor.submit(self.download_file, url, dest): (url, dest)
305
+ for url, dest in download_tasks
306
+ }
307
+
308
+ # Sonuçları topla
309
+ for future in concurrent.futures.as_completed(future_to_task):
310
+ task = future_to_task[future]
311
+ try:
312
+ result = future.result()
313
+ results.append(result)
314
+ except Exception as e:
315
+ results.append((False, f"İndirme hatası: {str(e)}"))
316
+
317
+ return results
318
+
319
+ # Cache decorator
320
+ def cached(max_age: int = 3600, cache_type: str = "metadata"):
321
+ """Cache decorator'ı"""
322
+ def decorator(func):
323
+ @wraps(func)
324
+ def wrapper(*args, **kwargs):
325
+ # Cache anahtarı oluştur
326
+ cache_key = f"{func.__name__}_{hash(str(args) + str(sorted(kwargs.items())))}"
327
+
328
+ # Cache manager oluştur
329
+ cache_manager = CacheManager()
330
+
331
+ # Cache'den kontrol et
332
+ cached_result = cache_manager.get(cache_key, cache_type, max_age)
333
+ if cached_result is not None:
334
+ return cached_result
335
+
336
+ # Fonksiyonu çalıştır
337
+ result = func(*args, **kwargs)
338
+
339
+ # Sonucu cache'le
340
+ cache_manager.set(cache_key, result, cache_type)
341
+
342
+ return result
343
+ return wrapper
344
+ return decorator
345
+
346
+ # Yardımcı fonksiyonlar
347
+ def create_cache_manager() -> CacheManager:
348
+ """Varsayılan ayarlarla CacheManager oluşturur"""
349
+ return CacheManager()
350
+
351
+ def create_parallel_downloader(max_workers: int = 4) -> ParallelDownloader:
352
+ """ParallelDownloader oluşturur"""
353
+ return ParallelDownloader(max_workers)
354
+
355
+ def get_cache_stats() -> Dict[str, Any]:
356
+ """Cache istatistiklerini alır"""
357
+ cache_manager = create_cache_manager()
358
+ return cache_manager.get_stats()
359
+
360
+ def clear_all_caches() -> int:
361
+ """Tüm cache'leri temizler"""
362
+ cache_manager = create_cache_manager()
363
+ return cache_manager.clear()
364
+
365
+ def download_packages_parallel(package_urls: List[str], destination_dir: str) -> List[Tuple[bool, str]]:
366
+ """Paketleri paralel indirir"""
367
+ downloader = create_parallel_downloader()
368
+
369
+ # İndirme görevlerini hazırla
370
+ download_tasks = []
371
+ for url in package_urls:
372
+ filename = os.path.basename(url)
373
+ destination = os.path.join(destination_dir, filename)
374
+ download_tasks.append((url, destination))
375
+
376
+ return downloader.download_files_parallel(download_tasks)
@@ -5,6 +5,7 @@ PYPI_UPLOAD.md
5
5
  README.md
6
6
  advanced_test.py
7
7
  build_index.py
8
+ cache_manager.py
8
9
  check_env.py
9
10
  clapp_app_structure.md
10
11
  clapp_core.py
@@ -23,18 +24,21 @@ manifest_schema.py
23
24
  manifest_validator.py
24
25
  package_registry.py
25
26
  package_runner.py
27
+ package_signing.py
26
28
  post_install_hint.py
27
29
  publish_command.py
28
30
  pyproject.toml
29
31
  remote_registry.py
30
32
  requirements.txt
31
33
  setup.py
34
+ smart_search.py
32
35
  system_test.py
33
36
  uninstall_command.py
34
37
  validate_command.py
35
38
  version.json
36
39
  version.py
37
40
  version_command.py
41
+ version_manager.py
38
42
  where_command.py
39
43
  ./CHANGELOG.md
40
44
  ./GITHUB_SETUP.md
@@ -42,6 +46,7 @@ where_command.py
42
46
  ./README.md
43
47
  ./advanced_test.py
44
48
  ./build_index.py
49
+ ./cache_manager.py
45
50
  ./check_env.py
46
51
  ./clapp_app_structure.md
47
52
  ./clapp_core.py
@@ -60,17 +65,20 @@ where_command.py
60
65
  ./manifest_validator.py
61
66
  ./package_registry.py
62
67
  ./package_runner.py
68
+ ./package_signing.py
63
69
  ./post_install_hint.py
64
70
  ./publish_command.py
65
71
  ./remote_registry.py
66
72
  ./requirements.txt
67
73
  ./setup.py
74
+ ./smart_search.py
68
75
  ./system_test.py
69
76
  ./uninstall_command.py
70
77
  ./validate_command.py
71
78
  ./version.json
72
79
  ./version.py
73
80
  ./version_command.py
81
+ ./version_manager.py
74
82
  ./where_command.py
75
83
  ./backup_current/build_index.py
76
84
  ./backup_current/check_env.py
@@ -1,4 +1,5 @@
1
1
  backup_current
2
+ cache_manager
2
3
  check_env
3
4
  clapp-packages-repo
4
5
  clapp_core
@@ -16,12 +17,15 @@ manifest_schema
16
17
  manifest_validator
17
18
  package_registry
18
19
  package_runner
20
+ package_signing
19
21
  packages
20
22
  post_install_hint
21
23
  publish_command
22
24
  remote_registry
25
+ smart_search
23
26
  uninstall_command
24
27
  validate_command
25
28
  version
26
29
  version_command
30
+ version_manager
27
31
  where_command
@@ -32,6 +32,12 @@ from clean_command import run_clean
32
32
  from where_command import locate_app_path, list_all_app_locations
33
33
  from version_command import print_version, print_detailed_version
34
34
 
35
+ # Yeni güvenlik ve performans modülleri
36
+ from package_signing import sign_package_file, verify_package_file, check_package_security
37
+ from version_manager import check_app_updates, get_app_latest_version, increment_app_version
38
+ from cache_manager import get_cache_stats, clear_all_caches, download_packages_parallel
39
+ from smart_search import search_packages, get_search_suggestions, get_search_analytics, clear_search_history
40
+
35
41
  # Yeni publish.cursorrules komutları
36
42
  from publish_command import publish_app
37
43
  from install_command import install_app
@@ -173,6 +179,34 @@ def main():
173
179
  version_parser.add_argument('--json', action='store_true', help='JSON formatında')
174
180
  version_parser.add_argument('--detailed', action='store_true', help='Detaylı bilgi')
175
181
 
182
+ # Güvenlik komutları
183
+ security_parser = subparsers.add_parser('security', help='Paket güvenlik işlemleri')
184
+ security_parser.add_argument('action', choices=['sign', 'verify', 'check'], help='Güvenlik işlemi')
185
+ security_parser.add_argument('package_path', help='Paket dosyası yolu')
186
+ security_parser.add_argument('--signature', help='İmza dosyası yolu (verify için)')
187
+
188
+ # Versiyon yönetimi komutları
189
+ update_parser = subparsers.add_parser('update', help='Versiyon yönetimi')
190
+ update_parser.add_argument('action', choices=['check', 'increment'], help='İşlem türü')
191
+ update_parser.add_argument('--app', help='Uygulama adı')
192
+ update_parser.add_argument('--type', choices=['major', 'minor', 'patch'], default='patch', help='Artırma tipi')
193
+
194
+ # Cache yönetimi komutları
195
+ cache_parser = subparsers.add_parser('cache', help='Cache yönetimi')
196
+ cache_parser.add_argument('action', choices=['stats', 'clear', 'download'], help='Cache işlemi')
197
+ cache_parser.add_argument('--urls', nargs='+', help='İndirilecek URL\'ler (download için)')
198
+ cache_parser.add_argument('--dest', help='Hedef dizin (download için)')
199
+
200
+ # Akıllı arama komutları
201
+ search_parser = subparsers.add_parser('search', help='Akıllı arama')
202
+ search_parser.add_argument('query', nargs='?', help='Arama sorgusu')
203
+ search_parser.add_argument('--suggestions', action='store_true', help='Arama önerileri')
204
+ search_parser.add_argument('--analytics', action='store_true', help='Arama analitikleri')
205
+ search_parser.add_argument('--clear-history', action='store_true', help='Arama geçmişini temizle')
206
+ search_parser.add_argument('--language', help='Dil filtresi')
207
+ search_parser.add_argument('--category', help='Kategori filtresi')
208
+ search_parser.add_argument('--sort', choices=['relevance', 'name', 'version', 'language'], default='relevance', help='Sıralama')
209
+
176
210
  # dependency komutu (yeni)
177
211
  dependency_parser = subparsers.add_parser('dependency', help='Bağımlılık yönetimi')
178
212
  dependency_subparsers = dependency_parser.add_subparsers(dest='dependency_command', help='Bağımlılık alt komutları')
@@ -341,6 +375,155 @@ def main():
341
375
  else:
342
376
  print("❌ Geçersiz dependency komutu")
343
377
  sys.exit(1)
378
+
379
+ elif args.command == 'security':
380
+ if args.action == 'sign':
381
+ success, message = sign_package_file(args.package_path)
382
+ if success:
383
+ print(f"✅ {message}")
384
+ else:
385
+ print(f"❌ {message}")
386
+ sys.exit(1)
387
+
388
+ elif args.action == 'verify':
389
+ signature_path = args.signature or args.package_path.replace('.zip', '.sig')
390
+ success, message = verify_package_file(args.package_path, signature_path)
391
+ print(f"{'✅' if success else '❌'} {message}")
392
+ sys.exit(0 if success else 1)
393
+
394
+ elif args.action == 'check':
395
+ results = check_package_security(args.package_path)
396
+ print("🔒 Paket Güvenlik Kontrolü")
397
+ print("=" * 40)
398
+ print(f"Bütünlük: {'✅' if results['integrity'] else '❌'}")
399
+ print(f"İmza: {'✅' if results['signature'] else '❌'}")
400
+ print(f"Checksum: {results['checksum']}")
401
+ if results['warnings']:
402
+ print("\n⚠️ Uyarılar:")
403
+ for warning in results['warnings']:
404
+ print(f" - {warning}")
405
+
406
+ elif args.command == 'update':
407
+ if args.action == 'check':
408
+ if not args.app:
409
+ print("❌ --app parametresi gerekli")
410
+ sys.exit(1)
411
+
412
+ from package_registry import get_manifest
413
+ manifest = get_manifest(args.app)
414
+ if not manifest:
415
+ print(f"❌ {args.app} uygulaması bulunamadı")
416
+ sys.exit(1)
417
+
418
+ current_version = manifest.get('version', '0.0.0')
419
+ update_info = check_app_updates(args.app, current_version)
420
+
421
+ print(f"📦 {args.app} Güncelleme Kontrolü")
422
+ print("=" * 40)
423
+ print(f"Mevcut: {update_info['current_version']}")
424
+ print(f"En son: {update_info['latest_version'] or 'Bilinmiyor'}")
425
+ print(f"Durum: {update_info['message']}")
426
+
427
+ if update_info['has_update']:
428
+ print(f"Güncelleme tipi: {update_info['update_type']}")
429
+
430
+ elif args.action == 'increment':
431
+ if not args.app:
432
+ print("❌ --app parametresi gerekli")
433
+ sys.exit(1)
434
+
435
+ from package_registry import get_manifest
436
+ manifest = get_manifest(args.app)
437
+ if not manifest:
438
+ print(f"❌ {args.app} uygulaması bulunamadı")
439
+ sys.exit(1)
440
+
441
+ current_version = manifest.get('version', '0.0.0')
442
+ new_version = increment_app_version(current_version, args.type)
443
+ print(f"📦 {args.app} versiyonu artırıldı")
444
+ print(f"Eski: {current_version} → Yeni: {new_version}")
445
+
446
+ elif args.command == 'cache':
447
+ if args.action == 'stats':
448
+ stats = get_cache_stats()
449
+ print("📊 Cache İstatistikleri")
450
+ print("=" * 30)
451
+ print(f"Hit: {stats['hits']}")
452
+ print(f"Miss: {stats['misses']}")
453
+ print(f"Hit Rate: {stats['hit_rate']}%")
454
+ print(f"Boyut: {stats['size_mb']} MB")
455
+
456
+ elif args.action == 'clear':
457
+ deleted_count = clear_all_caches()
458
+ print(f"✅ {deleted_count} cache dosyası silindi")
459
+
460
+ elif args.action == 'download':
461
+ if not args.urls or not args.dest:
462
+ print("❌ --urls ve --dest parametreleri gerekli")
463
+ sys.exit(1)
464
+
465
+ os.makedirs(args.dest, exist_ok=True)
466
+ results = download_packages_parallel(args.urls, args.dest)
467
+
468
+ print("📥 Paralel İndirme Sonuçları")
469
+ print("=" * 40)
470
+ for success, message in results:
471
+ print(f"{'✅' if success else '❌'} {message}")
472
+
473
+ elif args.command == 'search':
474
+ if args.suggestions:
475
+ from package_registry import list_packages
476
+ packages = list_packages()
477
+ suggestions = get_search_suggestions(args.query or "", packages)
478
+ print("💡 Arama Önerileri")
479
+ print("=" * 20)
480
+ for suggestion in suggestions:
481
+ print(f" • {suggestion}")
482
+
483
+ elif args.analytics:
484
+ analytics = get_search_analytics()
485
+ print("📈 Arama Analitikleri")
486
+ print("=" * 25)
487
+ print(f"Toplam arama: {analytics['total_searches']}")
488
+ print(f"Benzersiz sorgu: {analytics['unique_queries']}")
489
+ print(f"Hit rate: {round(analytics['total_searches'] / max(1, analytics['unique_queries']) * 100, 1)}%")
490
+
491
+ if analytics['most_popular']:
492
+ print("\n🔥 Popüler Aramalar:")
493
+ for query, count in analytics['most_popular']:
494
+ print(f" • {query} ({count} kez)")
495
+
496
+ elif args.clear_history:
497
+ clear_search_history()
498
+
499
+ elif args.query:
500
+ from package_registry import list_packages
501
+ packages = list_packages()
502
+
503
+ filters = {}
504
+ if args.language:
505
+ filters['language'] = args.language
506
+ if args.category:
507
+ filters['category'] = args.category
508
+ if args.sort:
509
+ filters['sort_by'] = args.sort
510
+
511
+ results = search_packages(args.query, packages, filters)
512
+
513
+ print(f"🔍 '{args.query}' için {len(results)} sonuç bulundu")
514
+ print("=" * 50)
515
+
516
+ for package in results:
517
+ score = package.get('search_score', 0)
518
+ print(f"📦 {package['name']} v{package['version']} ({package['language']})")
519
+ print(f" {package['description']}")
520
+ if score > 0:
521
+ print(f" Skor: {score:.2f}")
522
+ print()
523
+
524
+ else:
525
+ print("❌ Arama sorgusu gerekli veya --suggestions/--analytics kullanın")
526
+ sys.exit(1)
344
527
 
345
528
  except KeyboardInterrupt:
346
529
  print("\n❌ İşlem iptal edildi")