Update docs

This commit is contained in:
hhh
2024-03-17 17:26:03 +02:00
parent bb2b5e6a4f
commit fe1554045e
11 changed files with 152 additions and 98 deletions

4
.gitignore vendored
View File

@@ -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/

View File

@@ -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)

View File

@@ -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:

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"
}
)