noticecard 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {noticecard-0.2.0 → noticecard-0.2.1}/PKG-INFO +1 -1
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard/__init__.py +1 -1
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard/app.py +5 -1
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard/cli.py +21 -1
- noticecard-0.2.1/noticecard/migrations.py +84 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard.egg-info/PKG-INFO +1 -1
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard.egg-info/SOURCES.txt +1 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/pyproject.toml +1 -1
- {noticecard-0.2.0 → noticecard-0.2.1}/README.md +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard/models.py +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard/schemas.py +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard/templates.py +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard.egg-info/dependency_links.txt +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard.egg-info/entry_points.txt +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard.egg-info/requires.txt +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/noticecard.egg-info/top_level.txt +0 -0
- {noticecard-0.2.0 → noticecard-0.2.1}/setup.cfg +0 -0
|
@@ -32,6 +32,10 @@ def create_app(db_path: str) -> FastAPI:
|
|
|
32
32
|
"""Create and configure FastAPI application."""
|
|
33
33
|
global _session_maker, _db_path
|
|
34
34
|
|
|
35
|
+
# Check and migrate database if needed
|
|
36
|
+
from .migrations import check_and_migrate
|
|
37
|
+
check_and_migrate(db_path)
|
|
38
|
+
|
|
35
39
|
_db_path = db_path
|
|
36
40
|
engine = init_db(db_path)
|
|
37
41
|
_session_maker = get_session_maker(engine)
|
|
@@ -81,7 +85,7 @@ def create_app(db_path: str) -> FastAPI:
|
|
|
81
85
|
},
|
|
82
86
|
"serverInfo": {
|
|
83
87
|
"name": "noticecard",
|
|
84
|
-
"version": "0.2.
|
|
88
|
+
"version": "0.2.1"
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
91
|
}
|
|
@@ -7,7 +7,7 @@ import uvicorn
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
@click.group()
|
|
10
|
-
@click.version_option(version="0.2.
|
|
10
|
+
@click.version_option(version="0.2.1")
|
|
11
11
|
def main():
|
|
12
12
|
"""NoticeCard 服务端命令行工具"""
|
|
13
13
|
pass
|
|
@@ -76,5 +76,25 @@ def init(work_dir: str):
|
|
|
76
76
|
click.echo(f"数据库已初始化: {db_path}")
|
|
77
77
|
|
|
78
78
|
|
|
79
|
+
@main.command()
|
|
80
|
+
@click.option("--dir", "work_dir", default=".", help="工作目录")
|
|
81
|
+
def migrate(work_dir: str):
|
|
82
|
+
"""迁移数据库到最新版本"""
|
|
83
|
+
work_path = Path(work_dir).resolve()
|
|
84
|
+
db_path = work_path / "noticecard.db"
|
|
85
|
+
|
|
86
|
+
if not db_path.exists():
|
|
87
|
+
click.echo(f"数据库不存在: {db_path}")
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
from .migrations import migrate_to_v2
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
migrate_to_v2(str(db_path))
|
|
94
|
+
click.echo(f"✅ 数据库迁移成功: {db_path}")
|
|
95
|
+
except Exception as e:
|
|
96
|
+
click.echo(f"❌ 迁移失败: {e}", err=True)
|
|
97
|
+
|
|
98
|
+
|
|
79
99
|
if __name__ == "__main__":
|
|
80
100
|
main()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Database migration utilities."""
|
|
2
|
+
|
|
3
|
+
import sqlite3
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def migrate_to_v2(db_path: str):
|
|
8
|
+
"""Migrate database from v1 (desc1, desc2) to v2 (description)."""
|
|
9
|
+
conn = sqlite3.connect(db_path)
|
|
10
|
+
cursor = conn.cursor()
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
# Check if we need to migrate
|
|
14
|
+
cursor.execute("PRAGMA table_info(cards)")
|
|
15
|
+
columns = [col[1] for col in cursor.fetchall()]
|
|
16
|
+
|
|
17
|
+
if 'description' in columns:
|
|
18
|
+
print("Database already migrated to v2")
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
if 'desc1' not in columns:
|
|
22
|
+
print("Database is already in correct format")
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
print("Migrating database to v2...")
|
|
26
|
+
|
|
27
|
+
# Create new table with description field
|
|
28
|
+
cursor.execute("""
|
|
29
|
+
CREATE TABLE cards_new (
|
|
30
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
31
|
+
title TEXT NOT NULL,
|
|
32
|
+
description TEXT,
|
|
33
|
+
created_at TIMESTAMP NOT NULL,
|
|
34
|
+
updated_at TIMESTAMP NOT NULL
|
|
35
|
+
)
|
|
36
|
+
""")
|
|
37
|
+
|
|
38
|
+
# Migrate data: combine desc1 and desc2 into description
|
|
39
|
+
cursor.execute("""
|
|
40
|
+
INSERT INTO cards_new (id, title, description, created_at, updated_at)
|
|
41
|
+
SELECT
|
|
42
|
+
id,
|
|
43
|
+
title,
|
|
44
|
+
CASE
|
|
45
|
+
WHEN desc1 IS NOT NULL AND desc2 IS NOT NULL THEN desc1 || '\n' || desc2
|
|
46
|
+
WHEN desc1 IS NOT NULL THEN desc1
|
|
47
|
+
WHEN desc2 IS NOT NULL THEN desc2
|
|
48
|
+
ELSE NULL
|
|
49
|
+
END as description,
|
|
50
|
+
created_at,
|
|
51
|
+
updated_at
|
|
52
|
+
FROM cards
|
|
53
|
+
""")
|
|
54
|
+
|
|
55
|
+
# Drop old table and rename new one
|
|
56
|
+
cursor.execute("DROP TABLE cards")
|
|
57
|
+
cursor.execute("ALTER TABLE cards_new RENAME TO cards")
|
|
58
|
+
|
|
59
|
+
# Create index
|
|
60
|
+
cursor.execute("CREATE INDEX ix_cards_title ON cards (title)")
|
|
61
|
+
cursor.execute("CREATE INDEX ix_cards_id ON cards (id)")
|
|
62
|
+
|
|
63
|
+
conn.commit()
|
|
64
|
+
print("Migration completed successfully!")
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
conn.rollback()
|
|
68
|
+
print(f"Migration failed: {e}")
|
|
69
|
+
raise
|
|
70
|
+
finally:
|
|
71
|
+
conn.close()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def check_and_migrate(db_path: str):
|
|
75
|
+
"""Check database version and migrate if needed."""
|
|
76
|
+
if not Path(db_path).exists():
|
|
77
|
+
# New database, no migration needed
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
migrate_to_v2(db_path)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"Warning: Could not migrate database: {e}")
|
|
84
|
+
print("You may need to delete the old database and start fresh.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|