Update docs
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,11 +1,11 @@
|
|||||||
.idea/*
|
.idea/*
|
||||||
aiodatalite/__pycache__/*
|
aiodatalite/__pycache__/*
|
||||||
*.pyc
|
*.pyc
|
||||||
datalite/*.db
|
aiodatalite/*.db
|
||||||
*.db
|
*.db
|
||||||
docs/_build/*
|
docs/_build/*
|
||||||
build/*
|
build/*
|
||||||
datalite.egg-info/*
|
aiodatalite.egg-info/*
|
||||||
dist/*
|
dist/*
|
||||||
venv/*
|
venv/*
|
||||||
t/
|
t/
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# Minimal makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line, and also
|
|
||||||
# from the environment for the first two.
|
|
||||||
SPHINXOPTS ?=
|
|
||||||
SPHINXBUILD ?= sphinx-build
|
|
||||||
SOURCEDIR = .
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
|
||||||
help:
|
|
||||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
||||||
|
|
||||||
.PHONY: help Makefile
|
|
||||||
|
|
||||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
||||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
||||||
%: Makefile
|
|
||||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
||||||
@@ -1,39 +1,39 @@
|
|||||||
API Reference
|
API Reference
|
||||||
================
|
================
|
||||||
|
|
||||||
datalite Module
|
aiodatalite Module
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
.. autodecorator:: datalite.datalite
|
.. autodecorator:: aiodatalite.datalite
|
||||||
|
|
||||||
datalite.constraints module
|
aiodatalite.constraints module
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
.. automodule:: datalite.constraints
|
.. automodule:: aiodatalite.constraints
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
datalite.fetch module
|
aiodatalite.fetch module
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
.. automodule:: datalite.fetch
|
.. automodule:: aiodatalite.fetch
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
datalite.mass_actions module
|
aiodatalite.mass_actions module
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
.. automodule:: datalite.mass_actions
|
.. automodule:: aiodatalite.mass_actions
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
datalite.migrations module
|
aiodatalite.migrations module
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
.. automodule:: datalite.migrations
|
.. automodule:: aiodatalite.migrations
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
@@ -19,7 +19,7 @@ sys.path.insert(0, os.path.abspath("../."))
|
|||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
project = "Datalite"
|
project = "aiodatalite"
|
||||||
copyright = "2020, Ege Ozkan; 2024, hhh"
|
copyright = "2020, Ege Ozkan; 2024, hhh"
|
||||||
author = "Ege Ozkan, hhh"
|
author = "Ege Ozkan, hhh"
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ specific column **MUST** abide by specific constraints, these might be
|
|||||||
* Values of this column can be used to identify a record. (``PRIMARY``)
|
* Values of this column can be used to identify a record. (``PRIMARY``)
|
||||||
* Values of this column has a default value. (``DEFAULT``)
|
* Values of this column has a default value. (``DEFAULT``)
|
||||||
|
|
||||||
Some of these constraints are already implemented in datalite. With all of the set,
|
Some of these constraints are already implemented in aiodatalite. With all of the set,
|
||||||
is planned to be implemented in the future.
|
is planned to be implemented in the future.
|
||||||
|
|
||||||
Default Values
|
Default Values
|
||||||
@@ -53,7 +53,7 @@ Uniqueness constraint is declared thusly:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from datalite.constraints import Unique
|
from aiodatalite.constraints import Unique
|
||||||
|
|
||||||
@datalite("db.db")
|
@datalite("db.db")
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ Basic Decorator Operations
|
|||||||
Creating a datalite class
|
Creating a datalite class
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
A datalite class is a special dataclass. It is created by using a decorator ``@datalite.datalite``,
|
A datalite class is a special dataclass. It is created by using a decorator ``@aiodatalite.datalite``,
|
||||||
members of this class are, from Python's perspective, just normal classes. However, they have
|
members of this class are, from Python's perspective, just normal classes. However, they have
|
||||||
additional methods and attributes. ``@datalite`` decorator needs a database path to be provided.
|
additional methods and attributes. ``@datalite`` decorator needs a database path to be provided.
|
||||||
This database is the database the table for the dataclass will be created.
|
This database is the database the table for the dataclass will be created.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from datalite import datalite
|
from aiodatalite import datalite
|
||||||
@datalite(db_path='db.db')
|
@datalite(db_path='db.db')
|
||||||
@dataclass
|
@dataclass
|
||||||
class Student:
|
class Student:
|
||||||
@@ -29,6 +29,18 @@ Special Methods
|
|||||||
Each object initialised from a dataclass decorated with the ``@dataclass`` decorator automatically
|
Each object initialised from a dataclass decorated with the ``@dataclass`` decorator automatically
|
||||||
gains access to three special methods. It should be noted, due to the nature of the library, extensions
|
gains access to three special methods. It should be noted, due to the nature of the library, extensions
|
||||||
such as ``mypy`` and IDEs such as PyCharm will not be able to see these methods and may raise exceptions.
|
such as ``mypy`` and IDEs such as PyCharm will not be able to see these methods and may raise exceptions.
|
||||||
|
So, aiodatalite introduces ``typed`` module and ``DataliteHinted`` class, from which you can inherit your dataclass.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from aiodatalite import datalite
|
||||||
|
from aiodatalite.typed import DataliteHinted
|
||||||
|
@datalite(db_path='db.db')
|
||||||
|
@dataclass
|
||||||
|
class Student(DataliteHinted):
|
||||||
|
student_id: int = 1
|
||||||
|
student_name: str = "Kurt Gödel"
|
||||||
|
student_gpa: float = 3.9
|
||||||
|
|
||||||
With this in mind, let us create a new object and run the methods over this objects.
|
With this in mind, let us create a new object and run the methods over this objects.
|
||||||
|
|
||||||
@@ -36,6 +48,31 @@ With this in mind, let us create a new object and run the methods over this obje
|
|||||||
|
|
||||||
new_student = Student(0, "Albert Einstein", 4.0)
|
new_student = Student(0, "Albert Einstein", 4.0)
|
||||||
|
|
||||||
|
Marking up Table
|
||||||
|
#################
|
||||||
|
Due to the limitations of asynchronous programming, we cannot automatically create the table asynchronously,
|
||||||
|
so we provide two ways to do this.
|
||||||
|
|
||||||
|
First way is to create the table automatically in !synchronous! mode by explicitly passing an argument to the decorator.
|
||||||
|
We don't know what consequences this can lead to specifically in your application, but if you are confident in yourself,
|
||||||
|
use this method
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
...
|
||||||
|
@datalite(db_path='db.db', automarkup=True)
|
||||||
|
@dataclass
|
||||||
|
class Student(DataliteHinted):
|
||||||
|
...
|
||||||
|
|
||||||
|
The second way, which may be less convenient when using some frameworks but is more controllable, is to call the
|
||||||
|
asynchronous ``create_table`` method, which will be added to your dataclass after using ``@datalite`` decorator,
|
||||||
|
alongside with some other methods.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
await new_student.markup_table()
|
||||||
|
|
||||||
Creating an Entry
|
Creating an Entry
|
||||||
##################
|
##################
|
||||||
|
|
||||||
@@ -46,7 +83,7 @@ in the table:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
new_student.create_entry()
|
await new_student.create_entry()
|
||||||
|
|
||||||
This also modifies the object in an intresting way, it adds a new attribute ``obj_id``, this is a unique,
|
This also modifies the object in an intresting way, it adds a new attribute ``obj_id``, this is a unique,
|
||||||
autoincremented value in the database. It can be accessed by ``new_student.obj_id``.
|
autoincremented value in the database. It can be accessed by ``new_student.obj_id``.
|
||||||
@@ -60,7 +97,7 @@ record in the database, this method must be called.
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
new_student.student_gpa = 5.0 # He is Einstein, after all.
|
new_student.student_gpa = 5.0 # He is Einstein, after all.
|
||||||
new_student.update_entry()
|
await new_student.update_entry()
|
||||||
|
|
||||||
|
|
||||||
Deleting an Entry
|
Deleting an Entry
|
||||||
@@ -71,9 +108,57 @@ be used.
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
new_student.remove_entry()
|
await new_student.remove_entry()
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
It should be noted that, if the ``new_student.obj_id`` attribute is modified, ``.update_entry()``
|
It should be noted that, if the ``new_student.obj_id`` attribute is modified, ``.update_entry()``
|
||||||
and ``.remove_entry()`` may have unexpected results.
|
and ``.remove_entry()`` may have unexpected results.
|
||||||
|
|
||||||
|
|
||||||
|
Tweaked Types
|
||||||
|
--------------
|
||||||
|
Sometimes your objects may be somewhat complex or use a nested structure. This fork allows nesting by using the pickle
|
||||||
|
module, which gives you the ability to turn your objects into pure bytes that can be written to and from the database.
|
||||||
|
When the ``tweaked`` parameter is enabled, data that can be written natively is written as is, and data that cannot be
|
||||||
|
written in this way is first processed by pickle.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from aiodatalite import datalite
|
||||||
|
from aiodatalite.typed import DataliteHinted
|
||||||
|
|
||||||
|
# Bag dataclass defined somewhere
|
||||||
|
|
||||||
|
@datalite(db_path='db.db')
|
||||||
|
@dataclass
|
||||||
|
class Student(DataliteHinted):
|
||||||
|
student_id: int = 1
|
||||||
|
student_name: str = "Kurt Gödel"
|
||||||
|
student_gpa: float = 3.9
|
||||||
|
bag: Bag = Bag(
|
||||||
|
size="big",
|
||||||
|
items_number=88,
|
||||||
|
...
|
||||||
|
)
|
||||||
|
|
||||||
|
But with great opportunity comes great responsibility, so using nested models can lead to difficulties in migrating data
|
||||||
|
and updating the structure of nested objects, so changing the ``Bag`` object in this example, in theory, can break the
|
||||||
|
database without the possibility of migration. We recommend using multiple tables and simple relationships between them
|
||||||
|
(must be organized independently) in such cases.
|
||||||
|
|
||||||
|
The tweaked functionality of types can be disabled by passing the tweaked parameter as False to the datalite decorator
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from aiodatalite import datalite
|
||||||
|
from aiodatalite.typed import DataliteHinted
|
||||||
|
|
||||||
|
# Bag is defined somewhere as datalite table instance
|
||||||
|
|
||||||
|
@datalite(db_path='db.db', tweaked=False)
|
||||||
|
@dataclass
|
||||||
|
class Student(DataliteHinted):
|
||||||
|
bag_id: int
|
||||||
|
student_id: int = 1
|
||||||
|
student_name: str = "Kurt Gödel"
|
||||||
|
student_gpa: float = 3.9
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
Fetching Functions
|
Fetching Functions
|
||||||
===================
|
===================
|
||||||
|
|
||||||
A database is hardly useful if data does not persist between program runs. In ``datalite``
|
A database is hardly useful if data does not persist between program runs. In ``aiodatalite``
|
||||||
one can use ``datalite.fetch`` module to fetch data back from the database.
|
one can use ``aiodatalite.fetch`` module to fetch data back from the database.
|
||||||
|
|
||||||
There are different sorts of fetching. One can fetch all the objects of a class
|
There are different sorts of fetching. One can fetch all the objects of a class
|
||||||
using ``fetch_all(class_)``, or an object with a specific object id using ``fetch_from(class_, obj_id)``.
|
using ``await fetch_all(class_)``, or an object with a specific object id using ``await fetch_from(class_, obj_id)``
|
||||||
|
(useful when you know object id inside database, but lost the reference to the object itself somewhere).
|
||||||
There are more functions for plural conditional fetching (``fetch_if``, ``fetch_where``) where
|
There are more functions for plural conditional fetching (``fetch_if``, ``fetch_where``) where
|
||||||
all objects fitting a condition will be returned, as well as singular conditional fetching that returns
|
all objects fitting a condition will be returned, as well as singular conditional fetching that returns
|
||||||
the first object that fits a condition (``fetch_equals``).
|
the first object that fits a condition (``fetch_equals``).
|
||||||
@@ -13,7 +14,7 @@ the first object that fits a condition (``fetch_equals``).
|
|||||||
Pagination
|
Pagination
|
||||||
##########
|
##########
|
||||||
|
|
||||||
Pagination is a feature that allows a portion of the results to be returned. Since ``datalite``
|
Pagination is a feature that allows a portion of the results to be returned. Since ``aiodatalite``
|
||||||
is built to work with databases that may include large amounts of data, many systems using large
|
is built to work with databases that may include large amounts of data, many systems using large
|
||||||
portions of data also make use of pagination. By building pagination inside the system, we hope to
|
portions of data also make use of pagination. By building pagination inside the system, we hope to
|
||||||
allow easier usage.
|
allow easier usage.
|
||||||
@@ -29,4 +30,4 @@ each page has. When ``page`` is set to 0, all results are returned irregardless
|
|||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
More information regarding the ``datalite.fetch`` functions can be found in the API reference.
|
More information regarding the ``aiodatalite.fetch`` functions can be found in the API reference.
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
.. Datalite documentation master file, created by
|
Welcome to aioatalite's documentation!
|
||||||
sphinx-quickstart on Thu Aug 13 21:01:34 2020.
|
|
||||||
You can adapt this file completely to your liking, but it should at least
|
|
||||||
contain the root `toctree` directive.
|
|
||||||
|
|
||||||
|
|
||||||
Welcome to Datalite's documentation!
|
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
Datalite is a simple to use Python library that can bind a dataclass to an
|
aioatalite is a simple to use async Python library that can bind a dataclass to an
|
||||||
sqlite3 database.
|
sqlite3 database.
|
||||||
|
|
||||||
|
|
||||||
@@ -22,7 +16,7 @@ Documentation
|
|||||||
constraints
|
constraints
|
||||||
fetch
|
fetch
|
||||||
migration
|
migration
|
||||||
datalite
|
aiodatalite
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
Getting Started
|
Getting Started
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Welcome to the documentation of datalite. Datalite provides a simple, intuitive way to bind dataclasses
|
Welcome to the documentation of aiodatalite, an asynchronous fork of datalite. Datalite provides a simple, intuitive
|
||||||
to sqlite3 databases. In its current version, it provides implicit support for conversion between
|
way to bind dataclasses to sqlite3 databases. In its current version, it provides implicit support for conversion
|
||||||
``int``, ``float``, ``str``, ``bytes`` classes and their ``sqlite3`` counterparts, default values,
|
between ``int``, ``float``, ``str``, ``bytes`` classes and their ``sqlite3`` counterparts, default values,
|
||||||
basic schema migration and fetching functions.
|
basic schema migration and fetching functions.
|
||||||
|
Also, aiodatalite introduces ``tweaked`` parameter (True by default), which allows using pickle to store any values
|
||||||
|
in database
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
############
|
############
|
||||||
@@ -13,11 +15,11 @@ Simply write:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
pip install datalite
|
pip install aiodatalite
|
||||||
|
|
||||||
In the shell. And then, whenever you want to use it in Python, you can use:
|
In the shell. And then, whenever you want to use it in Python, you can use:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
import datalite
|
import aiodatalite
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
@ECHO OFF
|
|
||||||
|
|
||||||
pushd %~dp0
|
|
||||||
|
|
||||||
REM Command file for Sphinx documentation
|
|
||||||
|
|
||||||
if "%SPHINXBUILD%" == "" (
|
|
||||||
set SPHINXBUILD=sphinx-build
|
|
||||||
)
|
|
||||||
set SOURCEDIR=.
|
|
||||||
set BUILDDIR=_build
|
|
||||||
|
|
||||||
if "%1" == "" goto help
|
|
||||||
|
|
||||||
%SPHINXBUILD% >NUL 2>NUL
|
|
||||||
if errorlevel 9009 (
|
|
||||||
echo.
|
|
||||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
|
||||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
|
||||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
|
||||||
echo.may add the Sphinx directory to PATH.
|
|
||||||
echo.
|
|
||||||
echo.If you don't have Sphinx installed, grab it from
|
|
||||||
echo.http://sphinx-doc.org/
|
|
||||||
exit /b 1
|
|
||||||
)
|
|
||||||
|
|
||||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:help
|
|
||||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
|
||||||
|
|
||||||
:end
|
|
||||||
popd
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
Schema Migrations
|
Schema Migrations
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Datalite provides a module, ``datalite.migrations`` that handles schema migrations. When a class
|
Datalite provides a module, ``aiodatalite.migrations`` that handles schema migrations. When a class
|
||||||
definition is modified, ``datalite.migrations.basic_migration`` can be called to automatically
|
definition is modified, ``aiodatalite.migrations.migrate`` can be called to
|
||||||
transfer records to a table fitting the new definitions.
|
transfer records to a table fitting the new definitions.
|
||||||
|
|
||||||
Let us say we have made changes to the fields of a dataclass called ``Student`` and now,
|
Let us say we have made changes to the fields of a dataclass called ``Student`` and now,
|
||||||
@@ -13,7 +13,34 @@ name change. We can achieve this easily by:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
datalite.basic_migration(Student, {'studentt_id': 'student_id'})
|
await migrate(Student, {'studentt_id': 'student_id'})
|
||||||
|
|
||||||
This will make all the changes, if we had not provided the second argument,
|
This will make all the changes, if we had not provided the second argument,
|
||||||
the values would be lost.
|
the values would be lost.
|
||||||
|
|
||||||
|
Also, ``migrate`` provides automatic backup before migration, you can turn it off by passing ``do_backup=False`` into
|
||||||
|
function.
|
||||||
|
|
||||||
|
We also introduce safe migration defaults. This parameter should be passed a key-value dictionary, where the key is the
|
||||||
|
name of the new required field, and the value is what should be written to the old records in the database.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from aiodatalite import datalite
|
||||||
|
from aiodatalite.typed import DataliteHinted
|
||||||
|
@datalite(db_path='db.db')
|
||||||
|
@dataclass
|
||||||
|
class Student(DataliteHinted):
|
||||||
|
new_obligatory_field: str # the database will break if not all records have this field
|
||||||
|
student_id: int = 1
|
||||||
|
student_name: str = "Kurt Gödel"
|
||||||
|
student_gpa: float = 3.9
|
||||||
|
|
||||||
|
So in this situation basically what you need to do is:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
await migrate(Student, safe_migration_defaults={
|
||||||
|
"new_obligatory_field": "some value for records that already exist in the database"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user