change most double quotes to single quotes
This commit is contained in:
@@ -20,35 +20,35 @@ import json
|
|||||||
|
|
||||||
def create_default_avatar():
|
def create_default_avatar():
|
||||||
if Avatars.count() == 0:
|
if Avatars.count() == 0:
|
||||||
print("Creating default avatar reference")
|
print('Creating default avatar reference')
|
||||||
Avatars.create({
|
Avatars.create({
|
||||||
"file_path": "/static/avatars/default.webp",
|
'file_path': '/static/avatars/default.webp',
|
||||||
"uploaded_at": int(time.time())
|
'uploaded_at': int(time.time())
|
||||||
})
|
})
|
||||||
|
|
||||||
def create_admin():
|
def create_admin():
|
||||||
username = "admin"
|
username = 'admin'
|
||||||
if Users.count({"username": username}) == 0:
|
if Users.count({'username': username}) == 0:
|
||||||
print("!!!!!Creating admin account!!!!!")
|
print('!!!!!Creating admin account!!!!!')
|
||||||
password_length = 16
|
password_length = 16
|
||||||
password = secrets.token_urlsafe(password_length)
|
password = secrets.token_urlsafe(password_length)
|
||||||
hashed = digest(password)
|
hashed = digest(password)
|
||||||
Users.create({
|
Users.create({
|
||||||
"username": username,
|
'username': username,
|
||||||
"password_hash": hashed,
|
'password_hash': hashed,
|
||||||
"permission": PermissionLevel.ADMIN.value,
|
'permission': PermissionLevel.ADMIN.value,
|
||||||
})
|
})
|
||||||
print(f"!!!!!Administrator account created, use '{username}' as the login and '{password}' as the password. This will only be shown once!!!!!")
|
print(f"!!!!!Administrator account created, use '{username}' as the login and '{password}' as the password. This will only be shown once!!!!!")
|
||||||
|
|
||||||
def create_deleted_user():
|
def create_deleted_user():
|
||||||
username = "DeletedUser"
|
username = 'DeletedUser'
|
||||||
if Users.count({"username": username.lower()}) == 0:
|
if Users.count({'username': username.lower()}) == 0:
|
||||||
print("Creating DeletedUser")
|
print('Creating DeletedUser')
|
||||||
Users.create({
|
Users.create({
|
||||||
"username": username.lower(),
|
'username': username.lower(),
|
||||||
"display_name": username,
|
'display_name': username,
|
||||||
"password_hash": "",
|
'password_hash': '',
|
||||||
"permission": PermissionLevel.SYSTEM.value,
|
'permission': PermissionLevel.SYSTEM.value,
|
||||||
})
|
})
|
||||||
|
|
||||||
def reparse_babycode():
|
def reparse_babycode():
|
||||||
@@ -167,26 +167,26 @@ def create_app():
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print('No configuration file found, leaving defaults.')
|
print('No configuration file found, leaving defaults.')
|
||||||
|
|
||||||
if os.getenv("PYROM_PROD") is None:
|
if os.getenv('PYROM_PROD') is None:
|
||||||
app.static_folder = os.path.join(os.path.dirname(__file__), "../data/static")
|
app.static_folder = os.path.join(os.path.dirname(__file__), '../data/static')
|
||||||
app.debug = True
|
app.debug = True
|
||||||
app.config["DB_PATH"] = "data/db/db.dev.sqlite"
|
app.config['DB_PATH'] = 'data/db/db.dev.sqlite'
|
||||||
app.config["SERVER_NAME"] = "localhost:8080"
|
app.config['SERVER_NAME'] = 'localhost:8080'
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
else:
|
else:
|
||||||
app.config["DB_PATH"] = "data/db/db.prod.sqlite"
|
app.config['DB_PATH'] = 'data/db/db.prod.sqlite'
|
||||||
if not app.config["SERVER_NAME"]:
|
if not app.config['SERVER_NAME']:
|
||||||
raise SiteNameMissingException()
|
raise SiteNameMissingException()
|
||||||
|
|
||||||
app.config["SECRET_KEY"] = os.getenv("FLASK_SECRET_KEY")
|
app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY')
|
||||||
|
|
||||||
app.config['AVATAR_UPLOAD_PATH'] = 'data/static/avatars/'
|
app.config['AVATAR_UPLOAD_PATH'] = 'data/static/avatars/'
|
||||||
app.config['BADGES_PATH'] = 'data/static/badges/'
|
app.config['BADGES_PATH'] = 'data/static/badges/'
|
||||||
app.config['BADGES_UPLOAD_PATH'] = 'data/static/badges/user/'
|
app.config['BADGES_UPLOAD_PATH'] = 'data/static/badges/user/'
|
||||||
app.config['MAX_CONTENT_LENGTH'] = 3 * 1000 * 1000 # 3M total, subject to further limits per route
|
app.config['MAX_CONTENT_LENGTH'] = 3 * 1000 * 1000 # 3M total, subject to further limits per route
|
||||||
|
|
||||||
os.makedirs(os.path.dirname(app.config["DB_PATH"]), exist_ok = True)
|
os.makedirs(os.path.dirname(app.config['DB_PATH']), exist_ok = True)
|
||||||
os.makedirs(os.path.dirname(app.config["BADGES_UPLOAD_PATH"]), exist_ok = True)
|
os.makedirs(os.path.dirname(app.config['BADGES_UPLOAD_PATH']), exist_ok = True)
|
||||||
|
|
||||||
if app.config['CACHE_TYPE'] == 'FileSystemCache':
|
if app.config['CACHE_TYPE'] == 'FileSystemCache':
|
||||||
cache_dir = app.config.get('CACHE_DIR', 'data/_cached')
|
cache_dir = app.config.get('CACHE_DIR', 'data/_cached')
|
||||||
@@ -217,21 +217,21 @@ def create_app():
|
|||||||
def make_session_permanent():
|
def make_session_permanent():
|
||||||
session.permanent = True
|
session.permanent = True
|
||||||
|
|
||||||
commit = ""
|
commit = ''
|
||||||
with open('.git/refs/heads/main') as f:
|
with open('.git/refs/heads/main') as f:
|
||||||
commit = f.read().strip()
|
commit = f.read().strip()
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_constants():
|
def inject_constants():
|
||||||
return {
|
return {
|
||||||
"InfoboxHTMLClass": InfoboxHTMLClass,
|
'InfoboxHTMLClass': InfoboxHTMLClass,
|
||||||
"InfoboxKind": InfoboxKind,
|
'InfoboxKind': InfoboxKind,
|
||||||
"PermissionLevel": PermissionLevel,
|
'PermissionLevel': PermissionLevel,
|
||||||
"__commit": commit,
|
'__commit': commit,
|
||||||
"__emoji": EMOJI,
|
'__emoji': EMOJI,
|
||||||
"REACTION_EMOJI": REACTION_EMOJI,
|
'REACTION_EMOJI': REACTION_EMOJI,
|
||||||
"MOTD_BANNED_TAGS": MOTD_BANNED_TAGS,
|
'MOTD_BANNED_TAGS': MOTD_BANNED_TAGS,
|
||||||
"SIG_BANNED_TAGS": SIG_BANNED_TAGS,
|
'SIG_BANNED_TAGS': SIG_BANNED_TAGS,
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
@@ -241,18 +241,18 @@ def create_app():
|
|||||||
'get_time_now': lambda: int(time.time()),
|
'get_time_now': lambda: int(time.time()),
|
||||||
}
|
}
|
||||||
|
|
||||||
@app.template_filter("ts_datetime")
|
@app.template_filter('ts_datetime')
|
||||||
def ts_datetime(ts, format):
|
def ts_datetime(ts, format):
|
||||||
return datetime.utcfromtimestamp(ts or int(time.time())).strftime(format)
|
return datetime.utcfromtimestamp(ts or int(time.time())).strftime(format)
|
||||||
|
|
||||||
@app.template_filter("pluralize")
|
@app.template_filter('pluralize')
|
||||||
def pluralize(subject, num=1, singular = "", plural = "s"):
|
def pluralize(subject, num=1, singular = '', plural = 's'):
|
||||||
if int(num) == 1:
|
if int(num) == 1:
|
||||||
return subject + singular
|
return subject + singular
|
||||||
|
|
||||||
return subject + plural
|
return subject + plural
|
||||||
|
|
||||||
@app.template_filter("permission_string")
|
@app.template_filter('permission_string')
|
||||||
def permission_string(term):
|
def permission_string(term):
|
||||||
return permission_level_string(term)
|
return permission_level_string(term)
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ def create_app():
|
|||||||
# sooo... /shrug
|
# sooo... /shrug
|
||||||
@app.template_filter('cachebust')
|
@app.template_filter('cachebust')
|
||||||
def cachebust(subject):
|
def cachebust(subject):
|
||||||
return f"{subject}?v={str(int(time.time()))}"
|
return f'{subject}?v={str(int(time.time()))}'
|
||||||
|
|
||||||
@app.template_filter('theme_name')
|
@app.template_filter('theme_name')
|
||||||
def get_theme_name(subject: str):
|
def get_theme_name(subject: str):
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ class InfoboxKind(IntEnum):
|
|||||||
ERROR = 3
|
ERROR = 3
|
||||||
|
|
||||||
InfoboxHTMLClass = {
|
InfoboxHTMLClass = {
|
||||||
InfoboxKind.INFO: "",
|
InfoboxKind.INFO: '',
|
||||||
InfoboxKind.LOCK: "warn",
|
InfoboxKind.LOCK: 'warn',
|
||||||
InfoboxKind.WARN: "warn",
|
InfoboxKind.WARN: 'warn',
|
||||||
InfoboxKind.ERROR: "critical",
|
InfoboxKind.ERROR: 'critical',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ def run_migrations():
|
|||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
if len(MIGRATIONS) == 0:
|
if len(MIGRATIONS) == 0:
|
||||||
print("No migrations defined.")
|
print('No migrations defined.')
|
||||||
return
|
return
|
||||||
print("Running migrations...")
|
print('Running migrations...')
|
||||||
ran = 0
|
ran = 0
|
||||||
completed = {int(row["id"]) for row in db.query("SELECT id FROM _migrations")}
|
completed = {int(row['id']) for row in db.query('SELECT id FROM _migrations')}
|
||||||
to_run = {idx: migration_obj for idx, migration_obj in enumerate(MIGRATIONS) if idx not in completed}
|
to_run = {idx: migration_obj for idx, migration_obj in enumerate(MIGRATIONS) if idx not in completed}
|
||||||
if not to_run:
|
if not to_run:
|
||||||
print('No migrations need to run.')
|
print('No migrations need to run.')
|
||||||
@@ -74,4 +74,4 @@ def run_migrations():
|
|||||||
|
|
||||||
db.execute('INSERT INTO _migrations (id) VALUES (?)', migration_id)
|
db.execute('INSERT INTO _migrations (id) VALUES (?)', migration_id)
|
||||||
ran += 1
|
ran += 1
|
||||||
print(f"Ran {ran} migrations.")
|
print(f'Ran {ran} migrations.')
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ from flask import current_app
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
class Users(Model):
|
class Users(Model):
|
||||||
table = "users"
|
table = 'users'
|
||||||
|
|
||||||
def get_avatar_url(self):
|
def get_avatar_url(self):
|
||||||
return Avatars.find({"id": self.avatar_id}).file_path
|
return Avatars.find({'id': self.avatar_id}).file_path
|
||||||
|
|
||||||
def is_default_avatar(self):
|
def is_default_avatar(self):
|
||||||
return int(Avatars.find({'id': self.avatar_id}).id) == 1
|
return int(Avatars.find({'id': self.avatar_id}).id) == 1
|
||||||
@@ -104,7 +104,7 @@ class Users(Model):
|
|||||||
|
|
||||||
|
|
||||||
class Topics(Model):
|
class Topics(Model):
|
||||||
table = "topics"
|
table = 'topics'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_list(_cls):
|
def get_list(_cls):
|
||||||
@@ -131,12 +131,12 @@ class Topics(Model):
|
|||||||
topics.sort_order ASC"""
|
topics.sort_order ASC"""
|
||||||
return db.query(q)
|
return db.query(q)
|
||||||
|
|
||||||
def get_threads(self, per_page, page, sort_by = "activity"):
|
def get_threads(self, per_page, page, sort_by = 'activity'):
|
||||||
order_clause = ""
|
order_clause = ''
|
||||||
if sort_by == "thread":
|
if sort_by == 'thread':
|
||||||
order_clause = "ORDER BY threads.is_stickied DESC, threads.created_at DESC"
|
order_clause = 'ORDER BY threads.is_stickied DESC, threads.created_at DESC'
|
||||||
else:
|
else:
|
||||||
order_clause = "ORDER BY threads.is_stickied DESC, latest_post_created_at DESC"
|
order_clause = 'ORDER BY threads.is_stickied DESC, latest_post_created_at DESC'
|
||||||
|
|
||||||
q = """
|
q = """
|
||||||
SELECT
|
SELECT
|
||||||
@@ -168,7 +168,7 @@ class Topics(Model):
|
|||||||
users u ON u.id = posts.user_id
|
users u ON u.id = posts.user_id
|
||||||
WHERE
|
WHERE
|
||||||
threads.topic_id = ?
|
threads.topic_id = ?
|
||||||
""" + order_clause + " LIMIT ? OFFSET ?"
|
""" + order_clause + ' LIMIT ? OFFSET ?'
|
||||||
|
|
||||||
return db.query(q, self.id, per_page, (page - 1) * per_page)
|
return db.query(q, self.id, per_page, (page - 1) * per_page)
|
||||||
|
|
||||||
@@ -206,10 +206,10 @@ class Topics(Model):
|
|||||||
|
|
||||||
|
|
||||||
class Threads(Model):
|
class Threads(Model):
|
||||||
table = "threads"
|
table = 'threads'
|
||||||
|
|
||||||
def get_posts(self, limit, offset):
|
def get_posts(self, limit, offset):
|
||||||
q = Posts.FULL_POSTS_QUERY + " WHERE posts.thread_id = ? ORDER BY posts.created_at ASC LIMIT ? OFFSET ?"
|
q = Posts.FULL_POSTS_QUERY + ' WHERE posts.thread_id = ? ORDER BY posts.created_at ASC LIMIT ? OFFSET ?'
|
||||||
return db.query(q, self.id, limit, offset)
|
return db.query(q, self.id, limit, offset)
|
||||||
|
|
||||||
def get_posts_rss(self):
|
def get_posts_rss(self):
|
||||||
@@ -263,23 +263,23 @@ class Posts(Model):
|
|||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
user_badges ON users.id = user_badges.user_id"""
|
user_badges ON users.id = user_badges.user_id"""
|
||||||
|
|
||||||
table = "posts"
|
table = 'posts'
|
||||||
|
|
||||||
def get_full_post_view(self):
|
def get_full_post_view(self):
|
||||||
q = f'{self.FULL_POSTS_QUERY} WHERE posts.id = ?'
|
q = f'{self.FULL_POSTS_QUERY} WHERE posts.id = ?'
|
||||||
return db.fetch_one(q, self.id)
|
return db.fetch_one(q, self.id)
|
||||||
|
|
||||||
class PostHistory(Model):
|
class PostHistory(Model):
|
||||||
table = "post_history"
|
table = 'post_history'
|
||||||
|
|
||||||
class Sessions(Model):
|
class Sessions(Model):
|
||||||
table = "sessions"
|
table = 'sessions'
|
||||||
|
|
||||||
class Avatars(Model):
|
class Avatars(Model):
|
||||||
table = "avatars"
|
table = 'avatars'
|
||||||
|
|
||||||
class Subscriptions(Model):
|
class Subscriptions(Model):
|
||||||
table = "subscriptions"
|
table = 'subscriptions'
|
||||||
|
|
||||||
def get_unread_count(self):
|
def get_unread_count(self):
|
||||||
q = """SELECT COUNT(*) AS unread_count
|
q = """SELECT COUNT(*) AS unread_count
|
||||||
@@ -316,15 +316,15 @@ class APIRateLimits(Model):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
class Reactions(Model):
|
class Reactions(Model):
|
||||||
table = "reactions"
|
table = 'reactions'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def for_post(cls, post_id):
|
def for_post(cls, post_id):
|
||||||
qb = db.QueryBuilder(cls.table)\
|
qb = db.QueryBuilder(cls.table)\
|
||||||
.select("reaction_text, COUNT(*) as c")\
|
.select('reaction_text, COUNT(*) as c')\
|
||||||
.where({"post_id": post_id})\
|
.where({'post_id': post_id})\
|
||||||
.group_by("reaction_text")\
|
.group_by('reaction_text')\
|
||||||
.order_by("c", False)
|
.order_by('c', False)
|
||||||
result = qb.all()
|
result = qb.all()
|
||||||
return result if result else []
|
return result if result else []
|
||||||
|
|
||||||
@@ -342,7 +342,7 @@ class Reactions(Model):
|
|||||||
|
|
||||||
|
|
||||||
class PasswordResetLinks(Model):
|
class PasswordResetLinks(Model):
|
||||||
table = "password_reset_links"
|
table = 'password_reset_links'
|
||||||
|
|
||||||
|
|
||||||
class InviteKeys(Model):
|
class InviteKeys(Model):
|
||||||
@@ -446,7 +446,7 @@ class BadgeUploads(Model):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_for_user(cls, user_id):
|
def get_for_user(cls, user_id):
|
||||||
q = "SELECT * FROM badge_uploads WHERE user_id = ? OR user_id IS NULL ORDER BY uploaded_at"
|
q = 'SELECT * FROM badge_uploads WHERE user_id = ? OR user_id IS NULL ORDER BY uploaded_at'
|
||||||
res = db.query(q, int(user_id))
|
res = db.query(q, int(user_id))
|
||||||
return [cls.from_data(row) for row in res]
|
return [cls.from_data(row) for row in res]
|
||||||
|
|
||||||
|
|||||||
@@ -159,39 +159,39 @@ SCHEMA = [
|
|||||||
)""",
|
)""",
|
||||||
|
|
||||||
# INDEXES
|
# INDEXES
|
||||||
"CREATE INDEX IF NOT EXISTS idx_post_history_post_id ON post_history(post_id)",
|
'CREATE INDEX IF NOT EXISTS idx_post_history_post_id ON post_history(post_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_posts_thread ON posts(thread_id, created_at, id)",
|
'CREATE INDEX IF NOT EXISTS idx_posts_thread ON posts(thread_id, created_at, id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_posts_thread_id ON posts(thread_id)",
|
'CREATE INDEX IF NOT EXISTS idx_posts_thread_id ON posts(thread_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_rate_limit_user_method ON api_rate_limits (user_id, method)",
|
'CREATE INDEX IF NOT EXISTS idx_rate_limit_user_method ON api_rate_limits (user_id, method)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_subscription_user_thread ON subscriptions (user_id, thread_id)",
|
'CREATE INDEX IF NOT EXISTS idx_subscription_user_thread ON subscriptions (user_id, thread_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_threads_slug ON threads(slug)",
|
'CREATE INDEX IF NOT EXISTS idx_threads_slug ON threads(slug)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_threads_topic_id ON threads(topic_id)",
|
'CREATE INDEX IF NOT EXISTS idx_threads_topic_id ON threads(topic_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_topics_slug ON topics(slug)",
|
'CREATE INDEX IF NOT EXISTS idx_topics_slug ON topics(slug)',
|
||||||
"CREATE INDEX IF NOT EXISTS session_keys ON sessions(key)",
|
'CREATE INDEX IF NOT EXISTS session_keys ON sessions(key)',
|
||||||
"CREATE INDEX IF NOT EXISTS sessions_user_id ON sessions(user_id)",
|
'CREATE INDEX IF NOT EXISTS sessions_user_id ON sessions(user_id)',
|
||||||
|
|
||||||
"CREATE INDEX IF NOT EXISTS reaction_post_text ON reactions(post_id, reaction_text)",
|
'CREATE INDEX IF NOT EXISTS reaction_post_text ON reactions(post_id, reaction_text)',
|
||||||
"CREATE INDEX IF NOT EXISTS reaction_user_post_text ON reactions(user_id, post_id, reaction_text)",
|
'CREATE INDEX IF NOT EXISTS reaction_user_post_text ON reactions(user_id, post_id, reaction_text)',
|
||||||
|
|
||||||
"CREATE INDEX IF NOT EXISTS idx_bookmark_collections_user_id ON bookmark_collections(user_id)",
|
'CREATE INDEX IF NOT EXISTS idx_bookmark_collections_user_id ON bookmark_collections(user_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_bookmark_collections_user_default ON bookmark_collections(user_id, is_default) WHERE is_default = 1",
|
'CREATE INDEX IF NOT EXISTS idx_bookmark_collections_user_default ON bookmark_collections(user_id, is_default) WHERE is_default = 1',
|
||||||
|
|
||||||
"CREATE INDEX IF NOT EXISTS idx_bookmarked_posts_collection ON bookmarked_posts(collection_id)",
|
'CREATE INDEX IF NOT EXISTS idx_bookmarked_posts_collection ON bookmarked_posts(collection_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_bookmarked_posts_post ON bookmarked_posts(post_id)",
|
'CREATE INDEX IF NOT EXISTS idx_bookmarked_posts_post ON bookmarked_posts(post_id)',
|
||||||
|
|
||||||
"CREATE INDEX IF NOT EXISTS idx_bookmarked_threads_collection ON bookmarked_threads(collection_id)",
|
'CREATE INDEX IF NOT EXISTS idx_bookmarked_threads_collection ON bookmarked_threads(collection_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_bookmarked_threads_thread ON bookmarked_threads(thread_id)",
|
'CREATE INDEX IF NOT EXISTS idx_bookmarked_threads_thread ON bookmarked_threads(thread_id)',
|
||||||
|
|
||||||
"CREATE INDEX IF NOT EXISTS idx_mentioned_user ON mentions(mentioned_user_id)",
|
'CREATE INDEX IF NOT EXISTS idx_mentioned_user ON mentions(mentioned_user_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_mention_revision_id ON mentions(revision_id)",
|
'CREATE INDEX IF NOT EXISTS idx_mention_revision_id ON mentions(revision_id)',
|
||||||
|
|
||||||
"CREATE INDEX IF NOT EXISTS idx_badge_upload_user ON badge_uploads(user_id)",
|
'CREATE INDEX IF NOT EXISTS idx_badge_upload_user ON badge_uploads(user_id)',
|
||||||
"CREATE INDEX IF NOT EXISTS idx_badge_user ON badges(user_id)",
|
'CREATE INDEX IF NOT EXISTS idx_badge_user ON badges(user_id)',
|
||||||
]
|
]
|
||||||
|
|
||||||
def create():
|
def create():
|
||||||
print("Creating schema...")
|
print('Creating schema...')
|
||||||
with db.transaction():
|
with db.transaction():
|
||||||
for stmt in SCHEMA:
|
for stmt in SCHEMA:
|
||||||
db.execute(stmt)
|
db.execute(stmt)
|
||||||
print("Schema completed.")
|
print('Schema completed.')
|
||||||
|
|||||||
Reference in New Issue
Block a user