Use abstract base class to help the subclass know what to do.

master
voussoir 2021-10-09 12:12:18 -07:00
parent 8eefc4a095
commit 5b6a1b4c9c
No known key found for this signature in database
GPG Key ID: 5F7554F8C26DACCB
1 changed files with 35 additions and 3 deletions

View File

@ -1,6 +1,7 @@
'''
Worms is an SQL ORM with the strength and resilience of the humble earthworm.
'''
import abc
import functools
import re
import typing
@ -57,7 +58,7 @@ def transaction(method):
return wrapped_transaction
class Database:
class Database(metaclass=abc.ABCMeta):
'''
When your class subclasses this class, you need to ensure the following:
- self.COLUMNS is a dictionary of {table: [columns]} like what comes out of
@ -73,6 +74,25 @@ class Database:
self.on_rollback_queue = []
self.savepoints = []
@abc.abstractmethod
def _init_column_index(self):
'''
Your subclass needs to set self.COLUMNS and self.COLUMN_INDEX, where
COLUMNS is a dictionary of {'table': ['column1', 'column2', ...]} and
COLUMN_INDEX is a dict of {'table': {'column1': 0, 'column2': 1}}.
These outputs can come from sqlhelpers.extract_table_column_map and
reverse_table_column_map.
'''
raise NotImplementedError
@abc.abstractmethod
def _init_sql(self):
'''
Your subclass needs to set self.sql, which is a database connection.
'''
raise NotImplementedError
def assert_table_exists(self, table) -> None:
if table not in self.get_tables():
raise BadTable(f'Table {table} does not exist.')
@ -334,11 +354,23 @@ class Database:
query = f'UPDATE {table} {qmarks}'
self.execute(query, bindings)
class DatabaseWithCaching(Database):
class DatabaseWithCaching(Database, metaclass=abc.ABCMeta):
def __init__(self):
super().__init__()
self.caches = {}
def _init_caches(self):
'''
Your subclass needs to set self.caches, which is a dictionary of
{object: cache} where object is one of your data object types
(use the class itself as the key) and cache is a dictionary or
cacheclass.Cache or anything that supports subscripting.
If any types are omitted from this dictionary, objects of those
types will not be cached.
'''
raise NotImplementedError
def clear_all_caches(self) -> None:
for cache in self.caches:
cache.clear()
@ -483,7 +515,7 @@ class DatabaseWithCaching(Database):
for object_row in object_rows:
yield self.get_cached_instance(object_class, object_row)
class Object:
class Object(metaclass=abc.ABCMeta):
'''
When your objects subclass this class, you need to ensure the following: