D Ф m i И i q ц e L Ф y e r commited on
Commit
574de54
·
1 Parent(s): 4a8c1eb

Fix: Use Supabase REST API instead of psycopg2 for HF compatibility

Browse files
Files changed (2) hide show
  1. syscred/backend_app.py +19 -2
  2. syscred/database.py +90 -15
syscred/backend_app.py CHANGED
@@ -421,8 +421,9 @@ def verify_endpoint():
421
  print(f"[SysCRED Backend] TREC metrics error: {e}")
422
  result['trec_metrics'] = {'error': str(e)}
423
 
424
- # [NEW] Persist to Database
425
  try:
 
426
  new_analysis = AnalysisResult(
427
  url=input_data[:500],
428
  credibility_score=result.get('scoreCredibilite', 0.5),
@@ -431,7 +432,23 @@ def verify_endpoint():
431
  )
432
  db.session.add(new_analysis)
433
  db.session.commit()
434
- print(f"[SysCRED-DB] Result saved. ID: {new_analysis.id}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
435
  except Exception as e:
436
  print(f"[SysCRED-DB] Save failed: {e}")
437
 
 
421
  print(f"[SysCRED Backend] TREC metrics error: {e}")
422
  result['trec_metrics'] = {'error': str(e)}
423
 
424
+ # [NEW] Persist to Database (SQLite + Supabase REST)
425
  try:
426
+ # Save to SQLite
427
  new_analysis = AnalysisResult(
428
  url=input_data[:500],
429
  credibility_score=result.get('scoreCredibilite', 0.5),
 
432
  )
433
  db.session.add(new_analysis)
434
  db.session.commit()
435
+ print(f"[SysCRED-DB] Result saved to SQLite. ID: {new_analysis.id}")
436
+
437
+ # Also save to Supabase via REST API
438
+ try:
439
+ from syscred.database import get_supabase
440
+ supabase = get_supabase()
441
+ if supabase:
442
+ supabase.insert('analysis_results', {
443
+ 'url': input_data[:500],
444
+ 'credibility_score': result.get('scoreCredibilite', 0.5),
445
+ 'summary': result.get('resumeAnalyse', ''),
446
+ 'source_reputation': result.get('detailsScore', {}).get('factors', [{}])[0].get('value')
447
+ })
448
+ print(f"[SysCRED-DB] Result synced to Supabase")
449
+ except Exception as supabase_err:
450
+ print(f"[SysCRED-DB] Supabase sync failed: {supabase_err}")
451
+
452
  except Exception as e:
453
  print(f"[SysCRED-DB] Save failed: {e}")
454
 
syscred/database.py CHANGED
@@ -1,17 +1,95 @@
1
  # -*- coding: utf-8 -*-
2
  """
3
  Database Manager for SysCRED
4
- ===========================
5
- Handles connection to Supabase (PostgreSQL) and defines models.
6
  """
7
 
8
  import os
 
9
  from flask_sqlalchemy import SQLAlchemy
10
  from datetime import datetime
11
 
12
  # Initialize SQLAlchemy
13
  db = SQLAlchemy()
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  class AnalysisResult(db.Model):
16
  """Stores the result of a credibility analysis."""
17
  __tablename__ = 'analysis_results'
@@ -36,30 +114,27 @@ class AnalysisResult(db.Model):
36
  'source_reputation': self.source_reputation
37
  }
38
 
 
39
  def init_db(app):
40
  """Initialize the database with the Flask app."""
41
- # Prefer DATABASE_URL (direct connection), then SYSCRED_DATABASE_URL (pooler)
42
- # HF Spaces often can't resolve the pooler hostname
43
- db_url = os.environ.get('DATABASE_URL') or os.environ.get('SYSCRED_DATABASE_URL')
44
- if db_url and db_url.startswith("postgres://"):
45
- db_url = db_url.replace("postgres://", "postgresql://", 1)
46
-
47
- # Fallback to SQLite in a writable directory
48
- if not db_url:
49
- import tempfile
50
- db_path = os.path.join(tempfile.gettempdir(), 'syscred.db')
51
- db_url = f'sqlite:///{db_path}'
52
- print(f"[SysCRED-DB] No DATABASE_URL, using SQLite: {db_path}")
53
 
54
  app.config['SQLALCHEMY_DATABASE_URI'] = db_url
55
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
56
 
57
  db.init_app(app)
58
 
59
- # Create tables if they don't exist (basic migration)
60
  with app.app_context():
61
  try:
62
  db.create_all()
63
  print("[SysCRED-DB] Database tables initialized.")
64
  except Exception as e:
65
  print(f"[SysCRED-DB] Warning: create_all failed: {e}")
 
 
 
 
1
  # -*- coding: utf-8 -*-
2
  """
3
  Database Manager for SysCRED
4
+ =============================
5
+ Handles connection to Supabase using REST API (PostgREST) for HF Spaces compatibility.
6
  """
7
 
8
  import os
9
+ import requests
10
  from flask_sqlalchemy import SQLAlchemy
11
  from datetime import datetime
12
 
13
  # Initialize SQLAlchemy
14
  db = SQLAlchemy()
15
 
16
+ # Supabase REST API configuration
17
+ SUPABASE_URL = os.environ.get('SUPABASE_URL', 'https://zmluirvqfkmfazqitqgi.supabase.co')
18
+ SUPABASE_KEY = os.environ.get('SUPABASE_KEY', os.environ.get('SUPABASE_SERVICE_ROLE_KEY', ''))
19
+
20
+ class SupabaseClient:
21
+ """REST API client for Supabase (PostgREST)."""
22
+
23
+ def __init__(self):
24
+ self.url = SUPABASE_URL
25
+ self.key = SUPABASE_KEY
26
+ self.headers = {
27
+ 'apikey': self.key,
28
+ 'Authorization': f'Bearer {self.key}',
29
+ 'Content-Type': 'application/json',
30
+ 'Prefer': 'return=representation'
31
+ }
32
+
33
+ def insert(self, table, data):
34
+ """Insert a row into a table."""
35
+ try:
36
+ response = requests.post(
37
+ f"{self.url}/rest/v1/{table}",
38
+ json=data,
39
+ headers=self.headers
40
+ )
41
+ return response.status_code in [200, 201, 204]
42
+ except Exception as e:
43
+ print(f"[Supabase REST] Insert error: {e}")
44
+ return False
45
+
46
+ def select(self, table, filters=None):
47
+ """Select rows from a table."""
48
+ try:
49
+ params = filters or {}
50
+ response = requests.get(
51
+ f"{self.url}/rest/v1/{table}",
52
+ params=params,
53
+ headers=self.headers
54
+ )
55
+ if response.status_code == 200:
56
+ return response.json()
57
+ return []
58
+ except Exception as e:
59
+ print(f"[Supabase REST] Select error: {e}")
60
+ return []
61
+
62
+ def count(self, table):
63
+ """Count rows in a table."""
64
+ try:
65
+ response = requests.get(
66
+ f"{self.url}/rest/v1/{table}",
67
+ params={'select': 'count', 'count': 'exact'},
68
+ headers=self.headers
69
+ )
70
+ if response.status_code == 200:
71
+ return int(response.headers.get('Content-Range', '0-0').split('/')[-1])
72
+ return 0
73
+ except Exception as e:
74
+ print(f"[Supabase REST] Count error: {e}")
75
+ return 0
76
+
77
+
78
+ # Global Supabase client
79
+ supabase_client = None
80
+
81
+ def get_supabase():
82
+ """Get or create Supabase client."""
83
+ global supabase_client
84
+ if supabase_client is None:
85
+ if SUPABASE_KEY:
86
+ supabase_client = SupabaseClient()
87
+ print("[SysCRED-DB] Supabase REST client initialized")
88
+ else:
89
+ print("[SysCRED-DB] Warning: No SUPABASE_KEY, Supabase disabled")
90
+ return supabase_client
91
+
92
+
93
  class AnalysisResult(db.Model):
94
  """Stores the result of a credibility analysis."""
95
  __tablename__ = 'analysis_results'
 
114
  'source_reputation': self.source_reputation
115
  }
116
 
117
+
118
  def init_db(app):
119
  """Initialize the database with the Flask app."""
120
+ # Use SQLite fallback - Supabase operations use REST API separately
121
+ import tempfile
122
+ db_path = os.path.join(tempfile.gettempdir(), 'syscred.db')
123
+ db_url = f'sqlite:///{db_path}'
124
+ print(f"[SysCRED-DB] Using SQLite (Supabase uses REST API): {db_path}")
 
 
 
 
 
 
 
125
 
126
  app.config['SQLALCHEMY_DATABASE_URI'] = db_url
127
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
128
 
129
  db.init_app(app)
130
 
131
+ # Create tables
132
  with app.app_context():
133
  try:
134
  db.create_all()
135
  print("[SysCRED-DB] Database tables initialized.")
136
  except Exception as e:
137
  print(f"[SysCRED-DB] Warning: create_all failed: {e}")
138
+
139
+ # Initialize Supabase REST client
140
+ get_supabase()