Roudrigus commited on
Commit
a7cdbad
·
verified ·
1 Parent(s): 8e8f7d8

Update banco.py

Browse files
Files changed (1) hide show
  1. banco.py +47 -14
banco.py CHANGED
@@ -5,6 +5,7 @@ Compatível com:
5
  - Roteamento por ambiente (db_router.py): produção/teste/treinamento
6
  - Fallback: um único DATABASE_URL vindo de env/Secrets
7
  - Postgres / MySQL / SQLite (c/ alias de case para load.db no Linux)
 
8
  """
9
 
10
  import os
@@ -20,7 +21,7 @@ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
20
  load_dotenv()
21
 
22
  # =========================================================
23
- # 1) Correção de case para SQLite (Load.db → load.db)
24
  # =========================================================
25
  def _ensure_sqlite_case_alias() -> str:
26
  """
@@ -47,10 +48,42 @@ def _ensure_sqlite_case_alias() -> str:
47
 
48
 
49
  # =========================================================
50
- # 2) Suporte a roteador (db_router.py) opcional
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  # =========================================================
52
  # Se existir um roteador, delegamos a criação da engine e da SessionLocal
53
- # conforme o "banco atual" selecionado (ex.: prod/test).
54
  try:
55
  from db_router import (
56
  get_engine as _router_get_engine,
@@ -61,8 +94,9 @@ try:
61
  except Exception:
62
  _HAS_ROUTER = False
63
 
 
64
  # =========================================================
65
- # 3) Fallback quando NÃO há roteador: construir a URI
66
  # =========================================================
67
  def _build_fallback_uri() -> str:
68
  """
@@ -72,12 +106,13 @@ def _build_fallback_uri() -> str:
72
  2. Variáveis separadas: DB_DRIVER, DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME
73
  3. SQLite local em 'load.db'
74
  """
75
- # 3.1 DATABASE_URL completo
76
  url = os.getenv("DATABASE_URL")
77
  if url:
78
- return url
 
79
 
80
- # 3.2 Campos separados
81
  driver = (os.getenv("DB_DRIVER") or "").strip().lower() # "postgresql", "mysql"
82
  host = os.getenv("DB_HOST")
83
  port = os.getenv("DB_PORT")
@@ -95,13 +130,13 @@ def _build_fallback_uri() -> str:
95
  elif driver.startswith("mysql"): # MySQL/MariaDB
96
  return f"mysql+pymysql://{user}:{pwd}@{host}:{port}/{name}"
97
 
98
- # 3.3 SQLite local (fallback)
99
  sqlite_path = _ensure_sqlite_case_alias()
100
- return f"sqlite:///{sqlite_path}"
101
 
102
 
103
  # =========================================================
104
- # 4) Engine / SessionLocal
105
  # =========================================================
106
  # Observação importante:
107
  # - Se houver db_router, usamos as fábricas do roteador (engine/sessões por ambiente).
@@ -132,7 +167,6 @@ else:
132
  engine_args = {
133
  "echo": False, # defina True para depuração de SQL
134
  "pool_pre_ping": True, # valida conexões antes de usar
135
- # "future": True, # opcional (SQLAlchemy 2.x APIs)
136
  }
137
 
138
  if DATABASE_URL.startswith("sqlite"):
@@ -162,7 +196,7 @@ else:
162
 
163
 
164
  # =========================================================
165
- # 5) Expor 'engine' e Base ORM
166
  # =========================================================
167
  # Atenção: 'engine' é resolvido no momento da importação.
168
  # Se você troca de banco após importar 'banco', prefira usar get_engine()
@@ -172,7 +206,7 @@ Base = declarative_base()
172
 
173
 
174
  # =========================================================
175
- # 6) Utilitários (opcionais)
176
  # =========================================================
177
  def init_schema():
178
  """
@@ -202,7 +236,6 @@ def db_info() -> dict:
202
  try:
203
  url = str(eng.url)
204
  except Exception:
205
- # Quando sem roteador, se falhar, tenta DATABASE_URL/DB_* do fallback
206
  try:
207
  url = DATABASE_URL # type: ignore[name-defined]
208
  except Exception:
 
5
  - Roteamento por ambiente (db_router.py): produção/teste/treinamento
6
  - Fallback: um único DATABASE_URL vindo de env/Secrets
7
  - Postgres / MySQL / SQLite (c/ alias de case para load.db no Linux)
8
+ - Garantia de criação do diretório pai do SQLite (evita 'unable to open database file')
9
  """
10
 
11
  import os
 
21
  load_dotenv()
22
 
23
  # =========================================================
24
+ # 1) Correção de case para SQLite (Load.db → load.db) — opcional
25
  # =========================================================
26
  def _ensure_sqlite_case_alias() -> str:
27
  """
 
48
 
49
 
50
  # =========================================================
51
+ # 2) Helper: garantir diretório pai do arquivo SQLite
52
+ # =========================================================
53
+ def _ensure_parent_dir_sqlite(sqlite_url: str) -> str:
54
+ """
55
+ Garante que o diretório pai do arquivo SQLite exista.
56
+ Caso não consiga criar (permissão), cai para ~/.ioirun/<arquivo>.db
57
+ Retorna a URL (que pode ser ajustada para fallback).
58
+ """
59
+ if not sqlite_url or not sqlite_url.startswith("sqlite"):
60
+ return sqlite_url
61
+
62
+ # Extrai caminho do arquivo a partir da URL
63
+ # Formatos: sqlite:///relativo.db | sqlite:////abs/path/to.db
64
+ path = sqlite_url.replace("sqlite:///", "", 1)
65
+ # se vier com // (pouco comum), normaliza
66
+ if path.startswith("//"):
67
+ path = path[1:]
68
+ file_path = os.path.abspath(path)
69
+ parent = os.path.dirname(file_path)
70
+
71
+ try:
72
+ os.makedirs(parent, exist_ok=True)
73
+ return sqlite_url
74
+ except Exception:
75
+ # fallback para HOME (gravável no Spaces)
76
+ home_dir = os.path.join(os.path.expanduser("~"), ".ioirun")
77
+ os.makedirs(home_dir, exist_ok=True)
78
+ alt = os.path.join(home_dir, os.path.basename(file_path))
79
+ return f"sqlite:///{alt}"
80
+
81
+
82
+ # =========================================================
83
+ # 3) Suporte a roteador (db_router.py) — opcional
84
  # =========================================================
85
  # Se existir um roteador, delegamos a criação da engine e da SessionLocal
86
+ # conforme o "banco atual" selecionado (ex.: prod/test/treinamento).
87
  try:
88
  from db_router import (
89
  get_engine as _router_get_engine,
 
94
  except Exception:
95
  _HAS_ROUTER = False
96
 
97
+
98
  # =========================================================
99
+ # 4) Fallback quando NÃO há roteador: construir a URI
100
  # =========================================================
101
  def _build_fallback_uri() -> str:
102
  """
 
106
  2. Variáveis separadas: DB_DRIVER, DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME
107
  3. SQLite local em 'load.db'
108
  """
109
+ # 4.1 DATABASE_URL completo
110
  url = os.getenv("DATABASE_URL")
111
  if url:
112
+ # Garante diretório pai no caso de sqlite
113
+ return _ensure_parent_dir_sqlite(url)
114
 
115
+ # 4.2 Campos separados
116
  driver = (os.getenv("DB_DRIVER") or "").strip().lower() # "postgresql", "mysql"
117
  host = os.getenv("DB_HOST")
118
  port = os.getenv("DB_PORT")
 
130
  elif driver.startswith("mysql"): # MySQL/MariaDB
131
  return f"mysql+pymysql://{user}:{pwd}@{host}:{port}/{name}"
132
 
133
+ # 4.3 SQLite local (fallback)
134
  sqlite_path = _ensure_sqlite_case_alias()
135
+ return _ensure_parent_dir_sqlite(f"sqlite:///{sqlite_path}")
136
 
137
 
138
  # =========================================================
139
+ # 5) Engine / SessionLocal
140
  # =========================================================
141
  # Observação importante:
142
  # - Se houver db_router, usamos as fábricas do roteador (engine/sessões por ambiente).
 
167
  engine_args = {
168
  "echo": False, # defina True para depuração de SQL
169
  "pool_pre_ping": True, # valida conexões antes de usar
 
170
  }
171
 
172
  if DATABASE_URL.startswith("sqlite"):
 
196
 
197
 
198
  # =========================================================
199
+ # 6) Expor 'engine' e Base ORM
200
  # =========================================================
201
  # Atenção: 'engine' é resolvido no momento da importação.
202
  # Se você troca de banco após importar 'banco', prefira usar get_engine()
 
206
 
207
 
208
  # =========================================================
209
+ # 7) Utilitários (opcionais)
210
  # =========================================================
211
  def init_schema():
212
  """
 
236
  try:
237
  url = str(eng.url)
238
  except Exception:
 
239
  try:
240
  url = DATABASE_URL # type: ignore[name-defined]
241
  except Exception: