Sqloquent is a package for mapping database records into objects, including life cycle event hooks and a relation system (i.e. ORM). It also includes a query builder, migration system, and other tools. The majority of useful features are exposed from the root level of the package, and the rest from sqloquent.asyncql, sqloquent.tools, or from invoking the tools through the CLI.
General model for mapping a SQL row to an in-memory object.
- table: str
- id_column: str
- columns: tuple
- id: str
- name: str
- query_builder_class: Type[QueryBuilderProtocol]
- connection_info: str
- data: dict
- data_original: MappingProxyType
- _event_hooks: dict[str, list[Callable]]
Initialize the instance. Raises TypeError or ValueError if _post_init_hooks is not dict[Any, callable].
Allow inclusion in sets. Raises TypeError for unencodable type within self.data (calls packify.pack).
Allow comparisons. Raises TypeError on unencodable value in self.data or other.data (calls cls.hash which calls packify.pack).
Pretty str representation.
Add the hook for the event.
Remove the hook for the event.
Remove all hooks for an event. If no event is specified, clear all hooks for all events.
Invoke the hooks for the event, passing cls, *args, and **kwargs.
Create a dynamic property for the column with the given name.
Encode a value for hashing. Uses the pack function from packify.
Generates and returns a hexadecimal UUID4.
Find a record by its id and return it. Return None if it does not exist.
Insert a new record to the datastore. Return instance. Raises TypeError if data is not a dict.
Insert a batch of records and return the number of items inserted. Raises TypeError if items is not list[dict].
Persist the specified changes to the datastore. Return self in monad pattern. Raises TypeError or ValueError for invalid updates or conditions (self.data must include the id to update or conditions must be specified).
Persist to the datastore. Return self in monad pattern. Calls insert or update and raises appropriate errors.
Delete the record.
Reload values from datastore. Return self in monad pattern. Raises UsageError if id is not set in self.data.
Returns a query builder with any conditions provided. Conditions are parsed as key=value and cannot handle other comparison types. If connection_info is not injected and was added as a class attribute, that class attribute will be passed to the query_builder_class instead.
Main query builder class. Extend with child class to bind to a specific database
by supplying the context_manager param to a call to super().__init__()
.
Default binding is to sqlite3.
- model: Type[ModelProtocol]
- context_manager: Type[DBContextProtocol]
- connection_info: str
- clauses: list
- params: list
- order_column: str
- order_dir: str
- limit: int
- offset: int
- joins: list[JoinSpec]
- columns: list[str]
- grouping: str
- model: The model type that non-joined query results will be. Setting raises TypeError if supplied something other than a subclass of SqlModel.
- table: The table name for the base query. Setting raises TypeError if supplied something other than a str.
__init__(model_or_table: Type[SqlModel] | str = None, context_manager: Type[DBContextProtocol] = SqliteContext, connection_info: str = '', model: Type[SqlModel] = None, table: str = '', columns: list[str] = []) -> None:
Initialize the instance. Must supply model_or_table or model or table. Must supply context_manager.
Save the 'column is null' clause, then return self. Raises TypeError for invalid column. If a list or tuple is supplied, each element is treated as a separate clause.
Save the 'column is not null' clause, then return self. Raises TypeError for invalid column. If a list or tuple is supplied, each element is treated as a separate clause.
Save the 'column = data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with equal(column, data)
or
equal(column1=data1, column2=data2, etc=data3)
.
Save the 'column != data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with not_equal(column, data)
or
not_equal(column1=data1, column2=data2, etc=data3)
.
Save the 'column < data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with less(column, data)
or
less(column1=data1, column2=data2, etc=data3)
.
Save the 'column > data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with greater(column, data)
or
greater(column1=data1, column2=data2, etc=data3)
.
like(column: str, pattern: str = None, data: str = None, conditions: dict[str, tuple[str, str]] = None) -> SqlQueryBuilder:
Save the 'column like {pattern.replace(?, data)}' clause and param, then return
self. Raises TypeError or ValueError for invalid column, pattern, or data. This
method can be called with like(column, pattern, data)
or
like(column1=(pattern1,str1), column2=(pattern2,str2), etc=(pattern3,str3))
.
not_like(column: str, pattern: str = None, data: str = None, conditions: dict[str, tuple[str, str]] = None) -> SqlQueryBuilder:
Save the 'column not like {pattern.replace(?, data)}' clause and param, then
return self. Raises TypeError or ValueError for invalid column, pattern, or
data. This method can be called with not_like(column, pattern, data)
or
not_like(column1=(pattern1,str1), column2=(pattern2,str2), etc=(pattern3,str3))
.
Save the 'column like data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with starts_with(column, data)
or starts_with(column1=str1, column2=str2, etc=str3)
.
does_not_start_with(column: str, data: str = None, conditions: dict[str, Any] = None) -> SqlQueryBuilder:
Save the 'column not like data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with does_not_start_with(column, data)
or does_not_start_with(column1=str1, column2=str2, etc=str3)
.
Save the 'column like %data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with contains(column, data)
or contains(column1=str1, column2=str2, etc=str3)
.
Save the 'column not like %data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with excludes(column, data)
or excludes(column1=str1, column2=str2, etc=str3)
.
Save the 'column like %data' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with ends_with(column, data)
or ends_with(column1=str1, column2=str2, etc=str3)
.
does_not_end_with(column: str, data: str = None, conditions: dict[str, str] = None) -> SqlQueryBuilder:
Save the 'column like %data' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with does_not_end_with(column, data)
or does_not_end_with(column1=str1, column2=str2, etc=str3)
.
is_in(column: str, data: tuple | list = None, conditions: dict[str, tuple | list] = None) -> SqlQueryBuilder:
Save the 'column in data' clause and param, then return self. Raises TypeError
or ValueError for invalid column or data. This method can be called with
is_in(column, data)
or is_in(column1=list1, column2=list2, etc=list3)
.
not_in(column: str, data: tuple | list = None, conditions: dict[str, tuple | list] = None) -> SqlQueryBuilder:
Save the 'column not in data' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with not_in(column, data)
or not_in(column1=list1, column2=list2, etc=list3)
.
Parse the conditions as if they are sequential calls to the equivalent
SqlQueryBuilder methods. Syntax is as follows: where(is_null=[column1,...], not_null=[column2,...], equal={'column1':data1, 'column2':data2, 'etc':data3}, not_equal={'column1':data1, 'column2':data2, 'etc':data3}, less={'column1':data1, 'column2':data2, 'etc':data3}, greater={'column1':data1, 'column2':data2, 'etc':data3}, like={'column1':(pattern1,str1), 'column2':(pattern2,str2), 'etc':(pattern3,str3)}, not_like={'column1':(pattern1,str1), 'column2':(pattern2,str2), 'etc':(pattern3,str3)}, starts_with={'column1':str1, 'column2':str2, 'etc':str3}, does_not_start_with={'column1':str1, 'column2':str2, 'etc':str3}, contains={'column1':str1, 'column2':str2, 'etc':str3}, excludes={'column1':str1, 'column2':str2, 'etc':str3}, ends_with={'column1':str1, 'column2':str2, 'etc':str3}, does_not_end_with={'column1':str1, 'column2':str2, 'etc':str3}, is_in={'column1':list1, 'column2':list2, 'etc':list3}, not_in={'column1':list1, 'column2':list2, 'etc':list3})
.
All kwargs are optional.
order_by(column: str, direction: str = None, conditions: dict[str, str] = 'desc') -> SqlQueryBuilder:
Sets query order. Raises TypeError or ValueError for invalid column or
direction. This method can be called with order_by(column, direction)
or
order_by(column=direction)
. Note that only one column can be ordered by per
query.
Sets the number of rows to skip. Raises TypeError or ValueError for invalid offset.
Returns a fresh instance using the configured model.
Insert a record and return a model instance. Raises TypeError for invalid data or ValueError if a record with the same id already exists.
Insert a batch of records and return the number inserted. Raises TypeError for invalid items.
Find a record by its id and return it.
join(model_or_table: Type[SqlModel] | str, on: list[str], kind: str = 'inner', joined_table_columns: tuple[str] = ()) -> SqlQueryBuilder:
Prepares the query for a join over multiple tables/models. Raises TypeError or ValueError for invalid model, on, or kind.
Sets the columns to select. Raises TypeError for invalid columns.
Adds a GROUP BY constraint. Raises TypeError for invalid by.
Run the query on the datastore and return a list of results. Return SqlModels when running a simple query. Return JoinedModels when running a JOIN query. Return Rows when running a non-joined GROUP BY query.
Returns the number of records matching the query.
Takes the specified number of rows. Raises TypeError or ValueError for invalid limit.
Chunk all matching rows the specified number of rows at a time. Raises TypeError or ValueError for invalid number.
Run the query on the datastore and return the first result.
Update the datastore and return number of records updated. Raises TypeError for invalid updates or conditions.
Delete the records that match the query and return the number of deleted records.
Return the sql where clause from the clauses and params. If interpolate_params is True, the parameters will be interpolated into the SQL str and a single str result will be returned. If interpolate_params is False, the parameters will not be interpolated into the SQL str, instead including question marks, and an additional list of params will be returned along with the SQL str.
Execute raw SQL against the database. Return rowcount and fetchall results.
Context manager for sqlite.
- connection: sqlite3.Connection
- cursor: sqlite3.Cursor
- connection_info: str
Initialize the instance. Raises TypeError for non-str table.
Enter the context block and return the cursor.
__exit__(_SqliteContext__exc_type: Optional[Type[BaseException]], _SqliteContext__exc_value: Optional[BaseException], _SqliteContext__traceback: Optional[TracebackType]) -> None:
Exit the context block. Commit or rollback as appropriate, then close the connection.
Model for preserving and restoring deleted HashedModel records.
- table: str
- id_column: str
- columns: tuple
- id: str
- name: str
- query_builder_class: Type[QueryBuilderProtocol]
- connection_info: str
- data: dict
- data_original: MappingProxyType
- _event_hooks: dict[str, list[Callable]]
- model_class: str
- record_id: str
- record: bytes
- timestamp: str
Insert a new record to the datastore. Return instance. Raises TypeError if data is not a dict. Automatically sets a timestamp if one is not supplied.
Restore a deleted record, remove from deleted_records, and return the restored model. Raises ValueError if model_class cannot be found. Raises TypeError if model_class is not a subclass of SqlModel. Uses packify.unpack to unpack the record. Raises TypeError if packed record is not a dict.
Model for interacting with sql database using sha256 for id.
- table: str
- id_column: str
- columns: tuple[str]
- id: str
- name: str
- query_builder_class: Type[QueryBuilderProtocol]
- connection_info: str
- data: dict
- data_original: MappingProxyType
- _event_hooks: dict[str, list[Callable]]
- columns_excluded_from_hash: tuple[str]
- details: bytes
Generate an id by hashing the non-id contents. Raises TypeError for unencodable type (calls packify.pack). Any columns not present in the data dict will be set to the default value specified in the column annotation or None if no default is specified. Any columns in the columns_excluded_from_hash tuple will be excluded from the sha256 hash.
Insert a new record to the datastore. Return instance. Raises TypeError for non-dict data or unencodable type (calls cls.generate_id, which calls packify.pack).
Insert a batch of records and return the number of items inserted. Raises TypeError for invalid items or unencodable value (calls cls.generate_id, which calls packify.pack).
Persist the specified changes to the datastore, creating a new record in the process unless the changes were to the hash-excluded columns. Update and return self in monad pattern. Raises TypeError or ValueError for invalid updates. Did not need to overwrite the save method because save calls update or insert.
Delete the model, putting it in the deleted_records table, then return the DeletedModel. Raises packify.UsageError for unserializable data.
Class for attaching immutable details to a record.
- table: str
- id_column: str
- columns: tuple
- id: str
- name: str
- query_builder_class: Type[QueryBuilderProtocol]
- connection_info: str
- data: dict
- data_original: MappingProxyType
- _event_hooks: dict[str, list[Callable]]
- columns_excluded_from_hash: tuple[str]
- details: bytes | None
- related_model: str
- related_id: str
- _related: SqlModel
- _details: packify.SerializableType
Return the related record.
Attach to related model then return self.
Decode packed bytes to dict.
Set the details column using either supplied data or by packifying self._details. Return self in monad pattern. Raises packify.UsageError or TypeError if details contains unseriazliable type.
Class for representing a row from a query when no better model exists.
- data: dict
Class for representing the results of SQL JOIN queries.
- models: list[Type[SqlModel]]
- data: dict
Initialize the instance. Raises TypeError for invalid models or data.
Pretty str representation.
Parse data of form {table.column:value} to {table:{column:value}}. Raises TypeError for invalid models or data.
Returns the underlying models. Calls the find method for each model.
Class for representing joins to be executed by a query builder.
- kind: str
- table_1: str
- table_1_model: str | None
- table_1_columns: list[str]
- table_1_column_types: dict[str, type]
- column_1: str
- comparison: str
- table_2: str
- table_2_model: str | None
- table_2_columns: list[str]
- table_2_column_types: dict[str, type]
- column_2: str
__init__(kind: str, table_1: str, table_1_model: str | None, table_1_columns: list[str], table_1_column_types: dict[str, type], column_1: str, comparison: str, table_2: str, table_2_model: str | None, table_2_columns: list[str], table_2_column_types: dict[str, type], column_2: str):
Class for representing a default value for a column annotation.
Interface showing how a DB cursor should function.
Execute a single query with the given parameters.
Execute a query once for each list of parameters.
Execute a SQL script without parameters. No implicit transaciton handling.
Get one record returned by the previous query.
Get all records returned by the previous query.
Interface showing how a context manager for connecting to a database should behave.
Using the connection_info parameter is optional but should be supported. I recommend setting a class attribute with the default value taken from an environment variable, then use that class attribute within this method, overriding with the parameter only if it is not empty.
Enter the with
block. Should return a cursor useful for making db calls.
__exit__(exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], traceback: Optional[TracebackType]) -> None:
Exit the with
block. Should commit any pending transactions and close the
cursor and connection upon exiting the context.
Interface showing how a model should function.
- table: Str with the name of the table.
- id_column: Str with the name of the id column.
- columns: Tuple of str column names.
- data: Dict for storing model data.
- data_original: Read-only MappingProxyType for storing original data values for change tracking.
Allow inclusion in sets.
Return True if types and hashes are equal, else False.
Add the hook for the event.
Remove the hook for the event.
Remove all hooks for an event. If no event is specified, clear all hooks for all events.
Invoke the hooks for the event, passing cls, *args, and **kwargs.
Find a record by its id and return it. Return None if it does not exist.
Insert a new record to the datastore. Return instance.
Insert a batch of records and return the number of items inserted.
update(updates: dict, conditions: dict = None, /, *, suppress_events: bool = False) -> ModelProtocol:
Persist the specified changes to the datastore. Return self in monad pattern.
Persist to the datastore. Return self in monad pattern.
Delete the record.
Reload values from datastore. Return self in monad pattern.
Return a QueryBuilderProtocol for the model.
Interface showing how a query builder should function.
- table: The name of the table.
- model: The class of the relevant model.
__init__(model_or_table: Type[ModelProtocol] | str, context_manager: Type[DBContextProtocol], connection_info: str = '', model: Type[ModelProtocol] = None, table: str = None) -> None:
Initialize the instance. A class implementing ModelProtocol or the str name of a table must be provided.
Save the 'column is null' clause, then return self. Raises TypeError for invalid column. If a list or tuple is supplied, each element is treated as a separate clause.
Save the 'column is not null' clause, then return self. Raises TypeError for invalid column. If a list or tuple is supplied, each element is treated as a separate clause.
Save the 'column = data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with equal(column, data)
or
equal(column1=data1, column2=data2, etc=data3)
.
not_equal(column: str, data: Any = None, conditions: dict[str, Any] = None) -> QueryBuilderProtocol:
Save the 'column != data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with not_equal(column, data)
or
not_equal(column1=data1, column2=data2, etc=data3)
.
Save the 'column < data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with less(column, data)
or
less(column1=data1, column2=data2, etc=data3)
.
Save the 'column > data' clause and param, then return self. Raises TypeError
for invalid column. This method can be called with greater(column, data)
or
greater(column1=data1, column2=data2, etc=data3)
.
like(column: str, pattern: str = None, data: str = None, conditions: dict[str, tuple[str, str]] = None) -> QueryBuilderProtocol:
Save the 'column like {pattern.replace(?, data)}' clause and param, then return
self. Raises TypeError or ValueError for invalid column, pattern, or data. This
method can be called with like(column, pattern, data)
or
like(column1=(pattern1,str1), column2=(pattern2,str2), etc=(pattern3,str3))
.
not_like(column: str, pattern: str = None, data: str = None, conditions: dict[str, tuple[str, str]] = None) -> QueryBuilderProtocol:
Save the 'column not like {pattern.replace(?, data)}' clause and param, then
return self. Raises TypeError or ValueError for invalid column, pattern, or
data. This method can be called with not_like(column, pattern, data)
or
not_like(column1=(pattern1,str1), column2=(pattern2,str2), etc=(pattern3,str3))
.
starts_with(column: str, data: str = None, conditions: dict[str, Any] = None) -> QueryBuilderProtocol:
Save the 'column like data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with starts_with(column, data)
or starts_with(column1=str1, column2=str2, etc=str3)
.
does_not_start_with(column: str, data: str = None, conditions: dict[str, Any] = None) -> QueryBuilderProtocol:
Save the 'column not like data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with does_not_start_with(column, data)
or does_not_start_with(column1=str1, column2=str2, etc=str3)
.
Save the 'column like %data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with contains(column, data)
or contains(column1=str1, column2=str2, etc=str3)
.
Save the 'column not like %data%' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with excludes(column, data)
or excludes(column1=str1, column2=str2, etc=str3)
.
ends_with(column: str, data: str = None, conditions: dict[str, Any] = None) -> QueryBuilderProtocol:
Save the 'column like %data' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with ends_with(column, data)
or ends_with(column1=str1, column2=str2, etc=str3)
.
does_not_end_with(column: str, data: str = None, conditions: dict[str, Any] = None) -> QueryBuilderProtocol:
Save the 'column like %data' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with does_not_end_with(column, data)
or does_not_end_with(column1=str1, column2=str2, etc=str3)
.
is_in(column: str, data: Union[tuple, list] = None, conditions: dict[str, Any] = None) -> QueryBuilderProtocol:
Save the 'column in data' clause and param, then return self. Raises TypeError
or ValueError for invalid column or data. This method can be called with
is_in(column, data)
or is_in(column1=list1, column2=list2, etc=list3)
.
not_in(column: str, data: Union[tuple, list] = None, conditions: dict[str, Any] = None) -> QueryBuilderProtocol:
Save the 'column not in data' clause and param, then return self. Raises
TypeError or ValueError for invalid column or data. This method can be called
with not_in(column, data)
or not_in(column1=list1, column2=list2, etc=list3)
.
Parse the conditions as if they are sequential calls to the equivalent
SqlQueryBuilder methods. Syntax is as follows: where(is_null=[column1,...], not_null=[column2,...], equal={'column1':data1, 'column2':data2, 'etc':data3}, not_equal={'column1':data1, 'column2':data2, 'etc':data3}, less={'column1':data1, 'column2':data2, 'etc':data3}, greater={'column1':data1, 'column2':data2, 'etc':data3}, like={'column1':(pattern1,str1), 'column2':(pattern2,str2), 'etc':(pattern3,str3)}, not_like={'column1':(pattern1,str1), 'column2':(pattern2,str2), 'etc':(pattern3,str3)}, starts_with={'column1':str1, 'column2':str2, 'etc':str3}, does_not_start_with={'column1':str1, 'column2':str2, 'etc':str3}, contains={'column1':str1, 'column2':str2, 'etc':str3}, excludes={'column1':str1, 'column2':str2, 'etc':str3}, ends_with={'column1':str1, 'column2':str2, 'etc':str3}, does_not_end_with={'column1':str1, 'column2':str2, 'etc':str3}, is_in={'column1':list1, 'column2':list2, 'etc':list3}, not_in={'column1':list1, 'column2':list2, 'etc':list3})
.
All kwargs are optional.
order_by(column: str, direction: str = None, conditions: dict[str, Any] = 'desc') -> QueryBuilderProtocol:
Sets query order.
Sets the number of rows to skip.
Returns a fresh instance using the configured model.
Insert a record and return a model instance.
Insert a batch of records and return the number inserted.
Find a record by its id and return it.
join(model_or_table: Type[ModelProtocol] | str, on: list[str], kind: str = 'inner', joined_table_columns: tuple[str] = ()) -> QueryBuilderProtocol:
Prepares the query for a join over multiple tables/models. Raises TypeError or ValueError for invalid model, on, or kind.
Sets the columns to select.
Adds a group by constraint.
Run the query on the datastore and return a list of results. Return SqlModels when running a simple query. Return JoinedModels when running a JOIN query. Return Rows when running a non-joined GROUP BY query.
Returns the number of records matching the query.
Takes the specified number of rows.
chunk(number: int) -> Generator[list[ModelProtocol] | list[JoinedModelProtocol] | list[RowProtocol], None, None]:
Chunk all matching rows the specified number of rows at a time.
Run the query on the datastore and return the first result.
Update the datastore and return number of records updated.
Delete the records that match the query and return the number of deleted records.
Return the sql where clause from the clauses and params. If interpolate_params is True, the parameters will be interpolated into the SQL str and a single str result will be returned. If interpolate_params is False, the parameters will not be interpolated into the SQL str, instead including question marks, and an additional list of params will be returned along with the SQL str.
Execute raw SQL against the database. Return rowcount and fetchall results.
Interface for representations of JOIN query results.
- data: Dict for storing models data.
- models: List of the underlying model classes.
Initialize the instance.
Parse data of form {table.column:value} to {table:{column:value}}.
Returns the underlying models.
Interface for a generic row representation.
- data: Returns the underlying row data.
Interface showing how a relation should function.
- primary: Property that accesses the primary instance.
- secondary: Property that accesses the secondary instance(s).
The exact initialization will depend upon relation subtype.
Checks preconditions for a model.
Checks preconditions for list/tuple of models.
Checks that primary is instance of self.primary_class.
Checks that secondary is instance of self.secondary_class.
Checks preconditions for a pivot.
Save the relation by setting/unsetting relevant database values.
Reload the secondary models from the database.
Creates the base query for the underlying relation.
Get the cache key for the relation.
Produces a property to be set on a model, allowing it to access the related model through the relation.
Interface showing what a related model returned from an ORM helper function or RelationProtocol.create_property will behave. This is used for relations where the primary model is associated with a single secondary model.
Return the underlying relation when the property is called as a method, e.g.
phone.owner()
will return the relation while phone.owner
will access the
related model.
Interface showing what a related model returned from an ORM helper function or RelationProtocol.create_property will behave. This is used for relations where the primary model is associated with multiple secondary models.
Return the underlying relation when the property is called as a method, e.g.
fish.scales()
will return the relation while fish.scales
will access the
related models.
Allow the collection to be iterated over, returning a model on each iteration.
Return the related model at the given index.
Base class for setting up relations.
- primary_class: Type[ModelProtocol]
- secondary_class: Type[ModelProtocol]
- primary_to_add: ModelProtocol
- primary_to_remove: ModelProtocol
- secondary_to_add: list[ModelProtocol]
- secondary_to_remove: list[ModelProtocol]
- primary: ModelProtocol
- secondary: ModelProtocol | tuple[ModelProtocol]
- _primary: Optional[ModelProtocol]
- _secondary: Optional[ModelProtocol]
- primary: The primary model instance. Setting raises TypeError if a precondition check fails.
- secondary: The secondary model instance(s).
__init__(primary_class: Type[ModelProtocol], secondary_class: Type[ModelProtocol], primary_to_add: ModelProtocol = None, primary_to_remove: ModelProtocol = None, secondary_to_add: list[ModelProtocol] = [], secondary_to_remove: list[ModelProtocol] = [], primary: ModelProtocol = None, secondary: ModelProtocol | tuple[ModelProtocol] = None) -> None:
Precondition check for a single model. Raises TypeError if the check fails.
Precondition checks for a list of models. Raises TypeError if any check fails.
Precondition check for the primary instance. Raises TypeError if the check fails.
Precondition check for a secondary instance. Raises TypeError if the check fails.
Precondition check for a pivot type. Raises TypeError if the check fails.
Save the relation by setting/unsetting the relevant database values and unset the following attributes: primary_to_add, primary_to_remove, secondary_to_add, and secondary_to_remove.
Reload the relation from the database. Return self in monad pattern.
Creates the base query for the underlying relation.
Returns the cache key for the Relation.
Creates a property to be used on a model.
Class for the relation where primary owns a secondary: primary.data[id_column] = secondary.data[foreign_id_column]. An owner model.
- primary_class: Type[ModelProtocol]
- secondary_class: Type[ModelProtocol]
- primary_to_add: ModelProtocol
- primary_to_remove: ModelProtocol
- secondary_to_add: list[ModelProtocol]
- secondary_to_remove: list[ModelProtocol]
- primary: ModelProtocol
- secondary: ModelProtocol | tuple[ModelProtocol]
- _primary: Optional[ModelProtocol]
- _secondary: Optional[ModelProtocol]
- foreign_id_column: str
- secondary: The secondary model instance. Setting raises TypeError if the precondition check fails.
Set the foreign_id_column attribute, then let the Relation init handle the rest. Raises TypeError if foreign_id_column is not a str.
Save the relation by setting/unsetting the relevant database values and unset the following attributes: primary_to_add, primary_to_remove, secondary_to_add, and secondary_to_remove. Raises UsageError if the relation is missing data.
Reload the relation from the database. Return self in monad pattern.
Creates the base query for the underlying relation.
Returns the cache key for this relation.
Creates a property that can be used to set relation properties on models. Sets the relevant post-init hook to set up the relation on newly created models. Setting the secondary property on the instance will raise a TypeError if the precondition check fails.
Class for the relation where primary owns multiple secondary models: model.data[foreign_id_column] = primary.data[id_column] instance of this class is set on the owner model.
- primary_class: Type[ModelProtocol]
- secondary_class: Type[ModelProtocol]
- primary_to_add: ModelProtocol
- primary_to_remove: ModelProtocol
- secondary_to_add: list[ModelProtocol]
- secondary_to_remove: list[ModelProtocol]
- primary: ModelProtocol
- secondary: ModelProtocol | tuple[ModelProtocol]
- _primary: Optional[ModelProtocol]
- _secondary: Optional[ModelProtocol]
- foreign_id_column: str
- secondary: The secondary model instance. Setting raises TypeError if the precondition check fails.
Save the relation by setting the relevant database value(s). Raises UsageError if the relation is incomplete.
Reload the relation from the database. Return self in monad pattern.
Creates the base query for the underlying relation.
Creates a property that can be used to set relation properties on models. Sets the relevant post-init hook to set up the relation on newly created models. Setting the secondary property on the instance will raise a TypeError if the precondition check fails.
Class for the relation where primary belongs to a secondary: primary.data[foreign_id_column] = secondary.data[id_column]. Inverse of HasOne and HasMany. An instance of this class is set on the owned model.
- primary_class: Type[ModelProtocol]
- secondary_class: Type[ModelProtocol]
- primary_to_add: ModelProtocol
- primary_to_remove: ModelProtocol
- secondary_to_add: list[ModelProtocol]
- secondary_to_remove: list[ModelProtocol]
- primary: ModelProtocol
- secondary: ModelProtocol | tuple[ModelProtocol]
- _primary: Optional[ModelProtocol]
- _secondary: Optional[ModelProtocol]
- foreign_id_column: str
Persists the relation to the database. Raises UsageError if the relation is incomplete.
Reload the relation from the database. Return self in monad pattern.
Creates the base query for the underlying relation.
Creates a property that can be used to set relation properties on models. Sets the relevant post-init hook to set up the relation on newly created models. Setting the secondary property on the instance will raise a TypeError if the precondition check fails.
Class for the relation where each primary can have many secondary and each secondary can have many primary; e.g. users and roles, or roles and permissions. This requires the use of a pivot.
- primary_class: Type[ModelProtocol]
- secondary_class: Type[ModelProtocol]
- primary_to_add: ModelProtocol
- primary_to_remove: ModelProtocol
- secondary_to_add: list[ModelProtocol]
- secondary_to_remove: list[ModelProtocol]
- primary: ModelProtocol
- secondary: ModelProtocol | tuple[ModelProtocol]
- _primary: Optional[ModelProtocol]
- _secondary: Optional[ModelProtocol]
- pivot: Type[ModelProtocol]
- primary_id_column: str
- secondary_id_column: str
- secondary: The secondary model instances. Setting raises TypeError if a precondition check fails.
- pivot
Set the pivot and query_builder_pivot attributes, then let the Relation class handle the rest. Raises TypeError if either primary_id_column or secondary_id_column is not a str.
Save the relation by setting/unsetting the relevant database value(s). Raises UsageError if the relation is incomplete.
Reload the relation from the database. Return self in monad pattern.
Creates the base query for the underlying relation. This will return the query for a join between the pivot and the related model.
Returns the cache key for this relation.
Creates a property that can be used to set relation properties on models. Sets the relevant post-init hook to set up the relation on newly created models. Setting the secondary property on the instance will raise a TypeError if the precondition check fails.
Class for encoding a relationship in which a model contains the ID(s) for other models within a column: primary.data[foreign_id_column] = ",".join(sorted([ s.data[id_column] for s in secondary])). Useful for DAGs using HashedModel or something similar. IDs are sorted for deterministic hashing via HashedModel.
- primary_class: Type[ModelProtocol]
- secondary_class: Type[ModelProtocol]
- primary_to_add: ModelProtocol
- primary_to_remove: ModelProtocol
- secondary_to_add: list[ModelProtocol]
- secondary_to_remove: list[ModelProtocol]
- primary: ModelProtocol
- secondary: tuple[ModelProtocol]
- _primary: Optional[ModelProtocol]
- _secondary: tuple[ModelProtocol]
- foreign_id_column: str
Persists the relation to the database. Raises UsageError if the relation is incomplete.
Reload the relation from the database. Return self in monad pattern.
Creates the base query for the underlying relation.
Creates a property that can be used to set relation properties on models. Sets the relevant post-init hook to set up the relation on newly created models. Setting the secondary property on the instance will raise a TypeError if the precondition check fails.
Class for encoding a relationship in which the model's ID is contained within a column of another model: all([ primary.data[id_column] in s.data[foreign_id_column] for s in secondary]). Useful for DAGs using HashedModel or something similar. IDs are sorted for deterministic hashing via HashedModel.
- primary_class: Type[ModelProtocol]
- secondary_class: Type[ModelProtocol]
- primary_to_add: ModelProtocol
- primary_to_remove: ModelProtocol
- secondary_to_add: list[ModelProtocol]
- secondary_to_remove: list[ModelProtocol]
- primary: ModelProtocol
- secondary: tuple[ModelProtocol]
- _primary: Optional[ModelProtocol]
- _secondary: Optional[ModelProtocol]
- foreign_id_column: str
Persists the relation to the database. Raises UsageError if the relation is incomplete.
Reload the relation from the database. Return self in monad pattern.
Creates the base query for the underlying relation (i.e. to query the secondary class).
Creates a property that can be used to set relation properties on models. Sets the relevant post-init hook to set up the relation on newly created models. Setting the secondary property on the instance will raise a TypeError if the precondition check fails.
Column class for creating migrations.
- name: str
- datatype: str
- table: TableProtocol
- is_nullable: bool
- default_value: Any
- new_name: str
__init__(name: str, datatype: str, table: TableProtocol, is_nullable: bool = True, default_value: Any = None, new_name: str = None):
Validate the Column name. Raises TypeError or ValueError if the column name is invalid.
Marks the column as not nullable.
Marks the column as nullable.
Set the default value for the column.
Creates an index on the column.
Creates an unique index on the column.
Drops the column.
Marks the column as needing to be renamed.
Table class for creating migrations.
- name: str
- new_name: str
- columns_to_add: list[Column]
- columns_to_drop: list[Column | str]
- columns_to_rename: list[Column | list[str]]
- indices_to_add: list[list[Column | str]]
- indices_to_drop: list[list[Column | str]]
- uniques_to_add: list[list[Column | str]]
- uniques_to_drop: list[list[Column | str]]
- is_create: bool
- is_drop: bool
- callback: Callable[[list[str]], list[str]]
__init__(name: str, new_name: str = None, columns_to_add: list[Column] = <factory>, columns_to_drop: list[Column | str] = <factory>, columns_to_rename: list[Column | list[str]] = <factory>, indices_to_add: list[list[Column | str]] = <factory>, indices_to_drop: list[list[Column | str]] = <factory>, uniques_to_add: list[list[Column | str]] = <factory>, uniques_to_drop: list[list[Column | str]] = <factory>, is_create: bool = False, is_drop: bool = False, callback: Callable[[list[str]], list[str]] = <factory>):
For creating a table.
For altering a table.
For dropping a table.
Rename the table.
Create a simple index or a composite index.
Drop a simple index or a composite index.
Create a simple unique index or a composite unique index.
Drop a simple unique index or a composite unique index.
Drop the specified column.
Rename the specified column.
Creates an integer column.
Creates a numeric column.
Creates a real column.
Creates a text column.
Creates a blob column.
Creates a boolean column.
Add a custom callback that parses the SQL clauses before they are returnedf from
the sql
method. Must accept and return list[str]. This is a way to add custom
SQL while still using the migration system. Return self in monad pattern.
Return the SQL for the table structure changes. Raises UsageError if the Table was used incorrectly. Raises TypeError or ValueError if a Column fails validation.
Migration class for updating a database schema.
- connection_info: str
- context_manager: Type[DBContextProtocol]
- up_callbacks: list[Callable[[], list[TableProtocol]]]
- down_callbacks: list[Callable[[], list[TableProtocol]]]
__init__(connection_info: str = '', context_manager: Type[DBContextProtocol] = SqliteContext, up_callbacks: list[Callable[[], list[TableProtocol]]] = <factory>, down_callbacks: list[Callable[[], list[TableProtocol]]] = <factory>):
Specify the forward migration. May be called multiple times for multi-step migrations.
Specify the backward migration. May be called multiple times for multi-step migrations.
Get the SQL for the forward migration. Note that this will call all registered callbacks and may result in unexpected behavior.
Apply the forward migration.
Get the SQL for the backward migration. Note that this will call all registered callbacks and may result in unexpected behavior.
Apply the backward migration.
dynamic_sqlmodel(connection_string: str | bytes, table_name: str = '', column_names: tuple[str] = ()) -> Type[SqlModel]:
Generates a dynamic sqlite model for instantiating context managers. Raises TypeError for invalid connection_string or table_name.
has_one(cls: Type[ModelProtocol], owned_model: Type[ModelProtocol], foreign_id_column: str = None) -> property:
Creates a HasOne relation and returns the result of create_property. Usage
syntax is like User.avatar = has_one( User, Avatar)
. If the foreign id column
on the Avatar.table table is not user_id (cls.name PascalCase -> snake_case
- "_id"), then it can be specified.
has_many(cls: Type[ModelProtocol], owned_model: Type[ModelProtocol], foreign_id_column: str = None) -> property:
Creates a HasMany relation and returns the result of create_property. Usage
syntax is like User.posts = has_many( User, Post)
. If the foreign id column on
the Post.table table is not user_id (cls.name PascalCase -> snake_case +
"_id"), then it can be specified.
belongs_to(cls: Type[ModelProtocol], owner_model: Type[ModelProtocol], foreign_id_column: str = None) -> property:
Creates a BelongsTo relation and returns the result of create_property. Usage
syntax is like Post.owner = belongs_to( Post, User)
. If the foreign id column
on the Post.table table is not user_id (cls.name PascalCase -> snake_case +
"_id"), then it can be specified.
belongs_to_many(cls: Type[ModelProtocol], other_model: Type[ModelProtocol], pivot: Type[ModelProtocol], primary_id_column: str = None, secondary_id_column: str = None) -> property:
Creates a BelongsToMany relation and returns the result of create_property.
Usage syntax is like User.liked_posts = belongs_to_many(User, Post, LikedPost)
.
If the foreign id columns on LikedPost are not user_id and post_id (cls.name
or other_model.name PascalCase -> snake_case + "_id"), then they can be
specified.
contains(cls: Type[ModelProtocol], other_model: Type[ModelProtocol], foreign_ids_column: str = None) -> property:
Creates a Contains relation and returns the result of calling create_property.
Usage syntax is like Item.parents = contains(Item, Item)
. If the column
containing the sorted list of ids is not item_ids (i.e. other_model.name ->
snake_case + '_ids'), it can be specified.
within(cls: Type[ModelProtocol], other_model: Type[ModelProtocol], foreign_ids_column: str = None) -> property:
Creates a Within relation and returns the result of calling create_property.
Usage syntax is like Item.children = within(Item, Item)
. If the column
containing the sorted list of ids is not item_ids (i.e. cls.name ->
snake_case + '_ids'), it can be specified.
Generate the name for an index from the table, columns, and type.
__version__
: str