py.lib

Yohn Y. 2022-08-27 Parent:1668cc57225b

42:d9a3784f681b Go to Latest

py.lib/db/migrator.py

+ Возможность удаления cookie по полному объекту (полезно, когда выставляются особые параметры на cookie, и их не удаётся удалить по имени)

History
awgur@16 1 # coding: utf-8
awgur@16 2 """\
awgur@16 3 Инструмент миграции схемы БД.
awgur@16 4
awgur@16 5 DOC: https://ws.a0fs.net/w/ncc.ws/devel/python/modules/db_migrator/
awgur@16 6 """
awgur@16 7
awgur@16 8 from os.path import exists, join as p_join, isdir
awgur@16 9 from os import listdir
awgur@16 10
awgur@16 11
awgur@23 12 class MigrateError(Exception):
awgur@23 13 pass
awgur@16 14
awgur@16 15
awgur@16 16 class MigrateManager(object):
awgur@16 17 def __init__(self, control_table: str, migrate_env: str):
awgur@16 18 self.control_table = control_table
awgur@16 19
awgur@16 20 if not exists(migrate_env):
awgur@16 21 raise MigrateError('Migrate enviroment not found')
awgur@16 22
awgur@16 23 self.schema = p_join(migrate_env, 'schema.sql')
awgur@16 24 if not exists(self.schema):
awgur@23 25 raise MigrateError(f'Schema file not found: {self.schema}')
awgur@16 26
awgur@16 27 self.patch_dir = p_join(migrate_env, 'patch')
awgur@16 28 if not isdir(self.patch_dir):
awgur@23 29 raise MigrateError(f'Patch dir not found or not directory: {self.patch_dir}')
awgur@16 30
awgur@16 31 def get_patch_files(self, ver: int):
awgur@16 32 res = {}
awgur@16 33 for f in listdir(self.patch_dir):
awgur@16 34 if not f.lower().endswith('.sql'):
awgur@16 35 continue
awgur@16 36
awgur@16 37 _f = f.strip().split('.')
awgur@16 38
awgur@16 39 try:
awgur@16 40 _ver = int(_f[0])
awgur@16 41
awgur@16 42 except (TypeError, ValueError) as e:
awgur@23 43 raise MigrateError(f'Error on parse version "{_f[0]}" of file "{f}": {e}')
awgur@16 44
awgur@16 45 except IndexError:
awgur@23 46 raise MigrateError(f'Error on get version from filename: {f}')
awgur@16 47
awgur@16 48 if _ver in res:
awgur@23 49 raise MigrateError(f'Version duplicates on parse file: {f}')
awgur@16 50
awgur@16 51 res[_ver] = p_join(self.patch_dir, f)
awgur@16 52
awgur@16 53 for i in sorted(res.keys()):
awgur@16 54 if i > ver:
awgur@16 55 yield i, res[i]
awgur@16 56
awgur@16 57 @staticmethod
awgur@16 58 def get_commands(file):
awgur@16 59 buf = []
awgur@16 60 with open(file) as IN:
awgur@16 61 for l in IN:
awgur@16 62 if l.lstrip().startswith('--'):
awgur@16 63 if buf:
awgur@16 64 yield '\n'.join(buf)
awgur@16 65 buf[:] = []
awgur@16 66
awgur@16 67 else:
awgur@16 68 buf.append(l)
awgur@16 69
awgur@16 70 if buf:
awgur@16 71 yield '\n'.join(buf)
awgur@16 72
awgur@16 73 def init_db(self, db):
awgur@16 74 cursor = db.cursor()
awgur@16 75 for c in self.get_commands(self.schema):
awgur@19 76 cursor.execute(c)
awgur@19 77 db.commit()
awgur@16 78
awgur@16 79 db.commit()
awgur@16 80
awgur@16 81 def check(self, db):
awgur@16 82 cursor = db.cursor()
awgur@23 83 cursor.execute(f"SELECT version FROM {self.control_table}")
awgur@16 84 q = cursor.fetchone()
awgur@16 85 del cursor
awgur@16 86
awgur@16 87 if q is None:
awgur@16 88 ver = -1
awgur@16 89 else:
awgur@16 90 ver = int(q[0])
awgur@16 91
awgur@16 92 new_ver = ver
awgur@16 93 cursor = db.cursor()
awgur@16 94 for up_ver, patch_file in self.get_patch_files(ver):
awgur@16 95 new_ver = up_ver
awgur@16 96 for cmd in self.get_commands(patch_file):
awgur@16 97 cursor.execute(cmd)
awgur@16 98 db.commit()
awgur@16 99
awgur@23 100 cursor.execute(f"DELETE FROM {self.control_table}")
awgur@17 101
awgur@23 102 cursor.execute(f"""
awgur@23 103 INSERT INTO {self.control_table} (version)
awgur@23 104 VALUES ({new_ver})
awgur@23 105 """)
awgur@17 106 db.commit()
awgur@16 107
awgur@19 108 @staticmethod
awgur@19 109 def get_conn_from_my_obj(obj: object):
awgur@19 110 """\
awgur@19 111 Получиение объекта соединения из обёрток, которые я сам себе пишу для работы с DB-API
awgur@16 112
awgur@19 113 :param obj:
awgur@19 114 :return:
awgur@19 115 """
awgur@19 116 if hasattr(obj, '_conn'):
awgur@19 117 return obj._conn
awgur@19 118 elif hasattr(obj, '_con'):
awgur@19 119 return obj._con
awgur@19 120 else:
awgur@19 121 raise TypeError('No known connection object in given database object found')