Start switching to sqlalchemy

This commit is contained in:
th3r00t
2022-11-11 23:53:13 -05:00
parent 908e5e64b7
commit 3f83b9d3ef
4 changed files with 193 additions and 71 deletions

5
Pipfile vendored
View File

@@ -9,11 +9,12 @@ websockets = "*"
loguru = "*" loguru = "*"
pypdf2 = "*" pypdf2 = "*"
bs4 = "*" bs4 = "*"
mobi = "*"
mobi-python = "*"
requests = "*" requests = "*"
psycopg2-binary = "*" psycopg2-binary = "*"
django-debug-toolbar = "*" django-debug-toolbar = "*"
sqlalchemy = "*"
mobi-python = "*"
psycopg = "*"
[dev-packages] [dev-packages]

138
Pipfile.lock generated vendored
View File

@@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "1d519610b10185393198e5436b2f833eb38e14a7c9e4ccf25a413de6533ddf96" "sha256": "0c1aaa2295d95de322b5d3125570ec055e16803f0f6f312a0184e24c83a6166e"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@@ -71,6 +71,72 @@
"index": "pypi", "index": "pypi",
"version": "==3.7.0" "version": "==3.7.0"
}, },
"greenlet": {
"hashes": [
"sha256:0109af1138afbfb8ae647e31a2b1ab030f58b21dd8528c27beaeb0093b7938a9",
"sha256:0459d94f73265744fee4c2d5ec44c6f34aa8a31017e6e9de770f7bcf29710be9",
"sha256:04957dc96669be041e0c260964cfef4c77287f07c40452e61abe19d647505581",
"sha256:0722c9be0797f544a3ed212569ca3fe3d9d1a1b13942d10dd6f0e8601e484d26",
"sha256:097e3dae69321e9100202fc62977f687454cd0ea147d0fd5a766e57450c569fd",
"sha256:0b493db84d124805865adc587532ebad30efa68f79ad68f11b336e0a51ec86c2",
"sha256:13ba6e8e326e2116c954074c994da14954982ba2795aebb881c07ac5d093a58a",
"sha256:13ebf93c343dd8bd010cd98e617cb4c1c1f352a0cf2524c82d3814154116aa82",
"sha256:1407fe45246632d0ffb7a3f4a520ba4e6051fc2cbd61ba1f806900c27f47706a",
"sha256:1bf633a50cc93ed17e494015897361010fc08700d92676c87931d3ea464123ce",
"sha256:2d0bac0385d2b43a7bd1d651621a4e0f1380abc63d6fb1012213a401cbd5bf8f",
"sha256:3001d00eba6bbf084ae60ec7f4bb8ed375748f53aeaefaf2a37d9f0370558524",
"sha256:356e4519d4dfa766d50ecc498544b44c0249b6de66426041d7f8b751de4d6b48",
"sha256:38255a3f1e8942573b067510f9611fc9e38196077b0c8eb7a8c795e105f9ce77",
"sha256:3d75b8d013086b08e801fbbb896f7d5c9e6ccd44f13a9241d2bf7c0df9eda928",
"sha256:41b825d65f31e394b523c84db84f9383a2f7eefc13d987f308f4663794d2687e",
"sha256:42e602564460da0e8ee67cb6d7236363ee5e131aa15943b6670e44e5c2ed0f67",
"sha256:4aeaebcd91d9fee9aa768c1b39cb12214b30bf36d2b7370505a9f2165fedd8d9",
"sha256:4c8b1c43e75c42a6cafcc71defa9e01ead39ae80bd733a2608b297412beede68",
"sha256:4d37990425b4687ade27810e3b1a1c37825d242ebc275066cfee8cb6b8829ccd",
"sha256:4f09b0010e55bec3239278f642a8a506b91034f03a4fb28289a7d448a67f1515",
"sha256:505138d4fa69462447a562a7c2ef723c6025ba12ac04478bc1ce2fcc279a2db5",
"sha256:5067920de254f1a2dee8d3d9d7e4e03718e8fd2d2d9db962c8c9fa781ae82a39",
"sha256:56961cfca7da2fdd178f95ca407fa330c64f33289e1804b592a77d5593d9bd94",
"sha256:5a8e05057fab2a365c81abc696cb753da7549d20266e8511eb6c9d9f72fe3e92",
"sha256:659f167f419a4609bc0516fb18ea69ed39dbb25594934bd2dd4d0401660e8a1e",
"sha256:662e8f7cad915ba75d8017b3e601afc01ef20deeeabf281bd00369de196d7726",
"sha256:6f61d71bbc9b4a3de768371b210d906726535d6ca43506737682caa754b956cd",
"sha256:72b00a8e7c25dcea5946692a2485b1a0c0661ed93ecfedfa9b6687bd89a24ef5",
"sha256:811e1d37d60b47cb8126e0a929b58c046251f28117cb16fcd371eed61f66b764",
"sha256:81b0ea3715bf6a848d6f7149d25bf018fd24554a4be01fcbbe3fdc78e890b955",
"sha256:88c8d517e78acdf7df8a2134a3c4b964415b575d2840a2746ddb1cc6175f8608",
"sha256:8dca09dedf1bd8684767bc736cc20c97c29bc0c04c413e3276e0962cd7aeb148",
"sha256:974a39bdb8c90a85982cdb78a103a32e0b1be986d411303064b28a80611f6e51",
"sha256:9e112e03d37987d7b90c1e98ba5e1b59e1645226d78d73282f45b326f7bddcb9",
"sha256:9e9744c657d896c7b580455e739899e492a4a452e2dd4d2b3e459f6b244a638d",
"sha256:9ed358312e63bf683b9ef22c8e442ef6c5c02973f0c2a939ec1d7b50c974015c",
"sha256:9f2c221eecb7ead00b8e3ddb913c67f75cba078fd1d326053225a3f59d850d72",
"sha256:a20d33124935d27b80e6fdacbd34205732660e0a1d35d8b10b3328179a2b51a1",
"sha256:a4c0757db9bd08470ff8277791795e70d0bf035a011a528ee9a5ce9454b6cba2",
"sha256:afe07421c969e259e9403c3bb658968702bc3b78ec0b6fde3ae1e73440529c23",
"sha256:b1992ba9d4780d9af9726bbcef6a1db12d9ab1ccc35e5773685a24b7fb2758eb",
"sha256:b23d2a46d53210b498e5b701a1913697671988f4bf8e10f935433f6e7c332fb6",
"sha256:b5e83e4de81dcc9425598d9469a624826a0b1211380ac444c7c791d4a2137c19",
"sha256:be35822f35f99dcc48152c9839d0171a06186f2d71ef76dc57fa556cc9bf6b45",
"sha256:be9e0fb2ada7e5124f5282d6381903183ecc73ea019568d6d63d33f25b2a9000",
"sha256:c140e7eb5ce47249668056edf3b7e9900c6a2e22fb0eaf0513f18a1b2c14e1da",
"sha256:c6a08799e9e88052221adca55741bf106ec7ea0710bca635c208b751f0d5b617",
"sha256:cb242fc2cda5a307a7698c93173d3627a2a90d00507bccf5bc228851e8304963",
"sha256:cce1e90dd302f45716a7715517c6aa0468af0bf38e814ad4eab58e88fc09f7f7",
"sha256:cd4ccc364cf75d1422e66e247e52a93da6a9b73cefa8cad696f3cbbb75af179d",
"sha256:d21681f09e297a5adaa73060737e3aa1279a13ecdcfcc6ef66c292cb25125b2d",
"sha256:d38ffd0e81ba8ef347d2be0772e899c289b59ff150ebbbbe05dc61b1246eb4e0",
"sha256:d566b82e92ff2e09dd6342df7e0eb4ff6275a3f08db284888dcd98134dbd4243",
"sha256:d5b0ff9878333823226d270417f24f4d06f235cb3e54d1103b71ea537a6a86ce",
"sha256:d6ee1aa7ab36475035eb48c01efae87d37936a8173fc4d7b10bb02c2d75dd8f6",
"sha256:db38f80540083ea33bdab614a9d28bcec4b54daa5aff1668d7827a9fc769ae0a",
"sha256:ea688d11707d30e212e0110a1aac7f7f3f542a259235d396f88be68b649e47d1",
"sha256:f6327b6907b4cb72f650a5b7b1be23a2aab395017aa6f1adb13069d66360eb3f",
"sha256:fb412b7db83fe56847df9c47b6fe3f13911b06339c2aa02dcc09dce8bbf582cd"
],
"markers": "python_version >= '3' and platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32')))))",
"version": "==2.0.1"
},
"idna": { "idna": {
"hashes": [ "hashes": [
"sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4",
@@ -87,13 +153,6 @@
"index": "pypi", "index": "pypi",
"version": "==0.6.0" "version": "==0.6.0"
}, },
"mobi": {
"hashes": [
"sha256:919f60c3834c5885012210afc84a03a457fb8e58587037060a095b63ac832524"
],
"index": "pypi",
"version": "==0.3.3"
},
"mobi-python": { "mobi-python": {
"hashes": [ "hashes": [
"sha256:010d0ed1933ee9bf33330ac125e55f9cb956078b6e62cbdba59b3bd753f903f3", "sha256:010d0ed1933ee9bf33330ac125e55f9cb956078b6e62cbdba59b3bd753f903f3",
@@ -102,6 +161,14 @@
"index": "pypi", "index": "pypi",
"version": "==0.0.1" "version": "==0.0.1"
}, },
"psycopg": {
"hashes": [
"sha256:6874dbaba583cc6663437604bf45f7c244b5fd702f88af6211cd5a74e8ee3a8a",
"sha256:aba61f12b11936cb25ec7bdf2d222d1ec36e4541ddc41f774ca763e0c50dd06f"
],
"index": "pypi",
"version": "==3.1.4"
},
"psycopg2-binary": { "psycopg2-binary": {
"hashes": [ "hashes": [
"sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50", "sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50",
@@ -203,6 +270,53 @@
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==2.3.2.post1" "version": "==2.3.2.post1"
}, },
"sqlalchemy": {
"hashes": [
"sha256:0c8a174f23bc021aac97bcb27fbe2ae3d4652d3d23e5768bc2ec3d44e386c7eb",
"sha256:13ce4f3a068ec4ef7598d2a77f42adc3d90c76981f5a7c198756b25c4f4a22ea",
"sha256:1d16aca30fad4753aeb4ebde564bbd4a248b9673e4f879b940f4e806a17be87f",
"sha256:23a4569d3db1ce44370d05c5ad79be4f37915fcc97387aef9da232b95db7b695",
"sha256:27479b5a1e110e64c56b18ffbf8cf99e101572a3d1a43943ea02158f1304108e",
"sha256:2fef01240d32ada9007387afd8e0b2230f99efdc4b57ca6f1d1192fca4fcf6a5",
"sha256:35dc0a5e934c41e282e019c889069b01ff4cd356b2ea452c9985e1542734cfb1",
"sha256:41df873cdae1d56fde97a1b4f6ffa118f40e4b2d6a6aa8c25c50eea31ecbeb08",
"sha256:42bff29eaecbb284f614f4bb265bb0c268625f5b93ce6268f8017811e0afbdde",
"sha256:491d94879f9ec0dea7e1cb053cd9cc65a28d2467960cf99f7b3c286590406060",
"sha256:4a791e7a1e5ac33f70a3598f8f34fdd3b60c68593bbb038baf58bc50e02d7468",
"sha256:4abda3e693d24169221ffc7aa0444ccef3dc43dfeab6ad8665d3836751cd6af7",
"sha256:529e2cc8af75811114e5ab2eb116fd71b6e252c6bdb32adbfcd5e0c5f6d5ab06",
"sha256:59bd0ae166253f7fed8c3f4f6265d2637f25d2f6614d00df34d7ee0d95d29c91",
"sha256:5d5937e1bf7921e4d1acdfad72dd98d9e7f9ea5c52aeb12b3b05b534b527692d",
"sha256:6b462c070769f0ef06ea5fe65206b970bcf2b59cb3fda2bec2f4729e1be89c13",
"sha256:736d4e706adb3c95a0a7e660073a5213dfae78ff2df6addf8ff2918c83fbeebe",
"sha256:7d6293010aa0af8bd3b0c9993259f8979db2422d6abf85a31d70ec69cb2ee4dc",
"sha256:962c7c80c54a42836c47cb0d8a53016986c8584e8d98e90e2ea723a4ed0ba85b",
"sha256:a22f46440e61d90100e0f378faac40335fb5bbf278472df0d83dc15b653b9896",
"sha256:a7fa3e57a7b0476fbcba72b231150503d53dbcbdd23f4a86be5152912a923b6e",
"sha256:aa12e27cb465b4b006ffb777624fc6023363e01cfed2d3f89d33fb6da80f6de2",
"sha256:b6fd58e25e6cdd2a131d7e97f9713f8f2142360cd40c75af8aa5b83d535f811c",
"sha256:bd80300d81d92661e2488a4bf4383f0c5dc6e7b05fa46d2823e231af4e30539a",
"sha256:c1ced2fae7a1177a36cf94d0a5567452d195d3b4d7d932dd61f123fb15ddf87b",
"sha256:c1f5bfffc3227d05d90c557b10604962f655b4a83c9f3ad507a81ac8d6847679",
"sha256:c3dde668edea70dc8d55a74d933d5446e5a97786cdd1c67c8e4971c73bd087ad",
"sha256:c628697aad7a141da8fc3fd81b4874a711cc84af172e1b1e7bbfadf760446496",
"sha256:c6de20de7c19b965c007c9da240268dde1451865099ca10f0f593c347041b845",
"sha256:c9a6e878e63286392b262d86d21fe16e6eec12b95ccb0a92c392f2b1e0acca03",
"sha256:c9b59863e2b1f1e1ebf9ee517f86cdfa82d7049c8d81ad71ab58d442b137bbe9",
"sha256:cde363fb5412ab178f1cc1e596e9cfc396464da8a4fe8e733cc6d6b4e2c23aa9",
"sha256:d05d7365c2d1df03a69d90157a3e9b3e7b62088cca8ee6686aed2598659a6e14",
"sha256:dc1e005d490c101d27657481a05765851ab795cc8aedeb8d9425595088b20736",
"sha256:ed1c950aba723b7a5b702b88f05d883607c587de918d7d8c2014fe7f55cf67e0",
"sha256:ee9613b0460dce970414cfc990ca40afe518bc139e697243fcdf890285fb30ac",
"sha256:eeb55a555eef1a9607c1635bbdddd0b8a2bb9713bcb5bc8da1e8fae8ee46d1d8",
"sha256:f5438f6c768b7e928f0463777b545965648ba0d55877afd14a4e96d2a99702e7",
"sha256:f6e036714a586f757a3e12ff0798ce9a90aa04a60cff392d8bcacc5ecf79c95e",
"sha256:fa46d86a17cccd48c6762df1a60aecf5aaa2e0c0973efacf146c637694b62ffd",
"sha256:fb9a44e7124f72b79023ab04e1c8fcd8f392939ef0d7a75beae8634e15605d30"
],
"index": "pypi",
"version": "==1.4.43"
},
"sqlparse": { "sqlparse": {
"hashes": [ "hashes": [
"sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34", "sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34",
@@ -211,6 +325,14 @@
"markers": "python_version >= '3.5'", "markers": "python_version >= '3.5'",
"version": "==0.4.3" "version": "==0.4.3"
}, },
"typing-extensions": {
"hashes": [
"sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa",
"sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"
],
"markers": "python_version < '3.11'",
"version": "==4.4.0"
},
"urllib3": { "urllib3": {
"hashes": [ "hashes": [
"sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e",

3
configure vendored
View File

@@ -1,9 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import json import json
from pathlib import Path
from django.core.management.utils import get_random_secret_key
from src.backend.lib.pyShelf import Admin
from src.backend.lib.storage import Storage from src.backend.lib.storage import Storage

View File

@@ -1,88 +1,103 @@
#!/usr/bin/python #!/usr/bin/python
import datetime import datetime
import re import re
from sqlalchemy import create_engine, text
import psycopg2 from sqlalchemy.orm import Session
class Storage: class Storage:
"""Contains all methods for system storage""" """Contains all methods for system storage"""
def __init__(self, config): def __init__(self, config):
self.sql = config["DATABASE"] self.sql = config["DATABASE"]
self.user = config["USER"] self.user = config["USER"]
self.password = config["PASSWORD"] self.password = config["PASSWORD"]
self.db_host = config["DB_HOST"] self.db_host = config["DB_HOST"]
self.db_port = config["DB_PORT"] self.db_port = config["DB_PORT"]
self.db = psycopg2.connect(database=self.sql, self.db = create_engine(f"postgresql://{self.user}:{self.password}@{self.db_host}:{self.db_port}/{self.sql}")
user=self.user,
password=self.password,
host=self.db_host)
self.config = config self.config = config
self.cursor = self.db.cursor()
def check_ownership(self, table=None): def check_ownership(self, table=None):
if table is None: if table is None:
table = "books" table = "books"
_q = "SELECT * FROM books" _q = "SELECT * FROM books"
try: try:
self.cursor.execute(_q) self.transact(_q)
except Exception as e: except Exception as e:
if e.pgcode == "42501": if e.pgcode == "42501":
_q = """ALTER TABLE public.books OWNER to pyshelf;""" _q = """ALTER TABLE public.books OWNER to pyshelf;"""
self.close()
set_perms = Storage(self.config)
try: try:
set_perms.cursor.execute(_q) self.transact(_q)
set_perms.close()
except Exception as e: except Exception as e:
self.config.logger.error(e) self.config.logger.error(e)
set_perms.close()
def transact(self, query):
try:
with Session(self.db.connect()) as _sess:
try:
_sess.execute(text(query))
_sess.commit()
except Exception:
# TODO: Raise Exception
pass
_sess.close()
return True
except Exception:
return False
def create_tables(self): def create_tables(self):
"""Create table structure""" """Create table structure"""
q_check = "SELECT * FROM books" tables = [
q_create = """CREATE TABLE books(title text, author text, "CREATE TABLE books(title text, author text, categories text null,\
categories text null, cover blob null, pages int null, progress int null, cover bytea null, pages int null, progress int null,\
file_name text)""" file_name text, book_id int NOT NULL UNIQUE PRIMARY KEY)",
try:
self.cursor.execute(q_check) "CREATE TABLE collections(collection text, book_id int,\
except psycopg2.errors.UndefinedTable: CONSTRAINT book_id FOREIGN KEY(book_id) REFERENCES books(book_id),\
self.cursor.execute(q_create) collection_id int NOT NULL UNIQUE PRIMARY KEY)"
]
for table in tables:
self.transact(table)
def insert_book(self, book): def insert_book(self, book):
""" """
Insert book in database Insert book in database
:returns: True if succeeds False if not :returns: True if succeeds False if not
""" """
q = "INSERT INTO books (title, author, cover, progress, file_name, pages, description, identifier, publisher, date, rights, tags) values (%s, %s, %s, 0, %s, 0, %s, %s, %s, %s, %s, %s);" q = "INSERT INTO books (title, author, cover, progress, file_name,\
pages, description, identifier, publisher,\
date, rights, tags) values (%s, %s, %s, 0, %s,\
0, %s, %s, %s, %s,\
%s, %s);"
try: try:
try: try:
cover_image = book[2].data cover_image = book[2].data
except: except Exception:
cover_image = book[2] cover_image = book[2]
if not book[2]: # If cover image is missing unset entry if not book[2]: # If cover image is missing unset entry
cover_image = None cover_image = None
self.cursor.execute( _query = text(q, (
q, book[0], # title
( book[1], # author
book[0], # title cover_image,
book[1], # author book[3], # file
cover_image, book[4], # descr
book[3], # file book[5], # ident
book[4], # descr book[6], # publisher
book[5], # ident datetime.datetime.now(),
book[6], # publisher book[8], # rights
datetime.datetime.now(), book[9], # tags
book[8], # rights ))
book[9], # tags self.transact(_query)
),
)
self.config.logger.info(book[0][0:80]) self.config.logger.info(book[0][0:80])
return True return True
except Exception as e: except Exception as e:
# TODO: Handle Invalid Date Exception here
breakpoint()
if e.pgcode == '22007': # psycopg2's error code for invalid date if e.pgcode == '22007': # psycopg2's error code for invalid date
book[7] = psycopg2.Date(int(book[7]), 1, 1) print(e)
self.insert_book(book) # book[7] = psycopg2.Date(int(book[7]), 1, 1)
# self.insert_book(book)
raise e raise e
def book_paths_list(self): def book_paths_list(self):
@@ -92,33 +107,19 @@ class Storage:
q = "SELECT file_name FROM books;" q = "SELECT file_name FROM books;"
self.cursor.execute(q) self.cursor.execute(q)
try: try:
# TODO: Get all rows
x = self.cursor.fetchall() x = self.cursor.fetchall()
except psycopg2.Error as e: except Exception as e:
self.config.logger.error(e) self.config.logger.error(e)
x = [] x = []
return x return x
def commit(self):
"""
Commit database transactions
"""
try:
self.db.commit()
return True
except Exception as e:
return e
def close(self):
"""
Close database connection
"""
self.db.close()
return True
def make_collections(self): def make_collections(self):
# TODO: Check this still works with the switch to sqlalchemy
_title_regx = re.compile(r"^[0-9][0-9]*|-|\ \B") _title_regx = re.compile(r"^[0-9][0-9]*|-|\ \B")
_q = "SELECT id,file_name FROM books" _q = "SELECT id,file_name FROM books"
self.cursor.execute(_q) self.cursor.execute(_q)
# TODO: Get all rows
_set = self.cursor.fetchall() _set = self.cursor.fetchall()
for book in _set: for book in _set:
path = self.config.book_path + "/" path = self.config.book_path + "/"
@@ -142,6 +143,7 @@ class Storage:
) )
try: try:
self.cursor.execute(_q_x) self.cursor.execute(_q_x)
# TODO: Get all rows
if len(self.cursor.fetchall()) < 1: if len(self.cursor.fetchall()) < 1:
self.cursor.execute("""INSERT INTO collections\ self.cursor.execute("""INSERT INTO collections\
(collection, book_id_id) VALUES ('%s',%s)""" % (collection, book_id_id) VALUES ('%s',%s)""" %