Download scripts/baslat.py from SevdanurGenc/Text-to-SQL: direct link, hf CLI and curl.
- Browser
- Download file 12 kB
-
https://huggingface.co/SevdanurGenc/Text-to-SQL/resolve/main/scripts/baslat.py
- Command line
-
hf download hf://SevdanurGenc/Text-to-SQL/scripts/baslat.py
-
curl -L -o baslat.py https://huggingface.co/SevdanurGenc/Text-to-SQL/resolve/main/scripts/baslat.py
12 kB
| """Tablo2SQL-TR ortak başlatıcı (Windows / macOS / Linux). | |
| İşletim sistemine özel önyükleyiciler (baslat.bat, baslat.command, baslat.sh) Python'u bulur/kurar, | |
| sanal ortamı (.venv) hazırlar ve bu betiği o ortamın Python'u ile çalıştırır. Bu betik: | |
| 1. Gerekli Python paketlerini denetler; eksikse requirements.txt'den kurar | |
| 2. İsteğe bağlı bileşenleri denetler ve öneri verir (Ollama, API anahtarları) | |
| 3. Örnek belgeler eksikse üretir | |
| 4. Boş bir port bulur, arayüzü başlatır, hazır olunca tarayıcıyı açar | |
| 5. İlk çalıştırmada masaüstü kısayolu oluşturmayı önerir | |
| Seçenekler: | |
| --kontrol yalnızca denetle, arayüzü başlatma | |
| --port N belirli bir port kullan (varsayılan: 8501'den itibaren ilk boş port) | |
| --tarayici-yok tarayıcıyı otomatik açma | |
| --kisayol masaüstü kısayolu oluştur ve çık | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import importlib.util | |
| import json | |
| import os | |
| import platform | |
| import socket | |
| import subprocess | |
| import sys | |
| import time | |
| import urllib.request | |
| import webbrowser | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parent.parent | |
| REQ = ROOT / "requirements.txt" | |
| VENV = ROOT / ".venv" | |
| STATE = VENV / ".baslatici.json" if VENV.exists() else ROOT / "outputs" / ".baslatici.json" | |
| MIN_PY = (3, 10) | |
| # pip paket adı -> içe aktarma adı | |
| PACKAGES = { | |
| "pdfplumber": "pdfplumber", "camelot-py": "camelot", "beautifulsoup4": "bs4", "lxml": "lxml", | |
| "pandas": "pandas", "openpyxl": "openpyxl", "reportlab": "reportlab", "sqlglot": "sqlglot", | |
| "rapidfuzz": "rapidfuzz", "requests": "requests", "streamlit": "streamlit", | |
| "pypdfium2": "pypdfium2", "cv2 (opencv)": "cv2", | |
| } | |
| OPTIONAL = {"pytest": "pytest"} | |
| USE_COLOR = sys.stdout.isatty() and (os.name != "nt" or os.getenv("WT_SESSION") or os.getenv("TERM")) | |
| def c(code: str, s: str) -> str: | |
| return f"\033[{code}m{s}\033[0m" if USE_COLOR else s | |
| def ok(s): | |
| print(c("32", " [TAMAM] ") + s) | |
| def warn(s): | |
| print(c("33", " [UYARI] ") + s) | |
| def err(s): | |
| print(c("31", " [HATA] ") + s) | |
| def info(s): | |
| print(c("36", " [BİLGİ] ") + s) | |
| def head(s): | |
| print("\n" + c("1", s)) | |
| def load_state() -> dict: | |
| try: | |
| return json.loads(STATE.read_text(encoding="utf-8")) | |
| except Exception: | |
| return {} | |
| def save_state(d: dict): | |
| try: | |
| STATE.parent.mkdir(parents=True, exist_ok=True) | |
| STATE.write_text(json.dumps(d, ensure_ascii=False, indent=1), encoding="utf-8") | |
| except Exception: | |
| pass | |
| def ask(question: str, default: bool = True) -> bool: | |
| if not sys.stdin or not sys.stdin.isatty(): | |
| return default | |
| suffix = " [E/h] " if default else " [e/H] " | |
| try: | |
| a = input(" " + question + suffix).strip().lower() | |
| except EOFError: | |
| return default | |
| if not a: | |
| return default | |
| return a[0] in ("e", "y") | |
| # ------------------------------------------------------------------------- denetimler | |
| def check_python() -> bool: | |
| head("1) Python") | |
| v = sys.version_info | |
| in_venv = sys.prefix != getattr(sys, "base_prefix", sys.prefix) | |
| if v < MIN_PY: | |
| err(f"Python {v.major}.{v.minor} bulundu; en az {MIN_PY[0]}.{MIN_PY[1]} gerekir (3.12 önerilir).") | |
| return False | |
| ok(f"Python {v.major}.{v.minor}.{v.micro} · {platform.system()} {platform.machine()}" | |
| + (" · sanal ortam (.venv)" if in_venv else " · sistem Python'u")) | |
| if v >= (3, 14): | |
| warn("Çok yeni bir Python sürümü: bazı paketlerin hazır kurulum dosyası olmayabilir. " | |
| "Kurulum sorun çıkarırsa Python 3.12 kullanın.") | |
| return True | |
| def missing_packages() -> list[str]: | |
| return [pip for pip, mod in PACKAGES.items() if importlib.util.find_spec(mod) is None] | |
| def pip_install() -> bool: | |
| cmd = [sys.executable, "-m", "pip", "install", "--disable-pip-version-check", "-r", str(REQ)] | |
| info("Kuruluyor: " + " ".join(cmd[2:])) | |
| r = subprocess.run(cmd) | |
| return r.returncode == 0 | |
| def check_packages(auto_install: bool = True) -> bool: | |
| head("2) Python paketleri") | |
| miss = missing_packages() | |
| if not miss: | |
| ok(f"{len(PACKAGES)} gerekli paketin tamamı kurulu.") | |
| return True | |
| warn("Eksik paketler: " + ", ".join(miss)) | |
| if not auto_install: | |
| return False | |
| if not pip_install(): | |
| err("Paketler kurulamadı.") | |
| print(" Olası nedenler ve çözümler:\n" | |
| " • İnternet bağlantısı / kurum vekil sunucusu: 'pip config set global.proxy http://...'\n" | |
| " • Python sürümü çok yeni → Python 3.12 kurup .venv klasörünü silin ve tekrar başlatın\n" | |
| " • Linux'ta derleme gerekirse: sudo apt install build-essential python3-dev") | |
| return False | |
| importlib.invalidate_caches() | |
| miss = missing_packages() | |
| if miss: | |
| err("Kurulumdan sonra hâlâ eksik: " + ", ".join(miss)) | |
| return False | |
| ok("Tüm paketler kuruldu.") | |
| return True | |
| def check_optional(): | |
| head("3) İsteğe bağlı bileşenler (öneriler)") | |
| try: | |
| sys.path.insert(0, str(ROOT)) | |
| from t2s.llm import load_dotenv | |
| loaded = load_dotenv(ROOT / ".env") | |
| if loaded: | |
| ok(".env dosyasından okundu: " + ", ".join(loaded)) | |
| except Exception: # noqa: BLE001 | |
| pass | |
| keys = [k for k in ("ANTHROPIC_API_KEY", "OPENAI_API_KEY") if os.getenv(k)] | |
| if keys: | |
| ok("LLM API anahtarı bulundu: " + ", ".join(keys)) | |
| else: | |
| info("LLM API anahtarı yok → kural tabanlı arka uç kullanılır (anahtar gerekmez). " | |
| "AI için .env.example dosyasını .env olarak kopyalayıp anahtarı girin ya da anahtarı arayüzün kenar " | |
| "çubuğuna yazın; modeller otomatik listelenir.") | |
| ollama = None | |
| for name in ("ollama", "ollama.exe"): | |
| from shutil import which | |
| ollama = ollama or which(name) | |
| if not ollama and platform.system() == "Darwin" and Path("/Applications/Ollama.app").exists(): | |
| ollama = "/Applications/Ollama.app" | |
| if ollama: | |
| try: | |
| with urllib.request.urlopen("http://localhost:11434/api/tags", timeout=1.5) as r: | |
| models = [m["name"] for m in json.loads(r.read().decode()).get("models", [])] | |
| ok("Ollama çalışıyor; modeller: " + (", ".join(models) if models else "(model yok)")) | |
| if not models: | |
| info("Öneri: ollama pull qwen2.5-coder:7b") | |
| except Exception: | |
| info("Ollama kurulu ama çalışmıyor. Yerel LLM için Ollama uygulamasını açın ya da 'ollama serve' çalıştırın.") | |
| else: | |
| info("Ücretsiz yerel LLM isterseniz: Ollama → https://ollama.com/download , ardından " | |
| "'ollama pull qwen2.5-coder:7b' (≈4,7 GB, 8 GB+ RAM önerilir).") | |
| info("Taranmış (resim) PDF'ler desteklenmez; önce OCR uygulayın (ör. ocrmypdf).") | |
| def check_data(): | |
| head("4) Örnek veriler") | |
| docs = ROOT / "data" / "docs" | |
| if docs.exists() and any(docs.glob("*.pdf")): | |
| ok(f"{len(list(docs.iterdir()))} örnek belge hazır.") | |
| return True | |
| warn("Örnek belgeler yok; üretiliyor…") | |
| r = subprocess.run([sys.executable, str(ROOT / "data" / "generate_samples.py")], cwd=ROOT) | |
| if r.returncode != 0: | |
| err("Örnek belgeler üretilemedi. Arayüz yine açılır; kendi belgelerinizi yükleyebilirsiniz.") | |
| return False | |
| subprocess.run([sys.executable, str(ROOT / "benchmark" / "build_benchmark.py")], cwd=ROOT, | |
| stdout=subprocess.DEVNULL) | |
| ok("Örnek belgeler ve test kümesi üretildi.") | |
| return True | |
| def free_port(start: int = 8501, tries: int = 50) -> int: | |
| for p in range(start, start + tries): | |
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | |
| s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
| try: | |
| s.bind(("127.0.0.1", p)) | |
| return p | |
| except OSError: | |
| continue | |
| raise RuntimeError("Boş port bulunamadı.") | |
| def already_running(port: int) -> bool: | |
| try: | |
| with urllib.request.urlopen(f"http://localhost:{port}/_stcore/health", timeout=0.8) as r: | |
| return r.status == 200 | |
| except Exception: | |
| return False | |
| # ------------------------------------------------------------------------- başlatma | |
| def launch(port: int | None, open_browser: bool) -> int: | |
| head("5) Arayüz") | |
| st = load_state() | |
| last = st.get("son_port") | |
| if port is None and last and already_running(last): | |
| url = f"http://localhost:{last}" | |
| ok(f"Uygulama zaten çalışıyor: {url}") | |
| if open_browser: | |
| webbrowser.open(url) | |
| return 0 | |
| port = port or free_port() | |
| env = dict(os.environ, STREAMLIT_BROWSER_GATHER_USAGE_STATS="false", PYTHONIOENCODING="utf-8") | |
| cmd = [sys.executable, "-m", "streamlit", "run", str(ROOT / "app.py"), | |
| "--server.headless", "true", "--server.port", str(port), "--server.address", "localhost", | |
| "--browser.gatherUsageStats", "false"] | |
| log_path = ROOT / "outputs" / "arayuz.log" | |
| log_path.parent.mkdir(parents=True, exist_ok=True) | |
| log = open(log_path, "w", encoding="utf-8") | |
| proc = subprocess.Popen(cmd, cwd=ROOT, env=env, stdout=log, stderr=subprocess.STDOUT) | |
| url = f"http://localhost:{port}" | |
| info("Başlatılıyor… (ilk açılış 10-30 sn sürebilir)") | |
| t0 = time.time() | |
| while time.time() - t0 < 90: | |
| if proc.poll() is not None: | |
| log.close() | |
| err("Arayüz beklenmedik şekilde kapandı. Son satırlar:") | |
| print(" " + "\n ".join(log_path.read_text(encoding="utf-8", errors="replace").splitlines()[-15:])) | |
| return 1 | |
| if already_running(port): | |
| break | |
| time.sleep(0.5) | |
| else: | |
| warn("Sağlık kontrolü 90 sn içinde yanıt vermedi; yine de tarayıcıda deneyin.") | |
| st["son_port"] = port | |
| save_state(st) | |
| print() | |
| print(c("1;32", f" ► Tablo2SQL hazır: {url}")) | |
| print(" Bu pencereyi kapatmak veya Ctrl+C uygulamayı durdurur. Günlük: outputs/arayuz.log\n") | |
| if open_browser: | |
| webbrowser.open(url) | |
| try: | |
| return proc.wait() | |
| except KeyboardInterrupt: | |
| print("\n Durduruluyor…") | |
| proc.terminate() | |
| try: | |
| proc.wait(timeout=8) | |
| except subprocess.TimeoutExpired: | |
| proc.kill() | |
| return 0 | |
| finally: | |
| log.close() | |
| def offer_shortcut(force: bool = False): | |
| st = load_state() | |
| if not force and (st.get("kisayol_soruldu") or not (sys.stdin and sys.stdin.isatty())): | |
| return # daha önce soruldu ya da etkileşimsiz çalışma | |
| st["kisayol_soruldu"] = True | |
| save_state(st) | |
| if force or ask("Masaüstüne bir başlatma kısayolu oluşturulsun mu?"): | |
| sys.path.insert(0, str(ROOT / "scripts")) | |
| import kisayol | |
| kisayol.create() | |
| def main() -> int: | |
| ap = argparse.ArgumentParser(description="Tablo2SQL-TR başlatıcı") | |
| ap.add_argument("--kontrol", action="store_true") | |
| ap.add_argument("--port", type=int) | |
| ap.add_argument("--tarayici-yok", action="store_true") | |
| ap.add_argument("--kisayol", action="store_true") | |
| a = ap.parse_args() | |
| os.chdir(ROOT) | |
| if os.name == "nt": | |
| try: | |
| sys.stdout.reconfigure(encoding="utf-8") | |
| os.system("") # Windows konsolunda ANSI renkleri etkinleştir | |
| except Exception: | |
| pass | |
| print(c("1;34", "\n ═══ Tablo2SQL-TR · Türkçe belge tablolarını sorgula ═══")) | |
| if a.kisayol: | |
| offer_shortcut(force=True) | |
| return 0 | |
| if not check_python(): | |
| return 1 | |
| if not check_packages(auto_install=True): | |
| return 1 | |
| check_optional() | |
| check_data() | |
| if a.kontrol: | |
| head("Denetim tamamlandı.") | |
| return 0 | |
| offer_shortcut() | |
| return launch(a.port, not a.tarayici_yok) | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |