clapp-pm 1.0.17__py3-none-any.whl → 1.0.19__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.
- cache_manager.py +376 -0
- {clapp_pm-1.0.17.data → clapp_pm-1.0.19.data}/data/version.json +1 -1
- {clapp_pm-1.0.17.dist-info → clapp_pm-1.0.19.dist-info}/METADATA +1 -1
- {clapp_pm-1.0.17.dist-info → clapp_pm-1.0.19.dist-info}/RECORD +26 -13
- {clapp_pm-1.0.17.dist-info → clapp_pm-1.0.19.dist-info}/top_level.txt +7 -0
- cli_commands.py +5 -1
- docs/developer_guide.md +361 -0
- main.py +192 -0
- manifest_schema.py +20 -5
- manifest_validator.py +3 -3
- package_runner.py +134 -34
- package_signing.py +148 -0
- smart_search.py +451 -0
- templates/dart/manifest.json +11 -0
- templates/lua/manifest.json +11 -0
- templates/python/README.md +51 -0
- templates/python/main.py +55 -0
- templates/python/manifest.json +11 -0
- test-app/README.md +51 -0
- test-app/main.py +55 -0
- test-app/manifest.json +15 -0
- version.py +1 -1
- version_manager.py +351 -0
- {clapp_pm-1.0.17.dist-info → clapp_pm-1.0.19.dist-info}/WHEEL +0 -0
- {clapp_pm-1.0.17.dist-info → clapp_pm-1.0.19.dist-info}/entry_points.txt +0 -0
- {clapp_pm-1.0.17.dist-info → clapp_pm-1.0.19.dist-info}/licenses/LICENSE +0 -0
package_runner.py
CHANGED
@@ -1,9 +1,93 @@
|
|
1
1
|
import os
|
2
2
|
import json
|
3
3
|
import subprocess
|
4
|
+
from typing import Dict, Callable, Optional, Tuple
|
4
5
|
from package_registry import get_manifest
|
5
6
|
|
6
|
-
|
7
|
+
class LanguageRunner:
|
8
|
+
"""Dil çalıştırıcıları için temel sınıf"""
|
9
|
+
|
10
|
+
def __init__(self, name: str, command: str, file_extension: str = ""):
|
11
|
+
self.name = name
|
12
|
+
self.command = command
|
13
|
+
self.file_extension = file_extension
|
14
|
+
|
15
|
+
def run(self, entry_file: str, app_path: str) -> Tuple[bool, str]:
|
16
|
+
"""
|
17
|
+
Uygulamayı çalıştırır
|
18
|
+
|
19
|
+
Args:
|
20
|
+
entry_file: Giriş dosyası
|
21
|
+
app_path: Uygulama dizini
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
(success, error_message)
|
25
|
+
"""
|
26
|
+
try:
|
27
|
+
result = subprocess.run([self.command, entry_file],
|
28
|
+
cwd=app_path,
|
29
|
+
capture_output=False)
|
30
|
+
return result.returncode == 0, ""
|
31
|
+
except FileNotFoundError:
|
32
|
+
return False, f"{self.name} yüklü değil veya PATH'te bulunamadı."
|
33
|
+
except Exception as e:
|
34
|
+
return False, f"Çalıştırma hatası: {str(e)}"
|
35
|
+
|
36
|
+
def check_availability(self) -> bool:
|
37
|
+
"""Dil çalıştırıcısının sistemde mevcut olup olmadığını kontrol eder"""
|
38
|
+
try:
|
39
|
+
result = subprocess.run([self.command, "--version"],
|
40
|
+
capture_output=True,
|
41
|
+
text=True)
|
42
|
+
return result.returncode == 0
|
43
|
+
except FileNotFoundError:
|
44
|
+
return False
|
45
|
+
|
46
|
+
# Desteklenen diller için runner'lar
|
47
|
+
LANGUAGE_RUNNERS: Dict[str, LanguageRunner] = {
|
48
|
+
'python': LanguageRunner('Python', 'python', '.py'),
|
49
|
+
'lua': LanguageRunner('Lua', 'lua', '.lua'),
|
50
|
+
'dart': LanguageRunner('Dart', 'dart', '.dart'),
|
51
|
+
'go': LanguageRunner('Go', 'go', '.go'),
|
52
|
+
'rust': LanguageRunner('Rust', 'cargo', '.rs'),
|
53
|
+
'node': LanguageRunner('Node.js', 'node', '.js'),
|
54
|
+
'bash': LanguageRunner('Bash', 'bash', '.sh'),
|
55
|
+
'perl': LanguageRunner('Perl', 'perl', '.pl'),
|
56
|
+
'ruby': LanguageRunner('Ruby', 'ruby', '.rb'),
|
57
|
+
'php': LanguageRunner('PHP', 'php', '.php')
|
58
|
+
}
|
59
|
+
|
60
|
+
def get_runner_for_language(language: str) -> Optional[LanguageRunner]:
|
61
|
+
"""
|
62
|
+
Dile göre runner döndürür
|
63
|
+
|
64
|
+
Args:
|
65
|
+
language: Programlama dili
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
LanguageRunner veya None
|
69
|
+
"""
|
70
|
+
return LANGUAGE_RUNNERS.get(language.lower())
|
71
|
+
|
72
|
+
def add_language_support(name: str, command: str, file_extension: str = "") -> bool:
|
73
|
+
"""
|
74
|
+
Yeni dil desteği ekler
|
75
|
+
|
76
|
+
Args:
|
77
|
+
name: Dil adı
|
78
|
+
command: Çalıştırma komutu
|
79
|
+
file_extension: Dosya uzantısı
|
80
|
+
|
81
|
+
Returns:
|
82
|
+
Başarılı ise True
|
83
|
+
"""
|
84
|
+
try:
|
85
|
+
LANGUAGE_RUNNERS[name.lower()] = LanguageRunner(name, command, file_extension)
|
86
|
+
return True
|
87
|
+
except Exception:
|
88
|
+
return False
|
89
|
+
|
90
|
+
def run_app(app_name: str) -> bool:
|
7
91
|
"""
|
8
92
|
Belirtilen uygulamayı çalıştırır.
|
9
93
|
|
@@ -32,49 +116,33 @@ def run_app(app_name):
|
|
32
116
|
print(f"Hata: Giriş dosyası '{entry_file}' bulunamadı.")
|
33
117
|
return False
|
34
118
|
|
35
|
-
# Dile göre
|
119
|
+
# Dile göre runner al
|
36
120
|
language = manifest['language'].lower()
|
121
|
+
runner = get_runner_for_language(language)
|
37
122
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
result = subprocess.run(['python', entry_file],
|
42
|
-
cwd=app_path,
|
43
|
-
capture_output=False)
|
44
|
-
return result.returncode == 0
|
45
|
-
|
46
|
-
elif language == 'lua':
|
47
|
-
# Lua uygulamasını çalıştır
|
48
|
-
result = subprocess.run(['lua', entry_file],
|
49
|
-
cwd=app_path,
|
50
|
-
capture_output=False)
|
51
|
-
return result.returncode == 0
|
52
|
-
|
53
|
-
else:
|
54
|
-
print(f"Hata: Desteklenmeyen dil '{language}'. Desteklenen diller: python, lua")
|
55
|
-
return False
|
56
|
-
|
57
|
-
except FileNotFoundError as e:
|
58
|
-
if language == 'python':
|
59
|
-
print("Hata: Python yüklü değil veya PATH'te bulunamadı.")
|
60
|
-
elif language == 'lua':
|
61
|
-
print("Hata: Lua yüklü değil veya PATH'te bulunamadı.")
|
62
|
-
return False
|
63
|
-
|
64
|
-
except Exception as e:
|
65
|
-
print(f"Hata: Uygulama çalıştırılırken bir hata oluştu: {e}")
|
123
|
+
if not runner:
|
124
|
+
supported = ', '.join(LANGUAGE_RUNNERS.keys())
|
125
|
+
print(f"Hata: Desteklenmeyen dil '{language}'. Desteklenen diller: {supported}")
|
66
126
|
return False
|
127
|
+
|
128
|
+
# Uygulamayı çalıştır
|
129
|
+
success, error_msg = runner.run(entry_file, app_path)
|
130
|
+
|
131
|
+
if not success and error_msg:
|
132
|
+
print(f"Hata: {error_msg}")
|
133
|
+
|
134
|
+
return success
|
67
135
|
|
68
|
-
def get_supported_languages():
|
136
|
+
def get_supported_languages() -> list:
|
69
137
|
"""
|
70
138
|
Desteklenen programlama dillerinin listesini döndürür.
|
71
139
|
|
72
140
|
Returns:
|
73
141
|
list: Desteklenen diller listesi
|
74
142
|
"""
|
75
|
-
return
|
143
|
+
return list(LANGUAGE_RUNNERS.keys())
|
76
144
|
|
77
|
-
def check_language_support(language):
|
145
|
+
def check_language_support(language: str) -> bool:
|
78
146
|
"""
|
79
147
|
Belirtilen dilin desteklenip desteklenmediğini kontrol eder.
|
80
148
|
|
@@ -84,4 +152,36 @@ def check_language_support(language):
|
|
84
152
|
Returns:
|
85
153
|
bool: Dil destekleniyorsa True, değilse False
|
86
154
|
"""
|
87
|
-
return language.lower() in
|
155
|
+
return language.lower() in LANGUAGE_RUNNERS
|
156
|
+
|
157
|
+
def check_language_availability(language: str) -> bool:
|
158
|
+
"""
|
159
|
+
Belirtilen dilin sistemde mevcut olup olmadığını kontrol eder.
|
160
|
+
|
161
|
+
Args:
|
162
|
+
language (str): Kontrol edilecek dil
|
163
|
+
|
164
|
+
Returns:
|
165
|
+
bool: Dil mevcutsa True, değilse False
|
166
|
+
"""
|
167
|
+
runner = get_runner_for_language(language)
|
168
|
+
if not runner:
|
169
|
+
return False
|
170
|
+
return runner.check_availability()
|
171
|
+
|
172
|
+
def get_language_status_report() -> str:
|
173
|
+
"""
|
174
|
+
Tüm desteklenen dillerin durum raporunu döndürür.
|
175
|
+
|
176
|
+
Returns:
|
177
|
+
str: Formatlanmış durum raporu
|
178
|
+
"""
|
179
|
+
report = "🌐 Desteklenen Diller Durumu\n"
|
180
|
+
report += "=" * 40 + "\n\n"
|
181
|
+
|
182
|
+
for lang_name, runner in LANGUAGE_RUNNERS.items():
|
183
|
+
available = runner.check_availability()
|
184
|
+
status = "✅ Mevcut" if available else "❌ Mevcut Değil"
|
185
|
+
report += f"{lang_name.title():<12} : {status}\n"
|
186
|
+
|
187
|
+
return report
|
package_signing.py
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
package_signing.py - Paket İmzalama ve Doğrulama Sistemi
|
4
|
+
|
5
|
+
Bu modül clapp paketlerinin güvenliğini sağlamak için:
|
6
|
+
- Paket imzalama
|
7
|
+
- İmza doğrulama
|
8
|
+
- Checksum hesaplama
|
9
|
+
- Güvenlik kontrolü
|
10
|
+
"""
|
11
|
+
|
12
|
+
import os
|
13
|
+
import json
|
14
|
+
import hashlib
|
15
|
+
import base64
|
16
|
+
import zipfile
|
17
|
+
from typing import Dict, Tuple, Optional, Any
|
18
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
19
|
+
from cryptography.hazmat.primitives.asymmetric import rsa, padding
|
20
|
+
from cryptography.hazmat.backends import default_backend
|
21
|
+
|
22
|
+
|
23
|
+
class PackageSigner:
|
24
|
+
"""Paket bütünlüğü ve checksum sınıfı (imzalama geçici olarak devre dışı)"""
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
pass
|
28
|
+
|
29
|
+
def calculate_checksum(self, file_path: str) -> str:
|
30
|
+
"""
|
31
|
+
Dosyanın SHA-256 checksum'unu hesaplar
|
32
|
+
|
33
|
+
Args:
|
34
|
+
file_path: Dosya yolu
|
35
|
+
|
36
|
+
Returns:
|
37
|
+
SHA-256 hash (hex formatında)
|
38
|
+
"""
|
39
|
+
sha256_hash = hashlib.sha256()
|
40
|
+
|
41
|
+
with open(file_path, "rb") as f:
|
42
|
+
for chunk in iter(lambda: f.read(4096), b""):
|
43
|
+
sha256_hash.update(chunk)
|
44
|
+
|
45
|
+
return sha256_hash.hexdigest()
|
46
|
+
|
47
|
+
def calculate_package_checksum(self, package_path: str) -> Dict[str, str]:
|
48
|
+
"""
|
49
|
+
Paket içindeki tüm dosyaların checksum'unu hesaplar
|
50
|
+
|
51
|
+
Args:
|
52
|
+
package_path: Paket dosyası yolu (.zip)
|
53
|
+
|
54
|
+
Returns:
|
55
|
+
Dosya yolları ve checksum'ları
|
56
|
+
"""
|
57
|
+
checksums = {}
|
58
|
+
|
59
|
+
with zipfile.ZipFile(package_path, 'r') as zip_file:
|
60
|
+
for file_info in zip_file.filelist:
|
61
|
+
if not file_info.is_dir():
|
62
|
+
file_data = zip_file.read(file_info.filename)
|
63
|
+
checksum = hashlib.sha256(file_data).hexdigest()
|
64
|
+
checksums[file_info.filename] = checksum
|
65
|
+
|
66
|
+
return checksums
|
67
|
+
|
68
|
+
def _extract_manifest_data(self, package_path: str) -> Optional[Dict]:
|
69
|
+
"""Paket içinden manifest verilerini çıkarır"""
|
70
|
+
try:
|
71
|
+
with zipfile.ZipFile(package_path, 'r') as zip_file:
|
72
|
+
# packages/ klasörü altındaki manifest.json'u ara
|
73
|
+
for file_info in zip_file.filelist:
|
74
|
+
if file_info.filename.endswith('manifest.json'):
|
75
|
+
manifest_data = zip_file.read(file_info.filename)
|
76
|
+
return json.loads(manifest_data.decode('utf-8'))
|
77
|
+
|
78
|
+
# Doğrudan manifest.json'u ara
|
79
|
+
if 'manifest.json' in zip_file.namelist():
|
80
|
+
manifest_data = zip_file.read('manifest.json')
|
81
|
+
return json.loads(manifest_data.decode('utf-8'))
|
82
|
+
|
83
|
+
return None
|
84
|
+
except Exception:
|
85
|
+
return None
|
86
|
+
|
87
|
+
def verify_package_integrity(self, package_path: str) -> Tuple[bool, str]:
|
88
|
+
"""
|
89
|
+
Paket bütünlüğünü kontrol eder
|
90
|
+
|
91
|
+
Args:
|
92
|
+
package_path: Paket dosyası yolu
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
(is_valid, message)
|
96
|
+
"""
|
97
|
+
try:
|
98
|
+
# ZIP dosyası geçerliliğini kontrol et
|
99
|
+
with zipfile.ZipFile(package_path, 'r') as zip_file:
|
100
|
+
# Dosya listesini kontrol et
|
101
|
+
file_list = zip_file.namelist()
|
102
|
+
|
103
|
+
# Manifest dosyası var mı?
|
104
|
+
has_manifest = any(
|
105
|
+
f.endswith('manifest.json')
|
106
|
+
for f in file_list
|
107
|
+
)
|
108
|
+
if not has_manifest:
|
109
|
+
return False, "Manifest dosyası bulunamadı"
|
110
|
+
|
111
|
+
# Dosyaları test et
|
112
|
+
zip_file.testzip()
|
113
|
+
|
114
|
+
return True, "Paket bütünlüğü doğrulandı"
|
115
|
+
|
116
|
+
except zipfile.BadZipFile:
|
117
|
+
return False, "Geçersiz ZIP dosyası"
|
118
|
+
except Exception as e:
|
119
|
+
return False, f"Bütünlük kontrolü hatası: {str(e)}"
|
120
|
+
|
121
|
+
|
122
|
+
def check_package_security(package_path: str) -> Dict[str, Any]:
|
123
|
+
"""Paket güvenlik kontrolü yapar (imza kontrolü geçici olarak devre dışı)"""
|
124
|
+
signer = PackageSigner()
|
125
|
+
|
126
|
+
results = {
|
127
|
+
"integrity": False,
|
128
|
+
"signature": None,
|
129
|
+
"checksum": "",
|
130
|
+
"warnings": []
|
131
|
+
}
|
132
|
+
|
133
|
+
# Bütünlük kontrolü
|
134
|
+
integrity_valid, integrity_msg = signer.verify_package_integrity(
|
135
|
+
package_path
|
136
|
+
)
|
137
|
+
results["integrity"] = integrity_valid
|
138
|
+
|
139
|
+
if not integrity_valid:
|
140
|
+
results["warnings"].append(f"Bütünlük hatası: {integrity_msg}")
|
141
|
+
|
142
|
+
# Checksum hesapla
|
143
|
+
results["checksum"] = signer.calculate_checksum(package_path)
|
144
|
+
|
145
|
+
# İmza kontrolü kaldırıldı
|
146
|
+
results["signature"] = None
|
147
|
+
|
148
|
+
return results
|