wrd 0.1.41__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.
dune/__init__.py ADDED
@@ -0,0 +1,31 @@
1
+ """
2
+ Dune - Dynamiczny procesor danych z automatycznym wykrywaniem bibliotek.
3
+
4
+ Ten moduł zapewnia narzędzia do przetwarzania danych z automatycznym wykrywaniem
5
+ i wykorzystaniem odpowiednich bibliotek w zależności od typu danych wejściowych.
6
+
7
+ Główne komponenty:
8
+ - config_generator: Generowanie konfiguracji YAML z żądań w języku naturalnym
9
+ - interactive_mapper: Interaktywne mapowanie zadań do bibliotek
10
+ - processor_engine: Główny silnik przetwarzania danych
11
+ - smart_env_manager: Zarządzanie zmiennymi środowiskowymi
12
+ - task_validator: Walidacja konfiguracji zadań
13
+ """
14
+
15
+ __version__ = "0.1.1"
16
+
17
+ # Eksport głównych klas i funkcji
18
+ from .config_generator import ConfigGenerator
19
+ from .interactive_mapper import InteractiveMapper
20
+ from .processor_engine import ProcessorEngine
21
+ from .smart_env_manager import SmartEnvManager
22
+ from .task_validator import TaskValidator
23
+
24
+ __all__ = [
25
+ 'ConfigGenerator',
26
+ 'InteractiveMapper',
27
+ 'ProcessorEngine',
28
+ 'SmartEnvManager',
29
+ 'TaskValidator',
30
+ '__version__',
31
+ ]
dune/__main__.py ADDED
@@ -0,0 +1,6 @@
1
+ def main():
2
+ """Main entry point for the dune package."""
3
+ print("Dune package is installed and working!")
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,414 @@
1
+ """
2
+ Generator konfiguracji YAML na podstawie żądań w języku naturalnym.
3
+ """
4
+
5
+ import yaml
6
+ import re
7
+ from typing import Dict, List, Any, Optional
8
+ from datetime import datetime
9
+ from loguru import logger
10
+
11
+
12
+ class ConfigGenerator:
13
+ """Generator konfiguracji zadań na podstawie NLP."""
14
+
15
+ def __init__(self, llm_analyzer=None):
16
+ self.llm_analyzer = llm_analyzer
17
+ self.templates = self._load_templates()
18
+
19
+ def _load_templates(self) -> Dict[str, Any]:
20
+ """Ładuje szablony konfiguracji dla różnych typów zadań."""
21
+ return {
22
+ "email_processing": {
23
+ "runtime": {
24
+ "python_packages": {
25
+ "required": ["imaplib2", "email-validator", "python-dotenv", "loguru"],
26
+ "optional": ["beautifulsoup4", "chardet"]
27
+ },
28
+ "environment": {
29
+ "required": ["IMAP_SERVER", "IMAP_USERNAME", "IMAP_PASSWORD"],
30
+ "optional": ["IMAP_PORT", "IMAP_USE_SSL", "OUTPUT_DIR"]
31
+ }
32
+ },
33
+ "services": {
34
+ "dependencies": [{
35
+ "name": "imap-server",
36
+ "type": "imap",
37
+ "required": True,
38
+ "connection": {
39
+ "host": "${IMAP_SERVER}",
40
+ "port": "${IMAP_PORT:-143}",
41
+ "ssl": "${IMAP_USE_SSL:-false}"
42
+ },
43
+ "health_check": {
44
+ "type": "tcp_connect",
45
+ "timeout": "10s"
46
+ }
47
+ }]
48
+ }
49
+ },
50
+
51
+ "database_processing": {
52
+ "runtime": {
53
+ "python_packages": {
54
+ "required": ["sqlalchemy", "pandas", "python-dotenv"],
55
+ "optional": ["psycopg2-binary", "pymysql", "cx_Oracle"]
56
+ },
57
+ "environment": {
58
+ "required": ["DATABASE_URL"],
59
+ "optional": ["DB_POOL_SIZE", "DB_TIMEOUT"]
60
+ }
61
+ },
62
+ "services": {
63
+ "dependencies": [{
64
+ "name": "database",
65
+ "type": "sql",
66
+ "required": True,
67
+ "connection": {
68
+ "url": "${DATABASE_URL}"
69
+ },
70
+ "health_check": {
71
+ "type": "sql_query",
72
+ "query": "SELECT 1",
73
+ "timeout": "30s"
74
+ }
75
+ }]
76
+ }
77
+ },
78
+
79
+ "file_processing": {
80
+ "runtime": {
81
+ "python_packages": {
82
+ "required": ["pandas", "openpyxl", "python-dotenv"],
83
+ "optional": ["xlrd", "chardet", "python-magic"]
84
+ },
85
+ "environment": {
86
+ "required": ["INPUT_DIR", "OUTPUT_DIR"],
87
+ "optional": ["FILE_PATTERN", "ENCODING"]
88
+ }
89
+ }
90
+ },
91
+
92
+ "web_scraping": {
93
+ "runtime": {
94
+ "python_packages": {
95
+ "required": ["requests", "beautifulsoup4", "selenium", "python-dotenv"],
96
+ "optional": ["scrapy", "lxml", "html5lib"]
97
+ },
98
+ "environment": {
99
+ "required": ["TARGET_URL"],
100
+ "optional": ["USER_AGENT", "REQUEST_DELAY", "PROXY_URL"]
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ def generate_config_from_nlp(self, natural_request: str) -> Dict[str, Any]:
107
+ """Generuje konfigurację YAML na podstawie żądania w języku naturalnym."""
108
+
109
+ logger.info("🔄 Analizowanie żądania w celu wygenerowania konfiguracji...")
110
+
111
+ # Wykryj typ zadania
112
+ task_type = self._detect_task_type(natural_request)
113
+ logger.info(f"🎯 Wykryty typ zadania: {task_type}")
114
+
115
+ # Wyodrębnij wymagania
116
+ requirements = self._extract_requirements(natural_request)
117
+
118
+ # Wykryj potrzebne pakiety
119
+ packages = self._detect_required_packages(natural_request, task_type)
120
+
121
+ # Wykryj zmienne środowiskowe
122
+ env_vars = self._detect_environment_variables(natural_request, task_type)
123
+
124
+ # Wykryj usługi
125
+ services = self._detect_services(natural_request, task_type)
126
+
127
+ # Wygeneruj podstawową konfigurację
128
+ config = self._build_base_config(
129
+ natural_request, task_type, requirements,
130
+ packages, env_vars, services
131
+ )
132
+
133
+ return config
134
+
135
+ def _detect_task_type(self, request: str) -> str:
136
+ """Wykrywa typ zadania na podstawie słów kluczowych."""
137
+
138
+ request_lower = request.lower()
139
+
140
+ # Mapa słów kluczowych do typów zadań
141
+ keywords_map = {
142
+ "email_processing": ["email", "imap", "pop3", "skrzynka", "wiadomość", "poczta"],
143
+ "database_processing": ["baza danych", "sql", "tabela", "rekord", "zapytanie"],
144
+ "file_processing": ["plik", "csv", "excel", "json", "xml", "folder"],
145
+ "web_scraping": ["strona", "scraping", "pobierz z internetu", "www", "http"],
146
+ "api_processing": ["api", "endpoint", "rest", "json api", "webhook"],
147
+ "data_analysis": ["analiza", "wykres", "statystyki", "raport", "dashboard"]
148
+ }
149
+
150
+ # Zlicz dopasowania dla każdego typu
151
+ scores = {}
152
+ for task_type, keywords in keywords_map.items():
153
+ score = sum(1 for keyword in keywords if keyword in request_lower)
154
+ if score > 0:
155
+ scores[task_type] = score
156
+
157
+ # Zwróć typ z najwyższym wynikiem
158
+ if scores:
159
+ return max(scores, key=scores.get)
160
+
161
+ return "generic_processing"
162
+
163
+ def _extract_requirements(self, request: str) -> List[str]:
164
+ """Wyodrębnia wymagania funkcjonalne z żądania."""
165
+
166
+ requirements = []
167
+ request_lower = request.lower()
168
+
169
+ # Mapa wzorców do wymagań
170
+ patterns = {
171
+ r"pobierz.*email|pobierz.*wiadomoś": "download_emails",
172
+ r"zapisz.*folder|organizuj.*folder": "organize_files",
173
+ r"połącz.*imap|łącz.*imap": "connect_imap",
174
+ r"filtruj.*dat|sortuj.*dat": "filter_by_date",
175
+ r"utwórz.*raport|generuj.*raport": "generate_report",
176
+ r"analizuj.*treść": "analyze_content",
177
+ r"wyślij.*email": "send_email",
178
+ r"pobierz.*załącznik": "download_attachments"
179
+ }
180
+
181
+ for pattern, requirement in patterns.items():
182
+ if re.search(pattern, request_lower):
183
+ requirements.append(requirement)
184
+
185
+ return requirements if requirements else ["process_data"]
186
+
187
+ def _detect_required_packages(self, request: str, task_type: str) -> Dict[str, List[str]]:
188
+ """Wykrywa wymagane pakiety Python."""
189
+
190
+ # Pobierz bazowe pakiety dla typu zadania
191
+ base_template = self.templates.get(task_type, {})
192
+ packages = base_template.get("runtime", {}).get("python_packages", {
193
+ "required": ["python-dotenv", "loguru"],
194
+ "optional": []
195
+ }).copy()
196
+
197
+ request_lower = request.lower()
198
+
199
+ # Dodatkowe pakiety na podstawie kontekstu
200
+ additional_packages = {
201
+ "pandas": ["csv", "excel", "dataframe", "tabela"],
202
+ "requests": ["http", "api", "pobierz z internetu"],
203
+ "beautifulsoup4": ["html", "scraping", "parsuj"],
204
+ "sqlalchemy": ["sql", "baza danych"],
205
+ "matplotlib": ["wykres", "chart", "plot"],
206
+ "numpy": ["obliczenia", "matematyka", "array"],
207
+ "opencv-python": ["obraz", "zdjęcie", "cv2"],
208
+ "pillow": ["pil", "image", "grafika"]
209
+ }
210
+
211
+ for package, keywords in additional_packages.items():
212
+ if any(keyword in request_lower for keyword in keywords):
213
+ if package not in packages["required"]:
214
+ packages["optional"].append(package)
215
+
216
+ return packages
217
+
218
+ def _detect_environment_variables(self, request: str, task_type: str) -> Dict[str, List[str]]:
219
+ """Wykrywa potrzebne zmienne środowiskowe."""
220
+
221
+ # Pobierz bazowe zmienne dla typu zadania
222
+ base_template = self.templates.get(task_type, {})
223
+ env_vars = base_template.get("runtime", {}).get("environment", {
224
+ "required": [],
225
+ "optional": ["OUTPUT_DIR"]
226
+ }).copy()
227
+
228
+ request_lower = request.lower()
229
+
230
+ # Dodatkowe zmienne na podstawie kontekstu
231
+ additional_vars = {
232
+ "API_KEY": ["api", "klucz", "token"],
233
+ "DATABASE_URL": ["baza danych", "sql"],
234
+ "WEBHOOK_URL": ["webhook", "callback"],
235
+ "PROXY_URL": ["proxy", "pośrednik"],
236
+ "TIMEOUT": ["timeout", "czas", "oczekiwanie"]
237
+ }
238
+
239
+ for var, keywords in additional_vars.items():
240
+ if any(keyword in request_lower for keyword in keywords):
241
+ if var not in env_vars["required"]:
242
+ env_vars["optional"].append(var)
243
+
244
+ return env_vars
245
+
246
+ def _detect_services(self, request: str, task_type: str) -> Dict[str, Any]:
247
+ """Wykrywa wymagane usługi zewnętrzne."""
248
+
249
+ # Pobierz bazowe usługi dla typu zadania
250
+ base_template = self.templates.get(task_type, {})
251
+ services = base_template.get("services", {
252
+ "dependencies": [],
253
+ "managed_services": []
254
+ }).copy()
255
+
256
+ request_lower = request.lower()
257
+
258
+ # Dodatkowe usługi na podstawie kontekstu
259
+ if "redis" in request_lower:
260
+ services["dependencies"].append({
261
+ "name": "redis",
262
+ "type": "cache",
263
+ "required": False,
264
+ "connection": {"host": "${REDIS_HOST:-localhost}", "port": "6379"},
265
+ "health_check": {"type": "tcp_connect", "timeout": "5s"}
266
+ })
267
+
268
+ if "elasticsearch" in request_lower:
269
+ services["dependencies"].append({
270
+ "name": "elasticsearch",
271
+ "type": "search",
272
+ "required": False,
273
+ "connection": {"url": "${ELASTICSEARCH_URL:-http://localhost:9200}"},
274
+ "health_check": {"type": "http_get", "endpoint": "/_cluster/health", "timeout": "10s"}
275
+ })
276
+
277
+ return services
278
+
279
+ def _build_base_config(self, request: str, task_type: str, requirements: List[str],
280
+ packages: Dict[str, List[str]], env_vars: Dict[str, List[str]],
281
+ services: Dict[str, Any]) -> Dict[str, Any]:
282
+ """Buduje podstawową konfigurację."""
283
+
284
+ # Wygeneruj nazwę zadania
285
+ task_name = self._generate_task_name(request, task_type)
286
+
287
+ config = {
288
+ "apiVersion": "dune.io/v1",
289
+ "kind": "TaskConfiguration",
290
+ "metadata": {
291
+ "name": task_name,
292
+ "description": request[:200] + "..." if len(request) > 200 else request,
293
+ "version": "1.0",
294
+ "created": datetime.now().isoformat() + "Z",
295
+ "tags": [task_type, "auto-generated"]
296
+ },
297
+ "task": {
298
+ "natural_language": request,
299
+ "requirements": requirements,
300
+ "expected_output": {
301
+ "type": "file_structure",
302
+ "pattern": "output/**/*"
303
+ }
304
+ },
305
+ "runtime": {
306
+ "type": "docker",
307
+ "base_image": "python:3.11-slim",
308
+ "python_packages": packages,
309
+ "environment": env_vars
310
+ },
311
+ "services": services,
312
+ "validation": {
313
+ "pre_execution": [
314
+ {"type": "service_connectivity",
315
+ "services": [dep["name"] for dep in services.get("dependencies", []) if dep.get("required")]},
316
+ {"type": "environment_variables", "required": env_vars.get("required", [])},
317
+ {"type": "file_permissions", "paths": ["${OUTPUT_DIR:-./output}"],
318
+ "permissions": ["read", "write"]},
319
+ {"type": "disk_space", "minimum": "100MB", "path": "${OUTPUT_DIR:-./output}"}
320
+ ],
321
+ "post_execution": [
322
+ {"type": "output_verification", "expected_files": {"pattern": "output/**/*", "minimum_count": 1}},
323
+ {"type": "directory_structure", "expected": ["output"]}
324
+ ]
325
+ },
326
+ "monitoring": {
327
+ "logs": {
328
+ "level": "${LOG_LEVEL:-INFO}",
329
+ "destinations": [
330
+ {"type": "file", "path": "logs/task-execution.log"},
331
+ {"type": "stdout", "format": "json"}
332
+ ]
333
+ },
334
+ "metrics": [
335
+ {"name": "execution_time", "type": "histogram", "description": "Czas wykonania zadania"},
336
+ {"name": "errors_count", "type": "counter", "description": "Liczba błędów"}
337
+ ]
338
+ },
339
+ "security": {
340
+ "network": {
341
+ "allowed_outbound": ["*:80", "*:443"],
342
+ "blocked_outbound": ["*:22", "*:3389"]
343
+ },
344
+ "filesystem": {
345
+ "read_only_paths": ["/etc", "/usr"],
346
+ "writable_paths": ["${OUTPUT_DIR:-./output}", "/tmp", "logs/"]
347
+ }
348
+ },
349
+ "pipeline": {
350
+ "stages": [
351
+ {"name": "validation", "type": "validation", "config": {"run_pre_execution_checks": True}},
352
+ {"name": "environment_setup", "type": "setup",
353
+ "config": {"install_packages": True, "create_directories": True}},
354
+ {"name": "llm_analysis", "type": "llm_processing",
355
+ "config": {"analyze_natural_language": True, "generate_code": True}},
356
+ {"name": "task_execution", "type": "execution",
357
+ "config": {"run_generated_code": True, "capture_output": True}},
358
+ {"name": "post_validation", "type": "validation", "config": {"run_post_execution_checks": True}},
359
+ {"name": "cleanup", "type": "cleanup", "config": {"remove_temp_files": True}}
360
+ ]
361
+ },
362
+ "environments": {
363
+ "development": {
364
+ "managed_services_enabled": True,
365
+ "log_level": "DEBUG",
366
+ "validation_strict": False
367
+ },
368
+ "testing": {
369
+ "managed_services_enabled": True,
370
+ "log_level": "INFO",
371
+ "validation_strict": True
372
+ },
373
+ "production": {
374
+ "managed_services_enabled": False,
375
+ "log_level": "WARNING",
376
+ "validation_strict": True,
377
+ "security_enhanced": True
378
+ }
379
+ }
380
+ }
381
+
382
+ return config
383
+
384
+ def _generate_task_name(self, request: str, task_type: str) -> str:
385
+ """Generuje nazwę zadania na podstawie żądania."""
386
+
387
+ # Wyciągnij kluczowe słowa
388
+ words = re.findall(r'\b\w+\b', request.lower())
389
+ key_words = [w for w in words if len(w) > 3 and w not in [
390
+ "jest", "będzie", "oraz", "które", "wszystkie", "danych"
391
+ ]][:3]
392
+
393
+ if key_words:
394
+ name = "-".join(key_words)
395
+ else:
396
+ name = task_type.replace("_", "-")
397
+
398
+ return f"{name}-processor"
399
+
400
+ def save_config_to_file(self, config: Dict[str, Any], filename: str = None) -> str:
401
+ """Zapisuje konfigurację do pliku YAML."""
402
+
403
+ if not filename:
404
+ task_name = config["metadata"]["name"]
405
+ filename = f"configs/{task_name}.yaml"
406
+
407
+ # Utwórz katalog jeśli nie istnieje
408
+ Path(filename).parent.mkdir(parents=True, exist_ok=True)
409
+
410
+ with open(filename, 'w', encoding='utf-8') as f:
411
+ yaml.dump(config, f, default_flow_style=False, allow_unicode=True, indent=2)
412
+
413
+ logger.success(f"✅ Konfiguracja zapisana do: {filename}")
414
+ return filename
dune/genconfig.py ADDED
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CLI do generowania konfiguracji zadań z żądań w języku naturalnym.
4
+ """
5
+
6
+ import sys
7
+ import argparse
8
+ from pathlib import Path
9
+ from loguru import logger
10
+
11
+ # Dodaj src do PYTHONPATH
12
+ sys.path.insert(0, str(Path(__file__).parent / "src"))
13
+
14
+ from config_generator import ConfigGenerator
15
+ from llm_analyzer import LLMAnalyzer
16
+
17
+
18
+ def main():
19
+ """Główna funkcja CLI."""
20
+
21
+ parser = argparse.ArgumentParser(
22
+ description="Generator konfiguracji dune z żądań w języku naturalnym"
23
+ )
24
+
25
+ parser.add_argument(
26
+ "request",
27
+ nargs='?',
28
+ help="Żądanie w języku naturalnym (lub zostanie pobrane interaktywnie)"
29
+ )
30
+
31
+ parser.add_argument(
32
+ "--output", "-o",
33
+ type=str,
34
+ help="Ścieżka do pliku wyjściowego (domyślnie: configs/auto-generated.yaml)"
35
+ )
36
+
37
+ parser.add_argument(
38
+ "--interactive", "-i",
39
+ action="store_true",
40
+ help="Tryb interaktywny"
41
+ )
42
+
43
+ parser.add_argument(
44
+ "--validate", "-v",
45
+ action="store_true",
46
+ help="Waliduj wygenerowaną konfigurację"
47
+ )
48
+
49
+ parser.add_argument(
50
+ "--template", "-t",
51
+ type=str,
52
+ choices=["email_processing", "database_processing", "file_processing", "web_scraping"],
53
+ help="Użyj konkretnego szablonu"
54
+ )
55
+
56
+ args = parser.parse_args()
57
+
58
+ # Konfiguruj logowanie
59
+ logger.remove()
60
+ logger.add(sys.stdout, format="<green>{time:HH:mm:ss}</green> | <level>{message}</level>")
61
+
62
+ logger.info("🔧 Generator konfiguracji dune")
63
+
64
+ # Pobierz żądanie
65
+ if args.interactive or not args.request:
66
+ print("\n" + "=" * 60)
67
+ print("🤖 GENERATOR KONFIGURACJI dune")
68
+ print("=" * 60)
69
+ print("Opisz zadanie, które chcesz wykonać w języku naturalnym.")
70
+ print("Przykłady:")
71
+ print("• Pobierz emaile z IMAP i zapisz w folderach według dat")
72
+ print("• Przeanalizuj pliki CSV i wygeneruj raport")
73
+ print("• Pobierz dane z API i zapisz do bazy danych")
74
+ print("=" * 60)
75
+
76
+ request = input("\n📝 Twoje zadanie: ")
77
+ if not request.strip():
78
+ logger.error("❌ Nie podano żądania")
79
+ return
80
+ else:
81
+ request = args.request
82
+
83
+ try:
84
+ # Inicjalizuj generator
85
+ generator = ConfigGenerator()
86
+
87
+ logger.info("🔄 Analizowanie żądania...")
88
+
89
+ # Wygeneruj konfigurację
90
+ config = generator.generate_config_from_nlp(request)
91
+
92
+ # Określ ścieżkę wyjściową
93
+ if args.output:
94
+ output_path = args.output
95
+ else:
96
+ task_name = config["metadata"]["name"]
97
+ output_path = f"configs/{task_name}.yaml"
98
+
99
+ # Zapisz konfigurację
100
+ saved_path = generator.save_config_to_file(config, output_path)
101
+
102
+ # Pokaż podsumowanie
103
+ print("\n" + "=" * 60)
104
+ print("✅ KONFIGURACJA WYGENEROWANA POMYŚLNIE!")
105
+ print("=" * 60)
106
+ print(f"📄 Plik: {saved_path}")
107
+ print(f"🎯 Zadanie: {config['metadata']['name']}")
108
+ print(f"📦 Pakiety: {len(config['runtime']['python_packages']['required'])} wymaganych")
109
+ print(f"🔧 Usługi: {len(config['services'].get('dependencies', []))} zależności")
110
+ print(f"✅ Walidacja: {len(config['validation']['pre_execution'])} sprawdzeń")
111
+
112
+ # Pokaż kluczowe informacje
113
+ print(f"\n📋 PODSUMOWANIE:")
114
+ print(f" • Typ zadania: {config['metadata']['tags'][0] if config['metadata']['tags'] else 'generic'}")
115
+ print(f" • Wymagania: {', '.join(config['task']['requirements'])}")
116
+
117
+ required_packages = config['runtime']['python_packages']['required']
118
+ if required_packages:
119
+ print(f" • Pakiety: {', '.join(required_packages)}")
120
+
121
+ required_env = config['runtime']['environment']['required']
122
+ if required_env:
123
+ print(f" • Zmienne: {', '.join(required_env)}")
124
+
125
+ print(f"\n🚀 URUCHOMIENIE:")
126
+ print(f" python enhanced_run.py --config {saved_path}")
127
+
128
+ # Walidacja (jeśli zażądano)
129
+ if args.validate:
130
+ logger.info("🔍 Walidowanie konfiguracji...")
131
+ from task_validator import TaskValidator
132
+
133
+ validator = TaskValidator()
134
+ try:
135
+ loaded_config = validator.load_config(saved_path)
136
+ logger.success("✅ Konfiguracja jest poprawna")
137
+ except Exception as e:
138
+ logger.error(f"❌ Błąd walidacji: {e}")
139
+
140
+ except Exception as e:
141
+ logger.error(f"❌ Błąd generowania konfiguracji: {e}")
142
+ sys.exit(1)
143
+
144
+
145
+ if __name__ == "__main__":
146
+ main()