First commit
This commit is contained in:
commit
bdc97d621d
38
README.md
Normal file
38
README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Generating SQLite database documentation with Python and Doxygen #
|
||||
|
||||
Simple scripts for SQLite database documenting.
|
||||
|
||||
## Requirements ##
|
||||
|
||||
* Python 3
|
||||
- sqlite3 lib
|
||||
- json lib
|
||||
* Doxygen
|
||||
|
||||
## Usage ##
|
||||
|
||||
SQLite does not support table and field comments so we are using external comment source (table_comments.json).
|
||||
|
||||
```json
|
||||
{
|
||||
"table_name": {
|
||||
"comment": "Table comment",
|
||||
"fields": {
|
||||
"field_name": "Field comment",
|
||||
"field_name2": "Field comment 2"
|
||||
}
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
* `python mksqlitedoc_json.py` - generates or updates comment source (table_comments.json)
|
||||
|
||||
* `python mksqlitedoc_json.py` - generates Doxygen input file
|
||||
|
||||
* `doxygen` - generates Doxygen documentation
|
||||
|
||||
## Result ##
|
||||
|
||||

|
||||
|
||||
Python is not my strong side
|
2434
example/Doxyfile
Normal file
2434
example/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
BIN
example/database.db
Normal file
BIN
example/database.db
Normal file
Binary file not shown.
1
example/input/.gitignore
vendored
Normal file
1
example/input/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/database.dox
|
7
example/input/index.dox
Normal file
7
example/input/index.dox
Normal file
@ -0,0 +1,7 @@
|
||||
/*!
|
||||
* \mainpage Main page
|
||||
*
|
||||
*
|
||||
* \ref database_structure
|
||||
*
|
||||
*/
|
2
example/mkdocs.bat
Normal file
2
example/mkdocs.bat
Normal file
@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
python ..\mksqlitedoc_json.py && python ..\mksqlitedoc.py && doxygen
|
2
example/mkdocs.sh
Normal file
2
example/mkdocs.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
python ../mksqlitedoc_json.py && python ../mksqlitedoc.py && doxygen
|
18
example/table_comments.json
Normal file
18
example/table_comments.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"roles": {
|
||||
"comment": "Roles table description",
|
||||
"fields": {
|
||||
"id": "Role unique ID",
|
||||
"description": "Role description"
|
||||
}
|
||||
},
|
||||
"users": {
|
||||
"comment": "Users table description",
|
||||
"fields": {
|
||||
"id": "",
|
||||
"name": "User name",
|
||||
"role": "User role ID",
|
||||
"registration_date": "User registration date"
|
||||
}
|
||||
}
|
||||
}
|
101
mksqlitedoc.py
Normal file
101
mksqlitedoc.py
Normal file
@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ###################################################### #
|
||||
# Author: MultiMote #
|
||||
# Description: pysqlitedoc dox generator #
|
||||
# URL: https://github.com/MultiMote/pysqlitedoc #
|
||||
# ###################################################### #
|
||||
|
||||
import sqlite3
|
||||
import json
|
||||
|
||||
|
||||
db_path = "database.db"
|
||||
dox_path = "input/database.dox"
|
||||
comments_path = "table_comments.json"
|
||||
|
||||
|
||||
db = sqlite3.connect(db_path)
|
||||
output = open(dox_path, "w", encoding='utf-8')
|
||||
comments = {}
|
||||
|
||||
try:
|
||||
json_file = open(comments_path, "r", encoding='utf-8')
|
||||
comments = json.load(json_file)
|
||||
json_file.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
db.row_factory = sqlite3.Row
|
||||
|
||||
output.write("/*!\n")
|
||||
output.write(" * \\page database_structure Database structure\n")
|
||||
|
||||
for tabledef in db.execute("SELECT * FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite\\_%' ESCAPE '\\' ORDER BY name "):
|
||||
tablename = tabledef["name"]
|
||||
|
||||
output.write(" *\n")
|
||||
output.write(" *\n")
|
||||
output.write(" * \\section db_table_{} \"{}\" table\n".format(tablename, tablename))
|
||||
|
||||
try:
|
||||
output.write(" *\n")
|
||||
output.write(" * {}\n".format(comments.get(tablename).get("comment", "")))
|
||||
output.write(" *\n")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
output.write(" * <table>\n")
|
||||
output.write(" * <tr>\n")
|
||||
output.write(" * <th>Field</th>\n")
|
||||
output.write(" * <th>Type</th>\n")
|
||||
output.write(" * <th title=\"Primary key\">PK</th>\n")
|
||||
output.write(" * <th title=\"Required (NOT NULL)\">NN</th>\n")
|
||||
output.write(" * <th>Default</th>\n")
|
||||
output.write(" * <th>Description</th>\n")
|
||||
output.write(" * </tr>\n")
|
||||
|
||||
for field in db.execute("PRAGMA table_info({})".format(tablename)):
|
||||
output.write(" * <tr>\n")
|
||||
output.write(" * <td>{}</td>\n".format(field["name"]))
|
||||
output.write(" * <td>{}</td>\n".format(field["type"]))
|
||||
output.write(" * <td style=\"text-align:center\">{}</td>\n".format("●" if field["pk"] == 1 else ""))
|
||||
output.write(" * <td style=\"text-align:center\">{}</td>\n".format("●" if field["notnull"] == 1 else ""))
|
||||
output.write(" * <td style=\"text-align:center\">{}</td>\n".format("`NULL`" if field["dflt_value"] is None else field["dflt_value"]))
|
||||
|
||||
try:
|
||||
output.write(" * <td>{}</td>\n".format(comments.get(tablename).get("fields").get(field["name"], "")))
|
||||
except AttributeError:
|
||||
output.write(" * <td></td>\n")
|
||||
|
||||
output.write(" * </tr>\n")
|
||||
|
||||
output.write(" * </table>\n")
|
||||
|
||||
foreign_keys = db.execute("PRAGMA foreign_key_list({})".format(tablename)).fetchall()
|
||||
|
||||
if len(foreign_keys) > 0:
|
||||
output.write(" * <h2>\"{}\" foreign keys</h2>\n".format(tablename))
|
||||
output.write(" * <table>\n")
|
||||
output.write(" * <tr>\n")
|
||||
output.write(" * <th>Local field</th>\n")
|
||||
output.write(" * <th>Reference table</th>\n")
|
||||
output.write(" * <th>Reference field</th>\n")
|
||||
output.write(" * <th>On update</th>\n")
|
||||
output.write(" * <th>On delete</th>\n")
|
||||
output.write(" * </tr>\n")
|
||||
for fkey in foreign_keys:
|
||||
output.write(" * <tr>\n")
|
||||
output.write(" * <td>{}</td>\n".format(fkey["from"]))
|
||||
output.write(" * <td>{}</td>\n".format(fkey["table"]))
|
||||
output.write(" * <td>{}</td>\n".format(fkey["to"]))
|
||||
output.write(" * <td>{}</td>\n".format(fkey["on_update"]))
|
||||
output.write(" * <td>{}</td>\n".format(fkey["on_delete"]))
|
||||
output.write(" * </tr>\n")
|
||||
|
||||
output.write(" * </table>\n")
|
||||
|
||||
output.write("*/\n")
|
||||
|
||||
output.close()
|
47
mksqlitedoc_json.py
Normal file
47
mksqlitedoc_json.py
Normal file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ###################################################### #
|
||||
# Author: MultiMote #
|
||||
# Description: pysqlitedoc table_comments.json generator #
|
||||
# URL: https://github.com/MultiMote/pysqlitedoc #
|
||||
# ###################################################### #
|
||||
|
||||
import sqlite3
|
||||
import json
|
||||
|
||||
db_path = "database.db"
|
||||
comments_path = "table_comments.json"
|
||||
|
||||
|
||||
db = sqlite3.connect(db_path)
|
||||
json_data = {}
|
||||
|
||||
try:
|
||||
json_file = open(comments_path, "r", encoding='utf-8')
|
||||
json_data = json.load(json_file)
|
||||
json_file.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
db.row_factory = sqlite3.Row
|
||||
|
||||
for tabledef in db.execute("SELECT * FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite\\_%' ESCAPE '\\' "):
|
||||
tablename = tabledef["name"]
|
||||
|
||||
if json_data.get(tablename) is None:
|
||||
json_data[tablename] = {}
|
||||
|
||||
if json_data.get(tablename).get("comment") is None:
|
||||
json_data[tablename]["comment"] = ""
|
||||
|
||||
if json_data.get(tablename).get("fields") is None:
|
||||
json_data[tablename]["fields"] = {}
|
||||
|
||||
for field in db.execute("PRAGMA table_info({})".format(tablename)):
|
||||
if json_data.get(tablename).get("fields").get(field["name"]) is None:
|
||||
json_data[tablename]["fields"][field["name"]] = ""
|
||||
|
||||
json_file = open(comments_path, "w", encoding='utf-8')
|
||||
json.dump(json_data, json_file, indent=4)
|
||||
json_file.close()
|
BIN
screenshots/output.png
Normal file
BIN
screenshots/output.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 24 KiB |
Loading…
x
Reference in New Issue
Block a user