cryogenic22 commited on
Commit
22c9c7b
·
verified ·
1 Parent(s): 9274dab

Create data_persistence.py

Browse files
Files changed (1) hide show
  1. data_persistence.py +261 -0
data_persistence.py ADDED
@@ -0,0 +1,261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # File: data_persistence.py
2
+ # Location: /data_persistence.py
3
+ # Description: Robust data persistence and serialization for book writing project
4
+
5
+ import os
6
+ import json
7
+ import sqlite3
8
+ from typing import Dict, Any
9
+ import streamlit as st
10
+
11
+ class ProjectPersistenceManager:
12
+ def __init__(self, project_id: str = None):
13
+ """
14
+ Initialize persistent storage for book writing projects
15
+
16
+ Args:
17
+ project_id (str, optional): Unique identifier for the project
18
+ """
19
+ # Ensure data directory exists
20
+ os.makedirs('project_data', exist_ok=True)
21
+
22
+ # SQLite Database Setup
23
+ self.db_path = 'project_data/book_projects.db'
24
+ self.conn = sqlite3.connect(self.db_path)
25
+ self._create_tables()
26
+
27
+ def _create_tables(self):
28
+ """
29
+ Create necessary tables for project persistence
30
+ """
31
+ cursor = self.conn.cursor()
32
+
33
+ # Project Metadata Table
34
+ cursor.execute('''
35
+ CREATE TABLE IF NOT EXISTS projects (
36
+ project_id TEXT PRIMARY KEY,
37
+ title TEXT,
38
+ genre TEXT,
39
+ total_chapters INTEGER,
40
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
41
+ )
42
+ ''')
43
+
44
+ # Chapters Table
45
+ cursor.execute('''
46
+ CREATE TABLE IF NOT EXISTS chapters (
47
+ project_id TEXT,
48
+ chapter_number INTEGER,
49
+ content TEXT,
50
+ status TEXT,
51
+ generated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
52
+ PRIMARY KEY (project_id, chapter_number),
53
+ FOREIGN KEY (project_id) REFERENCES projects (project_id)
54
+ )
55
+ ''')
56
+
57
+ # Book Concept Table
58
+ cursor.execute('''
59
+ CREATE TABLE IF NOT EXISTS book_concepts (
60
+ project_id TEXT PRIMARY KEY,
61
+ concept_data TEXT,
62
+ FOREIGN KEY (project_id) REFERENCES projects (project_id)
63
+ )
64
+ ''')
65
+
66
+ self.conn.commit()
67
+
68
+ def save_project_metadata(self, project_data: Dict[str, Any]):
69
+ """
70
+ Save project metadata to persistent storage
71
+
72
+ Args:
73
+ project_data (Dict): Project metadata dictionary
74
+ """
75
+ cursor = self.conn.cursor()
76
+
77
+ # Upsert project metadata
78
+ cursor.execute('''
79
+ INSERT OR REPLACE INTO projects
80
+ (project_id, title, genre, total_chapters)
81
+ VALUES (?, ?, ?, ?)
82
+ ''', (
83
+ project_data.get('project_id', 'unknown'),
84
+ project_data.get('title', 'Untitled'),
85
+ project_data.get('genre', 'Unspecified'),
86
+ project_data.get('total_chapters', 0)
87
+ ))
88
+
89
+ self.conn.commit()
90
+
91
+ def save_book_concept(self, project_id: str, concept_data: Dict[str, Any]):
92
+ """
93
+ Save book concept to persistent storage
94
+
95
+ Args:
96
+ project_id (str): Unique project identifier
97
+ concept_data (Dict): Book concept details
98
+ """
99
+ cursor = self.conn.cursor()
100
+
101
+ # Upsert book concept
102
+ cursor.execute('''
103
+ INSERT OR REPLACE INTO book_concepts
104
+ (project_id, concept_data)
105
+ VALUES (?, ?)
106
+ ''', (
107
+ project_id,
108
+ json.dumps(concept_data)
109
+ ))
110
+
111
+ self.conn.commit()
112
+
113
+ def save_chapter(
114
+ self,
115
+ project_id: str,
116
+ chapter_number: int,
117
+ content: str,
118
+ status: str = 'Generated'
119
+ ):
120
+ """
121
+ Save chapter content to persistent storage
122
+
123
+ Args:
124
+ project_id (str): Unique project identifier
125
+ chapter_number (int): Chapter number
126
+ content (str): Chapter content
127
+ status (str): Chapter status
128
+ """
129
+ cursor = self.conn.cursor()
130
+
131
+ # Upsert chapter
132
+ cursor.execute('''
133
+ INSERT OR REPLACE INTO chapters
134
+ (project_id, chapter_number, content, status)
135
+ VALUES (?, ?, ?, ?)
136
+ ''', (
137
+ project_id,
138
+ chapter_number,
139
+ content,
140
+ status
141
+ ))
142
+
143
+ self.conn.commit()
144
+
145
+ def load_project_metadata(self, project_id: str) -> Dict[str, Any]:
146
+ """
147
+ Load project metadata from persistent storage
148
+
149
+ Args:
150
+ project_id (str): Unique project identifier
151
+
152
+ Returns:
153
+ Dict containing project metadata
154
+ """
155
+ cursor = self.conn.cursor()
156
+ cursor.execute('SELECT * FROM projects WHERE project_id = ?', (project_id,))
157
+
158
+ project = cursor.fetchone()
159
+ if project:
160
+ return {
161
+ 'project_id': project[0],
162
+ 'title': project[1],
163
+ 'genre': project[2],
164
+ 'total_chapters': project[3]
165
+ }
166
+
167
+ return {}
168
+
169
+ def load_book_concept(self, project_id: str) -> Dict[str, Any]:
170
+ """
171
+ Load book concept from persistent storage
172
+
173
+ Args:
174
+ project_id (str): Unique project identifier
175
+
176
+ Returns:
177
+ Dict containing book concept
178
+ """
179
+ cursor = self.conn.cursor()
180
+ cursor.execute('SELECT concept_data FROM book_concepts WHERE project_id = ?', (project_id,))
181
+
182
+ concept = cursor.fetchone()
183
+ return json.loads(concept[0]) if concept else {}
184
+
185
+ def load_chapters(self, project_id: str) -> Dict[int, Dict]:
186
+ """
187
+ Load all chapters for a project
188
+
189
+ Args:
190
+ project_id (str): Unique project identifier
191
+
192
+ Returns:
193
+ Dict of chapters with chapter number as key
194
+ """
195
+ cursor = self.conn.cursor()
196
+ cursor.execute('SELECT chapter_number, content, status FROM chapters WHERE project_id = ?', (project_id,))
197
+
198
+ chapters = {}
199
+ for chapter_num, content, status in cursor.fetchall():
200
+ chapters[chapter_num] = {
201
+ 'content': content,
202
+ 'status': status
203
+ }
204
+
205
+ return chapters
206
+
207
+ def close(self):
208
+ """
209
+ Close database connection
210
+ """
211
+ self.conn.close()
212
+
213
+ # Test functionality
214
+ def test_persistence():
215
+ """
216
+ Run comprehensive tests for data persistence
217
+ """
218
+ # Initialize persistence manager
219
+ pm = ProjectPersistenceManager()
220
+
221
+ # Test project metadata
222
+ test_project = {
223
+ 'project_id': 'test_project_1',
224
+ 'title': 'Test Book',
225
+ 'genre': 'Science Fiction',
226
+ 'total_chapters': 10
227
+ }
228
+
229
+ # Save project metadata
230
+ pm.save_project_metadata(test_project)
231
+
232
+ # Load and verify project metadata
233
+ loaded_project = pm.load_project_metadata('test_project_1')
234
+ assert loaded_project == test_project, "Project metadata not saved/loaded correctly"
235
+
236
+ # Test book concept
237
+ test_concept = {
238
+ 'narrative_premise': 'A story about AI and humanity',
239
+ 'core_themes': ['Technology', 'Ethics']
240
+ }
241
+
242
+ pm.save_book_concept('test_project_1', test_concept)
243
+
244
+ # Load and verify book concept
245
+ loaded_concept = pm.load_book_concept('test_project_1')
246
+ assert loaded_concept == test_concept, "Book concept not saved/loaded correctly"
247
+
248
+ # Test chapter saving and loading
249
+ pm.save_chapter('test_project_1', 1, "Chapter 1 content", "Generated")
250
+ pm.save_chapter('test_project_1', 2, "Chapter 2 content", "In Review")
251
+
252
+ # Load chapters
253
+ loaded_chapters = pm.load_chapters('test_project_1')
254
+ assert len(loaded_chapters) == 2, "Chapters not saved/loaded correctly"
255
+ assert loaded_chapters[1]['content'] == "Chapter 1 content", "Chapter 1 content mismatch"
256
+
257
+ print("All persistence tests passed successfully!")
258
+
259
+ # Run tests if script is executed directly
260
+ if __name__ == "__main__":
261
+ test_persistence()