Really-amin commited on
Commit
dcdf7c1
·
verified ·
1 Parent(s): a7524fd

Update setup.py

Browse files
Files changed (1) hide show
  1. setup.py +174 -728
setup.py CHANGED
@@ -1,776 +1,222 @@
1
  #!/usr/bin/env python3
2
  """
3
- Complete Setup Script for Iran Legal Dashboard
4
- ==============================================
5
- Enhanced setup with dependency management, environment setup, and comprehensive initialization
6
  """
7
 
8
- import sqlite3
9
- import json
10
  import os
11
  import sys
 
12
  import logging
13
- import subprocess
14
- import shutil
15
- from datetime import datetime
16
- from typing import Dict, List, Optional
17
  from pathlib import Path
18
 
19
- # Configure logging
20
  logging.basicConfig(
21
  level=logging.INFO,
22
- format='%(asctime)s - %(levelname)s - %(message)s',
23
- handlers=[
24
- logging.FileHandler('setup.log'),
25
- logging.StreamHandler(sys.stdout)
26
- ]
27
  )
28
  logger = logging.getLogger(__name__)
29
 
30
- class SetupManager:
31
- """Complete setup manager for the Iran Legal Dashboard"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
- def __init__(self):
34
- self.project_root = Path.cwd()
35
- self.data_dir = self.project_root / "data"
36
- self.logs_dir = self.project_root / "logs"
37
- self.temp_dir = self.project_root / "temp"
38
- self.config_file = self.project_root / "config.json"
39
-
40
- def run_complete_setup(self):
41
- """Run the complete setup process"""
42
- logger.info("🚀 Starting Iran Legal Dashboard Complete Setup...")
43
-
44
  try:
45
- # Step 1: Check system requirements
46
- if not self.check_system_requirements():
47
- return False
48
-
49
- # Step 2: Check and install dependencies
50
- if not self.setup_dependencies():
51
- return False
52
-
53
- # Step 3: Create directory structure
54
- self.create_directory_structure()
55
-
56
- # Step 4: Create configuration
57
- self.create_configuration()
58
-
59
- # Step 5: Initialize database
60
- if not self.setup_database():
61
- return False
62
-
63
- # Step 6: Create sample data
64
- self.create_sample_data()
65
-
66
- # Step 7: Setup environment files
67
- self.create_environment_files()
68
-
69
- # Step 8: Verify installation
70
- if not self.verify_installation():
71
- return False
72
-
73
- # Step 9: Create launcher scripts
74
- self.create_launcher_scripts()
75
-
76
- logger.info("✅ Setup completed successfully!")
77
- self.show_final_instructions()
78
- return True
79
 
 
 
 
 
 
 
80
  except Exception as e:
81
- logger.error(f" Setup failed: {e}")
82
- return False
83
 
84
- def check_system_requirements(self) -> bool:
85
- """Check system requirements"""
86
- logger.info("🔍 Checking system requirements...")
87
-
88
- # Check Python version
89
- python_version = sys.version_info
90
- if python_version.major < 3 or (python_version.major == 3 and python_version.minor < 7):
91
- logger.error("❌ Python 3.7+ is required")
92
- return False
93
-
94
- logger.info(f"✅ Python {python_version.major}.{python_version.minor}.{python_version.micro}")
95
-
96
- # Check available disk space (at least 100MB)
97
- try:
98
- free_space = shutil.disk_usage('.').free / (1024 * 1024) # MB
99
- if free_space < 100:
100
- logger.warning(f"⚠️ Low disk space: {free_space:.1f}MB available")
101
- else:
102
- logger.info(f"✅ Disk space: {free_space:.1f}MB available")
103
- except Exception as e:
104
- logger.warning(f"⚠️ Could not check disk space: {e}")
105
-
106
- # Check write permissions
107
- try:
108
- test_file = self.project_root / "test_write.tmp"
109
- test_file.write_text("test")
110
- test_file.unlink()
111
- logger.info("✅ Write permissions OK")
112
- except Exception as e:
113
- logger.error(f"❌ No write permissions: {e}")
114
- return False
115
-
116
- return True
117
 
118
- def setup_dependencies(self) -> bool:
119
- """Check and install Python dependencies"""
120
- logger.info("📦 Setting up dependencies...")
121
-
122
- required_packages = {
123
- 'streamlit': '>=1.28.0',
124
- 'pandas': '>=1.5.0',
125
- 'plotly': '>=5.0.0',
126
- 'requests': '>=2.25.0',
127
- 'beautifulsoup4': '>=4.9.0',
128
- 'Pillow': '>=8.0.0',
129
- 'python-dateutil': '>=2.8.0'
130
- }
131
-
132
- missing_packages = []
133
-
134
- for package, version in required_packages.items():
135
- try:
136
- if package == 'beautifulsoup4':
137
- import bs4
138
- logger.info(f"✅ {package} is available")
139
- elif package == 'Pillow':
140
- import PIL
141
- logger.info(f"✅ {package} is available")
142
- elif package == 'python-dateutil':
143
- import dateutil
144
- logger.info(f"✅ {package} is available")
145
- else:
146
- __import__(package)
147
- logger.info(f"✅ {package} is available")
148
- except ImportError:
149
- missing_packages.append(f"{package}{version}")
150
- logger.warning(f"⚠️ {package} is missing")
151
-
152
- if missing_packages:
153
- logger.info("📥 Installing missing packages...")
154
-
155
- # Create requirements.txt
156
- requirements_content = "\n".join(missing_packages)
157
- requirements_file = self.project_root / "requirements.txt"
158
- requirements_file.write_text(requirements_content)
159
-
160
- try:
161
- # Try to install packages
162
- subprocess.check_call([
163
- sys.executable, "-m", "pip", "install", "-r", str(requirements_file)
164
- ])
165
- logger.info("✅ Dependencies installed successfully")
166
- except subprocess.CalledProcessError as e:
167
- logger.error(f"❌ Failed to install dependencies: {e}")
168
- logger.info("Please run: pip install -r requirements.txt")
169
- return False
170
-
171
- return True
172
 
173
- def create_directory_structure(self):
174
- """Create necessary directories"""
175
- logger.info("📁 Creating directory structure...")
176
-
177
- directories = [
178
- self.data_dir,
179
- self.logs_dir,
180
- self.temp_dir,
181
- self.project_root / "assets",
182
- self.project_root / "backups",
183
- self.project_root / "exports"
184
- ]
185
-
186
- for directory in directories:
187
  try:
188
- directory.mkdir(exist_ok=True)
189
- logger.info(f"✅ Created/verified directory: {directory}")
 
 
 
 
190
  except Exception as e:
191
- logger.error(f"❌ Failed to create directory {directory}: {e}")
 
 
 
 
192
 
193
- def create_configuration(self):
194
- """Create configuration file"""
195
- logger.info("⚙️ Creating configuration...")
196
-
197
- config = {
198
- "app": {
199
- "name": "Iran Legal Information Dashboard",
200
- "version": "1.0.0",
201
- "description": "Legal document management and analysis system",
202
- "created": datetime.now().isoformat()
203
- },
204
- "database": {
205
- "type": "sqlite",
206
- "path": str(self.data_dir / "iran_legal.db"),
207
- "backup_interval": "daily",
208
- "max_backups": 7
209
- },
210
- "ai": {
211
- "enabled": True,
212
- "min_score_threshold": 0.3,
213
- "keyword_extraction_limit": 10
214
- },
215
- "scraping": {
216
- "enabled": True,
217
- "default_timeout": 15,
218
- "max_concurrent": 5,
219
- "delay_between_requests": 1,
220
- "trusted_domains": [
221
- "dastour.ir",
222
- "mizanonline.ir",
223
- "judiciary.ir",
224
- "majlis.ir",
225
- "rc.majlis.ir"
226
- ]
227
- },
228
- "ui": {
229
- "language": "fa",
230
- "theme": "modern",
231
- "items_per_page": 20,
232
- "enable_animations": True
233
- },
234
- "security": {
235
- "enable_logging": True,
236
- "max_upload_size": "10MB",
237
- "allowed_file_types": ["pdf", "txt", "docx"]
238
- },
239
- "paths": {
240
- "data": str(self.data_dir),
241
- "logs": str(self.logs_dir),
242
- "temp": str(self.temp_dir),
243
- "backups": str(self.project_root / "backups"),
244
- "exports": str(self.project_root / "exports")
245
- }
246
- }
247
-
248
- try:
249
- with open(self.config_file, 'w', encoding='utf-8') as f:
250
- json.dump(config, f, indent=2, ensure_ascii=False)
251
- logger.info(f"✅ Configuration created: {self.config_file}")
252
- except Exception as e:
253
- logger.error(f"❌ Failed to create configuration: {e}")
254
 
255
- def setup_database(self) -> bool:
256
- """Initialize database with tables and sample data"""
257
- logger.info("🗄️ Setting up database...")
258
-
259
- db_path = self.data_dir / "iran_legal.db"
260
-
261
  try:
262
- with sqlite3.connect(str(db_path)) as conn:
263
- # Enable WAL mode and foreign keys
264
- conn.execute("PRAGMA journal_mode=WAL;")
265
- conn.execute("PRAGMA foreign_keys = ON;")
266
-
267
- # Create tables
268
- self._create_database_tables(conn)
269
-
270
- # Add sample data
271
- self._add_sample_data(conn)
272
-
273
- logger.info(f"✅ Database initialized: {db_path}")
274
- return True
275
-
276
- except Exception as e:
277
- logger.error(f"❌ Database setup failed: {e}")
278
- return False
279
 
280
- def _create_database_tables(self, conn: sqlite3.Connection):
281
- """Create database tables"""
282
-
283
- # Documents table
284
- conn.execute("""
285
- CREATE TABLE IF NOT EXISTS documents (
286
- id INTEGER PRIMARY KEY AUTOINCREMENT,
287
- title TEXT NOT NULL,
288
- content TEXT NOT NULL,
289
- source TEXT,
290
- category TEXT,
291
- ai_score REAL DEFAULT 0.0,
292
- keywords TEXT,
293
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
294
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
295
- file_size INTEGER DEFAULT 0,
296
- language TEXT DEFAULT 'fa',
297
- status TEXT DEFAULT 'active'
298
- )
299
- """)
300
-
301
- # Scraped items table
302
- conn.execute("""
303
- CREATE TABLE IF NOT EXISTS scraped_items (
304
- id TEXT PRIMARY KEY,
305
- url TEXT NOT NULL UNIQUE,
306
- title TEXT,
307
- content TEXT,
308
- domain TEXT,
309
- rating_score REAL DEFAULT 0.0,
310
- word_count INTEGER DEFAULT 0,
311
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
312
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
313
- status TEXT DEFAULT 'completed',
314
- last_scraped TIMESTAMP DEFAULT CURRENT_TIMESTAMP
315
- )
316
- """)
317
-
318
- # System logs table
319
- conn.execute("""
320
- CREATE TABLE IF NOT EXISTS system_logs (
321
- id INTEGER PRIMARY KEY AUTOINCREMENT,
322
- timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
323
- level TEXT NOT NULL,
324
- component TEXT,
325
- message TEXT NOT NULL,
326
- details TEXT
327
- )
328
- """)
329
-
330
- # User sessions table (for future multi-user support)
331
- conn.execute("""
332
- CREATE TABLE IF NOT EXISTS user_sessions (
333
- id TEXT PRIMARY KEY,
334
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
335
- last_activity TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
336
- ip_address TEXT,
337
- user_agent TEXT,
338
- active BOOLEAN DEFAULT 1
339
- )
340
- """)
341
-
342
- # Performance indexes
343
- indexes = [
344
- "CREATE INDEX IF NOT EXISTS idx_documents_category ON documents(category);",
345
- "CREATE INDEX IF NOT EXISTS idx_documents_ai_score ON documents(ai_score);",
346
- "CREATE INDEX IF NOT EXISTS idx_documents_created_at ON documents(created_at);",
347
- "CREATE INDEX IF NOT EXISTS idx_scraped_domain ON scraped_items(domain);",
348
- "CREATE INDEX IF NOT EXISTS idx_scraped_rating ON scraped_items(rating_score);",
349
- "CREATE INDEX IF NOT EXISTS idx_scraped_created_at ON scraped_items(created_at);",
350
- "CREATE INDEX IF NOT EXISTS idx_logs_timestamp ON system_logs(timestamp);",
351
- "CREATE INDEX IF NOT EXISTS idx_logs_level ON system_logs(level);"
352
- ]
353
-
354
- for index in indexes:
355
- conn.execute(index)
356
-
357
- conn.commit()
358
- logger.info("✅ Database tables created")
359
 
360
- def _add_sample_data(self, conn: sqlite3.Connection):
361
- """Add comprehensive sample data"""
362
-
363
- # Sample documents
364
- sample_documents = [
365
- {
366
- 'title': 'قانون اساسی جمهوری اسلامی ایران - فصل اول',
367
- 'content': '''فصل اول - اصول کلی
368
-
369
- اصل یکم: حکومت ایران، جمهوری اسلامی است که ملت ایران بر اساس ایمان دیرینه‌اش به حاکمیت حق و عدالت قرآن، در انقلاب اسلامی سال ۱۳۵۷ تحت رهبری امام خمینی به آن رأی مثبت داد.
370
-
371
- اصل دوم: جمهوری اسلامی، نظامی است مبتنی بر ایمان به خدای یکتا، حاکمیت و قانون الهی، عدل، ایمان و تقوا، و در حکومت، دین مبین اسلام مذهب جعفری اثنی عشری.
372
-
373
- اصل سوم: برای نیل به اهداف مندرج در اصل دوم، دولت جمهوری اسلامی ایران موظف است تمام امکانات خود را برای دستیابی به مقاصد ذیل به کار گیرد:
374
- ۱- ایجاد محیط مساعد برای رشد فضایل اخلاقی بر پایه ایمان و تقوا و مبارزه با تمام مظاهر فساد و تباهی
375
- ۲- ارتقاء سطح آگاهی عمومی در همه زمینه‌ها با بهره‌گیری درست از مطبوعات، رسانه‌های گروهی و سایر وسایل
376
- ۳- آموزش و پرورش و تربیت بدنی رایگان برای همه در همه سطوح و تسهیل و تعمیم آموزش عالی''',
377
- 'source': 'قانون اساسی ج.ا.ایران',
378
- 'category': 'قانون',
379
- 'ai_score': 0.95,
380
- 'keywords': json.dumps(['قانون اساسی', 'جمهوری اسلامی', 'حاکمیت', 'عدالت', 'اسلام']),
381
- 'file_size': 2450,
382
- 'language': 'fa'
383
- },
384
- {
385
- 'title': 'قانون مجازات اسلامی - احکام عمومی',
386
- 'content': '''باب اول - احکام عمومی
387
-
388
- ماده ۱- مجازات‌ها به اعتبار کیفیت به سه دسته تقسیم می‌شوند:
389
- الف) حدود
390
- ب) قصاص
391
- ج) تعزیرات
392
-
393
- ماده ۲- حدود عبارت است از مجازات‌هایی که نوع و میزان آنها در شرع مقدس تعیین شده و حق العبد محسوب نمی‌شود.
394
-
395
- ماده ۳- قصاص عبارت است از مجازاتی که در شرع مقدس تعیین شده و حق العبد محسوب می‌شود.
396
-
397
- ماده ۴- تعزیرات عبارت است از مجازات‌هایی غیر از حدود و قصاص که برای تأدیب مرتکب یا جلوگیری از تکرار جرم یا ارتداع دیگران تعیین می‌شود.
398
-
399
- ماده ۵- هرگاه برای یک عمل مجرمانه، مجازات حد یا قصاص و نیز تعزیر تعیین شده باشد، مجازات حد یا قصاص مانع از اجرای تعزیر نیست مگر آنکه قانون طور دیگری مقرر داشته باشد.''',
400
- 'source': 'قانون مجازات اسلام��',
401
- 'category': 'قانون',
402
- 'ai_score': 0.88,
403
- 'keywords': json.dumps(['مجازات', 'حدود', 'قصاص', 'تعزیرات', 'شرع']),
404
- 'file_size': 1850,
405
- 'language': 'fa'
406
- },
407
- {
408
- 'title': 'قانون مدنی - قراردادها',
409
- 'content': '''فصل اول - احکام عمومی قراردادها
410
-
411
- ماده ۱۰- قراردادها برای متعاقدینی که آنها را منعقد نمده‌اند لازم‌الاجرا و قابل فسخ نیست مگر به رضایت طرفین یا در مواردی که قانون تجویز کرده است.
412
 
413
- ماده ۱۱- در قراردادها نه تنها به الفاظ بلکه به قصد و نیت طرفین نیز اعتبار است.
414
-
415
- ماده ۱۲- مجهول‌بودن مبیع یا ثمن مانع از صحت بیع است مگر آنکه مجهول بودن آن خفیف و متعارف باشد.
416
-
417
- ماده ۱۳- در عقود و ایقاعات، عبرت به قصد و معنی است نه به الفاظ.
418
-
419
- ماده ۱۴- تصرف در مال غیر بدون اذن مالک موجب ضمان است.''',
420
- 'source': 'قانون مدنی',
421
- 'category': 'قرارداد',
422
- 'ai_score': 0.82,
423
- 'keywords': json.dumps(['قرارداد', 'متعاقدین', 'بیع', 'ثمن', 'مبیع']),
424
- 'file_size': 1620,
425
- 'language': 'fa'
426
- },
427
- {
428
- 'title': 'قانون آیین دادرسی کیفری - کلیات',
429
- 'content': '''باب اول - کلیات
430
-
431
- ماده ۱- این قانون آیین تعقیب و محاکمه جرایم و اجرای احکام کیفری را تعیین می‌کند.
432
-
433
- ماده ۲- دادرسی کیفری بر اساس احترام به کرامت انسانی، حفظ حقوق فردی و اجتماعی، حق دفاع، برائت ذمه، آزادی و امنیت اشخاص استوار است.
434
-
435
- ماده ۳- هیچ کس را نمی‌توان بدون حکم مقام قضایی ذی‌صلاح دستگیر، بازداشت یا زندانی کرد.
436
-
437
- ماده ۴- متهم حق دارد در تمام مراحل دادرسی وکیل انتخاب کند.
438
-
439
- ماده ۵- تفتیش مسکن، محل کسب و کار، وسایل نقلیه یا اماکن دیگر جز در موارد مستثنی قانونی منوط به حکم مقام قضایی است.''',
440
- 'source': 'قانون آیین دادرسی کیفری',
441
- 'category': 'حکم',
442
- 'ai_score': 0.90,
443
- 'keywords': json.dumps(['دادرسی', 'کیفری', 'متهم', 'دادگاه', 'قاضی']),
444
- 'file_size': 2100,
445
- 'language': 'fa'
446
- }
447
- ]
448
-
449
- # Insert sample documents
450
- for doc in sample_documents:
451
  conn.execute("""
452
  INSERT INTO documents (title, content, source, category, ai_score, keywords, file_size, language)
453
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
454
  """, (
455
- doc['title'], doc['content'], doc['source'], doc['category'],
456
- doc['ai_score'], doc['keywords'], doc['file_size'], doc['language']
 
 
 
 
 
 
457
  ))
458
-
459
- # Sample scraped items
460
- sample_scraped = [
461
- {
462
- 'id': 'sample_dastour_001',
463
- 'url': 'https://dastour.ir/bakhshodare/ghanoon-asasi',
464
- 'title': 'متن کامل قانون اساسی جمهوری اسلامی ایران',
465
- 'content': 'قانون اساسی جمهوری اسلامی ایران که در سال ۱۳۵۸ تصویب و در سال ۱۳۶۸ بازنگری شد، مشتمل بر ۱۷۷ اصل است که در ۱۴ فصل تنظیم شده است. این قانون بنیادی‌ترین و مهم‌ترین قانون کشور محسوب می‌شود.',
466
- 'domain': 'dastour.ir',
467
- 'rating_score': 0.95,
468
- 'word_count': 15420,
469
- 'status': 'completed'
470
- },
471
- {
472
- 'id': 'sample_mizan_001',
473
- 'url': 'https://mizanonline.ir/fa/news/legal-reforms-2024',
474
- 'title': 'اصلاحات جدید در نظام حقوقی کشور - ۱۴۰۳',
475
- 'content': 'در راستای بهبود نظام حقوقی کشور و همسو شدن با تحولات جهانی، مجموعه‌ای از اصلاحات قانونی در دست بررسی قرار گرفته که شامل تغییرات در قوانین مدنی، جزایی و اداری می‌شود. این اصلاحات با هدف تسریع روند دادرسی و حفظ حقوق شهروندان طراحی شده‌اند.',
476
- 'domain': 'mizanonline.ir',
477
- 'rating_score': 0.78,
478
- 'word_count': 852,
479
- 'status': 'completed'
480
- },
481
- {
482
- 'id': 'sample_judiciary_001',
483
- 'url': 'https://judiciary.ir/news/supreme-court-decisions-2024',
484
- 'title': 'آرای مهم دیوان عالی کشور در سال ۱۴۰۳',
485
- 'content': 'دیوان عالی کشور در سال جاری مجموعه‌ای از آرای مهم و تأثیرگذار در خصوص تفسیر قوانین مختلف صادر کرده که نقش به‌سزایی در وحدت رویه قضایی و شفاف‌سازی مسائل حقوقی خواهد داشت. این آرا شامل موضوعات مدنی، کیفری و اداری می‌شود.',
486
- 'domain': 'judiciary.ir',
487
- 'rating_score': 0.87,
488
- 'word_count': 1240,
489
- 'status': 'completed'
490
- }
491
- ]
492
-
493
- # Insert sample scraped items
494
- for item in sample_scraped:
495
  conn.execute("""
496
  INSERT INTO scraped_items (id, url, title, content, domain, rating_score, word_count, status)
497
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
498
  """, (
499
- item['id'], item['url'], item['title'], item['content'],
500
- item['domain'], item['rating_score'], item['word_count'], item['status']
 
 
 
 
 
 
501
  ))
502
-
503
- # Add system log entry
504
- conn.execute("""
505
- INSERT INTO system_logs (level, component, message, details)
506
- VALUES (?, ?, ?, ?)
507
- """, ('INFO', 'setup', 'Database initialized with sample data',
508
- json.dumps({'documents': len(sample_documents), 'scraped_items': len(sample_scraped)})))
509
-
510
- conn.commit()
511
- logger.info(f"✅ Added {len(sample_documents)} sample documents and {len(sample_scraped)} scraped items")
512
-
513
- def create_sample_data(self):
514
- """Create additional sample data files"""
515
- logger.info("📝 Creating sample data files...")
516
-
517
- # Create sample upload file
518
- sample_text = """نمونه متن حقوقی
519
-
520
- این یک نمونه متن حقوقی است که می‌توانید برای تست سیستم استفاده کنید.
521
-
522
- ماده ۱- این متن به عنوان نمونه تهیه شده است.
523
- ماده ۲- محتوای این متن صرفاً جنبه آموزشی دارد.
524
 
525
- تبصره: این متن قابلیت آپلود و تحلیل توسط سیستم هوش مصنوعی را دارد.
526
- """
527
-
528
- sample_file = self.temp_dir / "sample_legal_text.txt"
529
- sample_file.write_text(sample_text, encoding='utf-8')
530
- logger.info(f"✅ Sample file created: {sample_file}")
531
 
532
- def create_environment_files(self):
533
- """Create environment and configuration files"""
534
- logger.info("🔧 Creating environment files...")
535
-
536
- # Create .streamlit directory and config
537
- streamlit_dir = self.project_root / ".streamlit"
538
- streamlit_dir.mkdir(exist_ok=True)
539
-
540
- # Streamlit config
541
- streamlit_config = """[theme]
542
- primaryColor = "#667eea"
543
- backgroundColor = "#ffffff"
544
- secondaryBackgroundColor = "#f0f2f6"
545
- textColor = "#262730"
546
- font = "sans serif"
547
-
548
- [server]
549
- headless = true
550
- port = 8501
551
- enableCORS = false
552
- enableXsrfProtection = false
553
-
554
- [browser]
555
- gatherUsageStats = false
556
- """
557
-
558
- (streamlit_dir / "config.toml").write_text(streamlit_config)
559
-
560
- # Create .env file
561
- env_content = """# Iran Legal Dashboard Environment Variables
562
-
563
- # Application Settings
564
- APP_NAME="Iran Legal Information Dashboard"
565
- APP_VERSION="1.0.0"
566
- DEBUG=false
567
-
568
- # Database Settings
569
- DATABASE_PATH="./data/iran_legal.db"
570
- DATABASE_BACKUP_ENABLED=true
571
-
572
- # Security Settings
573
- SECRET_KEY="your-secret-key-here"
574
- MAX_UPLOAD_SIZE=10485760
575
-
576
- # Feature Flags
577
- ENABLE_AI_ANALYSIS=true
578
- ENABLE_WEB_SCRAPING=true
579
- ENABLE_LOGGING=true
580
-
581
- # External Services (if needed)
582
- # API_KEY=""
583
- # EXTERNAL_SERVICE_URL=""
584
- """
585
-
586
- env_file = self.project_root / ".env"
587
- env_file.write_text(env_content)
588
-
589
- logger.info("✅ Environment files created")
590
 
591
- def verify_installation(self) -> bool:
592
- """Verify the installation"""
593
- logger.info("🔍 Verifying installation...")
594
-
595
- checks = [
596
- (self.data_dir / "iran_legal.db", "Database file"),
597
- (self.config_file, "Configuration file"),
598
- (self.project_root / ".streamlit" / "config.toml", "Streamlit config"),
599
- (self.project_root / ".env", "Environment file")
600
- ]
601
-
602
- all_good = True
603
- for file_path, description in checks:
604
- if file_path.exists():
605
- logger.info(f"✅ {description}: OK")
606
- else:
607
- logger.error(f"❌ {description}: Missing")
608
- all_good = False
609
-
610
- # Test database connection
611
- try:
612
- db_path = self.data_dir / "iran_legal.db"
613
- with sqlite3.connect(str(db_path)) as conn:
614
- cursor = conn.execute("SELECT COUNT(*) FROM documents")
615
- doc_count = cursor.fetchone()[0]
616
- cursor = conn.execute("SELECT COUNT(*) FROM scraped_items")
617
- scraped_count = cursor.fetchone()[0]
618
- logger.info(f"✅ Database connectivity: OK ({doc_count} documents, {scraped_count} scraped items)")
619
- except Exception as e:
620
- logger.error(f"❌ Database connectivity: Failed - {e}")
621
- all_good = False
622
-
623
- return all_good
624
 
625
- def create_launcher_scripts(self):
626
- """Create launcher scripts for different platforms"""
627
- logger.info("🚀 Creating launcher scripts...")
628
-
629
- # Windows batch file
630
- windows_script = """@echo off
631
- echo Starting Iran Legal Dashboard...
632
- echo.
633
-
634
- :: Check if Python is available
635
- python --version >nul 2>&1
636
- if errorlevel 1 (
637
- echo Python is not installed or not in PATH
638
- pause
639
- exit /b 1
640
- )
641
-
642
- :: Check if Streamlit is available
643
- python -c "import streamlit" >nul 2>&1
644
- if errorlevel 1 (
645
- echo Installing required packages...
646
- pip install -r requirements.txt
647
- )
648
-
649
- :: Start the application
650
- echo Starting application on http://localhost:8501
651
- echo Press Ctrl+C to stop
652
- echo.
653
- streamlit run streamlit_app.py
654
-
655
- pause
656
- """
657
-
658
- windows_file = self.project_root / "start_dashboard.bat"
659
- windows_file.write_text(windows_script)
660
-
661
- # Unix shell script
662
- unix_script = """#!/bin/bash
663
- echo "Starting Iran Legal Dashboard..."
664
- echo
665
-
666
- # Check if Python is available
667
- if ! command -v python3 &> /dev/null; then
668
- echo "Python 3 is not installed or not in PATH"
669
- exit 1
670
- fi
671
-
672
- # Check if Streamlit is available
673
- python3 -c "import streamlit" 2>/dev/null
674
- if [ $? -ne 0 ]; then
675
- echo "Installing required packages..."
676
- pip3 install -r requirements.txt
677
- fi
678
-
679
- # Start the application
680
- echo "Starting application on http://localhost:8501"
681
- echo "Press Ctrl+C to stop"
682
- echo
683
- streamlit run streamlit_app.py
684
- """
685
-
686
- unix_file = self.project_root / "start_dashboard.sh"
687
- unix_file.write_text(unix_script)
688
-
689
- # Make shell script executable
690
- try:
691
- unix_file.chmod(0o755)
692
- except Exception:
693
- pass # Windows doesn't support chmod
694
-
695
- # Create requirements.txt
696
- requirements = """streamlit>=1.28.0
697
- pandas>=1.5.0
698
- plotly>=5.0.0
699
- requests>=2.25.0
700
- beautifulsoup4>=4.9.0
701
- Pillow>=8.0.0
702
- python-dateutil>=2.8.0
703
- """
704
-
705
- requirements_file = self.project_root / "requirements.txt"
706
- requirements_file.write_text(requirements)
707
-
708
- logger.info("✅ Launcher scripts created")
709
 
710
- def show_final_instructions(self):
711
- """Show final setup instructions"""
712
- logger.info("\n" + "="*60)
713
- logger.info("🎉 SETUP COMPLETED SUCCESSFULLY!")
714
- logger.info("="*60)
715
- logger.info("")
716
- logger.info("📋 NEXT STEPS:")
717
- logger.info("")
718
- logger.info("1. To start the application:")
719
-
720
- if os.name == 'nt': # Windows
721
- logger.info(" Windows: Double-click 'start_dashboard.bat'")
722
- logger.info(" Or run: streamlit run streamlit_app.py")
723
- else: # Unix-like
724
- logger.info(" Unix/Linux/macOS: ./start_dashboard.sh")
725
- logger.info(" Or run: streamlit run streamlit_app.py")
726
-
727
- logger.info("")
728
- logger.info("2. Open your browser and go to: http://localhost:8501")
729
- logger.info("")
730
- logger.info("📁 IMPORTANT FILES:")
731
- logger.info(f" • Main app: streamlit_app.py")
732
- logger.info(f" • Database: {self.data_dir}/iran_legal.db")
733
- logger.info(f" • Config: {self.config_file}")
734
- logger.info(f" • Logs: {self.logs_dir}/")
735
- logger.info("")
736
- logger.info("🔧 TROUBLESHOOTING:")
737
- logger.info(" • Check setup.log for detailed logs")
738
- logger.info(" • Ensure Python 3.7+ is installed")
739
- logger.info(" • Run 'pip install -r requirements.txt' if needed")
740
- logger.info("")
741
- logger.info("📚 FEATURES READY:")
742
- logger.info(" ✅ Document management")
743
- logger.info(" ✅ AI analysis engine")
744
- logger.info(" ✅ Web scraping service")
745
- logger.info(" ✅ Search functionality")
746
- logger.info(" ✅ Analytics dashboard")
747
- logger.info("")
748
- logger.info("="*60)
749
-
750
- def main():
751
- """Main setup function"""
752
- print("🚀 Iran Legal Dashboard Setup")
753
- print("=" * 40)
754
 
755
- setup_manager = SetupManager()
 
756
 
757
- try:
758
- success = setup_manager.run_complete_setup()
759
-
760
- if success:
761
- print("\n✅ Setup completed successfully!")
762
- print("Run 'streamlit run streamlit_app.py' to start the application.")
763
- else:
764
- print("\n❌ Setup failed. Check setup.log for details.")
765
- sys.exit(1)
766
-
767
- except KeyboardInterrupt:
768
- print("\n\n⚠️ Setup interrupted by user")
769
- sys.exit(1)
770
- except Exception as e:
771
- logger.error(f"Unexpected error: {e}")
772
- print(f"\n❌ Unexpected error: {e}")
773
- sys.exit(1)
774
 
775
  if __name__ == "__main__":
776
- main()
 
 
 
1
  #!/usr/bin/env python3
2
  """
3
+ Startup Script for Iran Legal Dashboard
4
+ ======================================
5
+ Ensures proper initialization and debugging
6
  """
7
 
 
 
8
  import os
9
  import sys
10
+ import sqlite3
11
  import logging
 
 
 
 
12
  from pathlib import Path
13
 
14
+ # Setup logging
15
  logging.basicConfig(
16
  level=logging.INFO,
17
+ format='%(asctime)s - %(levelname)s - %(message)s'
 
 
 
 
18
  )
19
  logger = logging.getLogger(__name__)
20
 
21
+ def check_environment():
22
+ """Check if running environment is properly configured"""
23
+ logger.info("🔍 Checking environment...")
24
+
25
+ # Check current directory
26
+ cwd = os.getcwd()
27
+ logger.info(f"📁 Current working directory: {cwd}")
28
+
29
+ # Check for required files
30
+ required_files = ['app.py', 'requirements.txt']
31
+ src_required_files = ['src/streamlit_app.py'] if os.path.exists('src') else []
32
+
33
+ all_required = required_files + src_required_files
34
+
35
+ missing_files = []
36
+ for file in all_required:
37
+ if not os.path.exists(file):
38
+ missing_files.append(file)
39
+
40
+ if missing_files:
41
+ logger.error(f"❌ Missing required files: {missing_files}")
42
+ return False
43
+
44
+ logger.info("✅ All required files found")
45
+ return True
46
+
47
+ def setup_database():
48
+ """Setup database with proper permissions"""
49
+ logger.info("🗄️ Setting up database...")
50
 
51
+ # Try different database paths
52
+ db_paths = [
53
+ "/tmp/iran_legal.db",
54
+ "./iran_legal.db",
55
+ "data/iran_legal.db"
56
+ ]
57
+
58
+ for db_path in db_paths:
 
 
 
59
  try:
60
+ # Ensure directory exists
61
+ db_dir = os.path.dirname(db_path)
62
+ if db_dir and not os.path.exists(db_dir):
63
+ os.makedirs(db_dir, exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
+ # Test database connection
66
+ with sqlite3.connect(db_path, timeout=10) as conn:
67
+ conn.execute("SELECT 1")
68
+ logger.info(f"✅ Database accessible at: {db_path}")
69
+ return db_path
70
+
71
  except Exception as e:
72
+ logger.warning(f"⚠️ Cannot access {db_path}: {e}")
73
+ continue
74
 
75
+ logger.error("❌ No accessible database path found")
76
+ return None
77
+
78
+ def check_permissions():
79
+ """Check write permissions for critical directories"""
80
+ logger.info("🔐 Checking permissions...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
+ test_dirs = ["/tmp", ".", "./data", "./src"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
+ results = {}
85
+ for test_dir in test_dirs:
86
+ if os.path.exists(test_dir):
 
 
 
 
 
 
 
 
 
 
 
87
  try:
88
+ test_file = os.path.join(test_dir, "test_write.tmp")
89
+ with open(test_file, 'w') as f:
90
+ f.write("test")
91
+ os.remove(test_file)
92
+ results[test_dir] = True
93
+ logger.info(f"✅ {test_dir} - Writable")
94
  except Exception as e:
95
+ results[test_dir] = False
96
+ logger.warning(f"❌ {test_dir} - Not writable: {e}")
97
+ else:
98
+ results[test_dir] = None
99
+ logger.info(f"ℹ️ {test_dir} - Does not exist")
100
 
101
+ return results
102
+
103
+ def verify_imports():
104
+ """Verify all required imports work"""
105
+ logger.info("📦 Verifying imports...")
106
+
107
+ required_modules = [
108
+ 'streamlit',
109
+ 'pandas',
110
+ 'plotly',
111
+ 'requests',
112
+ 'bs4',
113
+ 'sqlite3',
114
+ 'json',
115
+ 'hashlib',
116
+ 'datetime'
117
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
+ failed_imports = []
120
+
121
+ for module in required_modules:
 
 
 
122
  try:
123
+ __import__(module)
124
+ logger.info(f"✅ {module} - OK")
125
+ except ImportError as e:
126
+ failed_imports.append(module)
127
+ logger.error(f"❌ {module} - Failed: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
+ if failed_imports:
130
+ logger.error(f" Failed imports: {failed_imports}")
131
+ logger.info("💡 Run: pip install -r requirements.txt")
132
+ return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
+ return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
+ def create_sample_data(db_path):
137
+ """Create sample data for testing"""
138
+ logger.info("📝 Creating sample data...")
139
+
140
+ try:
141
+ with sqlite3.connect(db_path) as conn:
142
+ # Check if data already exists
143
+ cursor = conn.execute("SELECT COUNT(*) FROM documents")
144
+ doc_count = cursor.fetchone()[0]
145
+
146
+ if doc_count > 0:
147
+ logger.info(f"ℹ️ Database already has {doc_count} documents")
148
+ return True
149
+
150
+ # Create sample document
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  conn.execute("""
152
  INSERT INTO documents (title, content, source, category, ai_score, keywords, file_size, language)
153
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
154
  """, (
155
+ "نمونه سند حقوقی",
156
+ "این یک نمونه سند حقوقی برای تست سیستم است که شامل محتوای آزمایشی می‌باشد.",
157
+ "سیستم تست",
158
+ "قانون",
159
+ 0.75,
160
+ '["نمونه", "حقوق", "تست"]',
161
+ 150,
162
+ "fa"
163
  ))
164
+
165
+ # Create sample scraped item
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  conn.execute("""
167
  INSERT INTO scraped_items (id, url, title, content, domain, rating_score, word_count, status)
168
  VALUES (?, ?, ?, ?, ?, ?, ?, ?)
169
  """, (
170
+ "sample_001",
171
+ "https://dastour.ir/sample",
172
+ "نمونه محتوای حقوقی",
173
+ "این یک نمونه محتوای حقوقی جمع‌آوری شده از وب است.",
174
+ "dastour.ir",
175
+ 0.80,
176
+ 25,
177
+ "completed"
178
  ))
179
+
180
+ conn.commit()
181
+ logger.info("✅ Sample data created successfully")
182
+ return True
183
+
184
+ except Exception as e:
185
+ logger.error(f"❌ Failed to create sample data: {e}")
186
+ return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
+ def main():
189
+ """Main startup function"""
190
+ logger.info("🚀 Starting Iran Legal Dashboard initialization...")
 
 
 
191
 
192
+ # Check environment
193
+ if not check_environment():
194
+ logger.error(" Environment check failed")
195
+ return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
+ # Check permissions
198
+ check_permissions()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
+ # Verify imports
201
+ if not verify_imports():
202
+ logger.error(" Import verification failed")
203
+ return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
+ # Setup database
206
+ db_path = setup_database()
207
+ if not db_path:
208
+ logger.error(" Database setup failed")
209
+ return False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
+ # Create sample data
212
+ create_sample_data(db_path)
213
 
214
+ logger.info("✅ Initialization completed successfully!")
215
+ logger.info("🎉 Ready to run: streamlit run app.py")
216
+
217
+ return True
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
219
  if __name__ == "__main__":
220
+ success = main()
221
+ if not success:
222
+ sys.exit(1)