update docstring formats to RST for Sphinx docs

This commit is contained in:
Sam G. 2024-04-28 18:04:07 -07:00
parent 2c72ce80e5
commit b3dc2a0876
32 changed files with 357 additions and 605 deletions

View File

@ -1,43 +1,46 @@
'''
Database submodule
- `db`: contains SQLAlchemy-based schema definitions
- `accessors`: convenience methods for accessing database entries
- `populate`: convenience methods for populating database tables
- ``db``: contains SQLAlchemy-based schema definitions
- ``accessors``: convenience methods for accessing database entries
- ``populate``: convenience methods for populating database tables
The `accessors` and `populate` submodules are each split into `schema` and `fts` method
The ``accessors`` and ``populate`` submodules are each split into ``schema`` and ``fts`` method
groups. The former concerns methods relating to the actual database schema, the latter to
their SQLite FTS counterparts.
Note: Subpackages organization
.. admonition:: Subpackages organization
Subpackages are broken up by inheritance. Within a given submodule, you have a
`_base.py` file defining the base class associated with that submodule's title, along
``_base.py`` file defining the base class associated with that submodule's title, along
with concrete subclasses of that base in their own files. Deeper inheritance would
recursively extend this structure. The `__init__.py` for a given submodule then
recursively extend this structure. The ``__init__.py`` for a given submodule then
exposes the concrete instances, leaving the base hidden. For example,
accessors/
_base.py
core.py
fts.py
.. code-block::
`core` and `fts` house the `CoreAccessor` and `FTSAccessor` classes, respectively,
and are the direct subclasses of the `Accessor` parent found in the `_base`. This base
class _could_ be placed outside of the submodule in the parent directory (imported
with something like `from db import accessor` instead of `from db.accessor import
_base`). This is entirely valid, but I tend to prefer when the base class is among its
accessors/
_base.py
core.py
fts.py
``core`` and ``fts`` house the ``CoreAccessor`` and ``FTSAccessor`` classes, respectively,
and are the direct subclasses of the ``Accessor`` parent found in the ``_base``. This base
class *could* be placed outside of the submodule in the parent directory (imported
with something like ``from db import accessor`` instead of ``from db.accessor import
_base``). This is entirely valid, but I tend to prefer when the base class is among its
direct children, as
- In this case at least, the base doesn't need to be exposed
- The base class is being stowed away under an appropriately named submodule; having a
separate `accessor.py` and `accessors/` file/directory can feel a little cluttered.
separate ``accessor.py`` and ``accessors/`` file/directory can feel a little cluttered.
- It makes imports across the accessors feel standardized:
```py
from localsys.db.accessors._base import Accessor
.. code-block:: python
from localsys.db.accessors.core import CoreAccessor
```
from localsys.db.accessors._base import Accessor
from localsys.db.accessors.core import CoreAccessor
Both have the same level of nesting to reach the class.
@ -46,46 +49,49 @@ Note: Subpackages organization
the moment, and so long as I keep things consistent, choosing one over the other
shouldn't matter.
Additionally, note how `__init__.py`s are typically set up when providing wider access
to internal modules. The `init` typically pulls out classes from sibling modules
Additionally, note how ``__init__.py``s are typically set up when providing wider access
to internal modules. The ``init`` typically pulls out classes from sibling modules
(i.e., files), but will import subpackages are the topmost level. For example, for the
structure
```
db/
__init__.py
accessors/
.. code-block::
db/
__init__.py
_base.py
core.py
fts.py
```
accessors/
__init__.py
_base.py
core.py
fts.py
we have
```db/__init__.py
from localsys.db import accessors
```
.. code-block::
:name: db/__init__.py
which just imports the subpackage `accessors`. However, within subpackage:
from localsys.db import accessors
```db/accessors/__init__.py
from localsys.db.accessors.core import CoreAccessor
```
which just imports the subpackage ``accessors``. However, within subpackage:
we don't just import the submodule `core`; we did into the file to grab the relevant
class and pull it into the outer namespace. Overarching point: `__init__.py` files
.. code-block::
:name: db/accessors/__init__.py
from localsys.db.accessors.core import CoreAccessor
we don't just import the submodule ``core``; we did into the file to grab the relevant
class and pull it into the outer namespace. Overarching point: ``__init__.py`` files
typically reach into the sibling files (submodules) and pull out classes. Given that
this behavior is recursive, `__init__.py` then respect subpackages (nested
directories), importing them at the top-level and expecting an internal `__init__.py`
this behavior is recursive, ``__init__.py`` then respect subpackages (nested
directories), importing them at the top-level and expecting an internal ``__init__.py``
will have managed access appropriately.
Note: Organization for inheritance over composition
.. admonition:: Organization for inheritance over composition
At a glance, the organization of subpackages here feels like it clashes with those
seen in `localsys.primitives`. `note_components`, for instance, houses the components
for the outer `note` module. Contrast this with how the `core` submodule looks: it's
composing `*/core.py` files across subpackages `accessors` and `managers`, rather than
a single subpackage like `note`. This seems inconsistent, but the subpackages here are
seen in ``localsys.primitives``. ``note_components``, for instance, houses the components
for the outer ``note`` module. Contrast this with how the ``core`` submodule looks: it's
composing ``*/core.py`` files across subpackages ``accessors`` and ``managers``, rather than
a single subpackage like ``note``. This seems inconsistent, but the subpackages here are
actually still organized in the same way: by inheritance. It just happens that the
all of the note components inherit from the same base class, and are thus confined to
a single subpackage. This aside, the subpackages themselves are still created around

View File

@ -1,5 +1,5 @@
'''
**Accessor**
Accessor
Provides access to an underlying schema through a supported set of operations. Class
methods could be general, high-level SQL wrappers, or convenience functions for common

View File

@ -15,8 +15,8 @@ subclasses.
For instance, you could wrap an FTSComposer in either a TableAccessor or FTSAccessor. The
former will treat the tables in the composer like regular tables, exposing methods like
`.select` and `.select_one`, whereas the latter defines FTS-specific actions like
`.search`.
``.select`` and ``.select_one``, whereas the latter defines FTS-specific actions like
``.search``.
'''
from co3.accessors.sql import SQLAccessor

View File

@ -25,12 +25,12 @@ class FTSAccessor(Accessor):
'''
Execute a search query against an indexed FTS table for specific primitives. This
method is mostly a generic FTS handler, capable of handling queries to any available
FTS table with a matching naming scheme (`fts_<type>_<tokenizer>`). The current
FTS table with a matching naming scheme (``fts_<type>_<tokenizer>``). The current
intention is support all tokenizers, for file, note, block, and link primitives.
Search results include all FTS table columns, as well as SQLite-supported `snippet`s
and `highlight`s for matches. Matches are filtered and ordered by SQLite's
`MATCH`-based score for the text & column queries. Results are (a list of) fully
Search results include all FTS table columns, as well as SQLite-supported ``snippet``s
and ``highlight``s for matches. Matches are filtered and ordered by SQLite's
``MATCH``-based score for the text & column queries. Results are (a list of) fully
expanded dictionaries housing column-value pairs.
Note:
@ -55,7 +55,7 @@ class FTSAccessor(Accessor):
search_cols : space separated string of columns to use for primary queries
q : search query
colq : column constraint string; must conform to SQLite standards (e.g.,
`<col>:<text>`
``<col>:<text>``
snip_col : table column to use for snippets (default: 1; source content column)
hl_col : table column to use for highlights (default: 2; format column, applied
to HTML targets)

View File

@ -3,34 +3,34 @@ Design proposal: variable backends
One particular feature not supported by the current type hierarchy is the possible use of
different backends to implement a general interface like SQLAccessor. One could imagine,
for instance, using `sqlalchemy` or `sqlite` to define the same methods laid out in a
for instance, using ``sqlalchemy`` or ``sqlite`` to define the same methods laid out in a
parent class blueprint. It's not too difficult to imagine cases where both of these may be
useful, but for now it is outside the development scope. Should it ever enter the scope,
however, we might consider a simple `backend` argument on instantiation, keeping just the
however, we might consider a simple ``backend`` argument on instantiation, keeping just the
SQLAccessor exposed rather than a whole set of backend-specific types:
```py
class SQLAlchemyAccessor(RelationalAccessor): # may also inherit from a dedicated interface parent
def select(...):
...
.. code-block:: python
class SQLiteAccessor(RelationalAccessor):
def select(...):
...
class SQLAlchemyAccessor(RelationalAccessor): # may also inherit from a dedicated interface parent
def select(...):
...
class SQLAccessor(RelationalAccessor):
backends = {
'sqlalchemy': SQLAlchemyAccessor,
'sqlite': SQLteAccessor,
}
class SQLiteAccessor(RelationalAccessor):
def select(...):
...
def __init__(self, backend: str):
self.backend = self.backends.get(backend)
class SQLAccessor(RelationalAccessor):
backends = {
'sqlalchemy': SQLAlchemyAccessor,
'sqlite': SQLteAccessor,
}
def select(...):
return self.backend.select(...)
def __init__(self, backend: str):
self.backend = self.backends.get(backend)
def select(...):
return self.backend.select(...)
```
For now, we can look at SQLAccessor (and equivalents in other type hierarchies, like
SQLManagers) as being SQLAlchemyAccessors and not supporting any backend swapping. But in
@ -130,7 +130,7 @@ class SQLAccessor(RelationalAccessor[SQLTable]):
): # -> list[dict|sa.Mapping]: (double check the Mapping types)
'''
Perform a SELECT query against the provided table-like object (see
`check_table()`).
``check_table()``).
Deprecated: String aliases
String aliases for tables are no longer supported. This method no longer checks
@ -177,7 +177,7 @@ class SQLAccessor(RelationalAccessor[SQLTable]):
Parse SQLAlchemy results into Python dicts. Leverages mappings to associate full
column name context.
If `query_cols` is provided, their implicit names will be used for the keys of the
If ``query_cols`` is provided, their implicit names will be used for the keys of the
returned dictionaries. This information is not available under CursorResults and thus
must be provided separately. This will yield results like the following:

View File

@ -1,7 +1,7 @@
'''
CO4
CO3
CO4 is an abstract base class for scaffolding object hierarchies and managing operations
CO3 is an abstract base class for scaffolding object hierarchies and managing operations
with associated database schemas. It facilitates something like a "lightweight ORM" for
classes/tables/states with fixed transformations of interest. The canonical use case is
managing hierarchical document relations, format conversions, and syntactical components.
@ -60,13 +60,16 @@ class FormatRegistryMeta(type):
class CO3(metaclass=FormatRegistryMeta):
'''
CO3: COllate, COllect, COmpose - conversion & DB insertion base
Conversion & DB insertion base class
CO3: COllate, COllect, COmpose
- Collate: organize and transform conversion outputs, possibly across class components
- Collect: gather core attributes, conversion data, and subcomponents for DB insertion
- Compose: construct object-associated DB table references through the class hierarchy
Note: on action groups
.. admonition:: on action groups
Group keys are simply named collections to make it easy for storage components to
be attached to action subsets. They do _not_ augment the action registration
namespace, meaning the action key should still be unique; the group key is purely
@ -74,14 +77,14 @@ class CO3(metaclass=FormatRegistryMeta):
Action methods can also be attached to several groups, in case there is
overlapping utility within or across schemas or storage media. In this case, it
becomes particularly critical to ensure registered `collate` methods really are
becomes particularly critical to ensure registered ``collate`` methods really are
just "gathering results" from possibly heavy-duty operations, rather than
performing them when called, so as to reduce wasted computation.
'''
@property
def attributes(self):
'''
Method to define how a subtype's inserts should be handled under `collect` for
Method to define how a subtype's inserts should be handled under ``collect`` for
canonical attributes, i.e., inserts to the type's table.
'''
return vars(self)
@ -89,7 +92,7 @@ class CO3(metaclass=FormatRegistryMeta):
@property
def components(self):
'''
Method to define how a subtype's inserts should be handled under `collect` for
Method to define how a subtype's inserts should be handled under ``collect`` for
constituent components that need handling.
'''
return []
@ -99,9 +102,9 @@ class CO3(metaclass=FormatRegistryMeta):
Return "connective" collation component data, possibly dependent on
instance-specific attributes and the action arguments. This is typically the
auxiliary structure that may be needed to attach to responses from registered
`collate` calls to complete inserts.
``collate`` calls to complete inserts.
Note: this method is primarily used by `Mapper.collect()`, and is called just
Note: this method is primarily used by ``Mapper.collect()``, and is called just
prior to collector send-off for collation inserts and injected alongside collation
data. Common structure in collation components can make this function easy to
define, independent of action group for instance.

View File

@ -6,10 +6,11 @@ their representations in the database. It operates with full knowledge of how bo
defined, and abstracts away both the prep work for DB insertions as well as updates
trickling down the primitive hierarchy.
The `src` format target is re-used for both canonical tables/primitives, as well as
<prim>_conversion_matter tables in tables/conversions under the `src` format. The latter
is meant to extend those attributes that are format-specific (i.e., would change when, say,
converting to `html5`), and thus need to be broken across the format dimension.
The ``src`` format target is re-used for both canonical tables/primitives, as well as
``<prim>_conversion_matter`` tables in tables/conversions under the ``src`` format. The
latter is meant to extend those attributes that are format-specific (i.e., would change
when, say, converting to ``html5``), and thus need to be broken across the format
dimension.
Note:
Despite the structure of the database module, this class does not currently inherit
@ -46,8 +47,8 @@ class Collector[C: Component]:
def _inserts_from_receipts(self, receipts: list[str]|None=None, pop=False):
'''
Group up added inserts by Component, often to be used directly for bulk insertion.
Optionally provide a list of `receipts` to group up only the corresponding subset of
inserts, and `pop` to remove encountered receipts from the internal store.
Optionally provide a list of ``receipts`` to group up only the corresponding subset of
inserts, and ``pop`` to remove encountered receipts from the internal store.
'''
inserts = defaultdict(list)
@ -113,7 +114,7 @@ class Collector[C: Component]:
The overall collection scheme embraces a session-like sequential update model to
an internal insert tracker. The sequence of insert methods is ordered according to
the schema hierarchy, and higher level inserts dictate the scope for lower level
inserts (all methods check and populate the same `inserts` dictionary). Calling
inserts (all methods check and populate the same ``inserts`` dictionary). Calling
this method flushes any existing inserts, ensuring a re-scan takes place across
calls (or "sessions").

View File

@ -66,7 +66,7 @@ class SQLTable(Relation[SQLTableLike]):
def from_table(cls, table: sa.Table):
'''
Note that the sa.Table type is intentional here; not all matching types for
SQLTableLike have a defined `name` property
SQLTableLike have a defined ``name`` property
'''
return cls(table.name, table)

View File

@ -15,32 +15,34 @@ under one roof. This includes the Engine (opens up connections to the database),
insert-like actions), and Indexers (systematically caching Accessor queries). Generalized
behavior is supported by explicitly leveraging the individual components. For example,
```
with db.engine.connect() as connection:
db.access.select(
connection,
<query>
)
db.manager.insert(
connection,
component,
data
)
```
.. code-block:: python
with db.engine.connect() as connection:
db.access.select(
connection,
<query>
)
db.manager.insert(
connection,
component,
data
)
The Database also supports a few directly callable methods for simplified interaction.
These methods manage a connection context internally, passing them through the way they
might otherwise be handled explicitly, as seen above.
```
db.select(<query>)
.. code-block:: python
db.insert(<query>, data)
```
db.select(<query>)
db.insert(<query>, data)
.. admonition:: on explicit connection contexts
Dev note: on explicit connection contexts
Older models supported Accessors/Managers that housed their own Engine instances, and
when performing actions like `insert`, the Engine would be passed all the way through
when performing actions like ``insert``, the Engine would be passed all the way through
until a Connection could be spawned, and in that context the single action would be
made. This model forfeits a lot of connection control, preventing multiple actions
under a single connection.
@ -71,23 +73,23 @@ class Database[C: Component]:
generic openness must be propagated here, as it's intended to be fully abstracted away
under the Database roof. Note that we cannot explicitly use an Engine type in its
place, as it obscures its internal resource type dependence when we need it for
hinting here in `__init__`.
hinting here in ``__init__``.
Development TODO list:
- Decide on official ruling for assigning Schema objects, and verifying any
attempted Component-based actions (e.g., inserts, selects) to belong to or be a
composition of Components within an attached Schema. Reasons for: helps complete
the sense of a "Database" here programmatically, incorporating a more
structurally accurate representation of allowed operations, and prevent possible
attribute and type collisions. Reasons against: generally not a huge concern to
align Schemas as transactions will rollback, broadly increases a bit of bulk,
and users often expected know which components belong to a particular DB.
Leaning more to **for**, and would only apply to the directly supported method
passthroughs (and thus would have no impact on independent methods like
`Accessor.raw_select`). Additionally, even if component clashes don't pose
serious risk, it can be helpful to systematically address the cases where a
misalignment is occurring (by having helpful `verify` methods that can be ran
before any actions).
.. admonition:: Development TODO list
Decide on official ruling for assigning Schema objects, and verifying any
attempted Component-based actions (e.g., inserts, selects) to belong to or be a
composition of Components within an attached Schema. Reasons for: helps complete
the sense of a "Database" here programmatically, incorporating a more structurally
accurate representation of allowed operations, and prevent possible attribute and
type collisions. Reasons against: generally not a huge concern to align Schemas as
transactions will rollback, broadly increases a bit of bulk, and users often
expected know which components belong to a particular DB. Leaning more to **for**,
and would only apply to the directly supported method passthroughs (and thus would
have no impact on independent methods like ``Accessor.raw_select``). Additionally,
even if component clashes don't pose serious risk, it can be helpful to
systematically address the cases where a misalignment is occurring (by having
helpful ``verify`` methods that can be ran before any actions).
'''
_accessor_cls: type[Accessor[C]] = Accessor[C]
_manager_cls: type[Manager[C]] = Manager[C]
@ -119,10 +121,12 @@ class Database[C: Component]:
def select(self, component: C, *args, **kwargs):
'''
Dev note: args and kwargs have to be general/unspecified here due to the possible
passthrough method adopting arbitrary parameters in subtypes. I could simply
overload this method in the relevant inheriting DBs (i.e., by matching the
expected Accessor's .select signature).
.. admonition:: Dev note
args and kwargs have to be general/unspecified here due to the possible
passthrough method adopting arbitrary parameters in subtypes. I could simply
overload this method in the relevant inheriting DBs (i.e., by matching the
expected Accessor's .select signature).
'''
with self.engine.connect() as connection:
return self.accessor.select(
@ -154,7 +158,7 @@ class Database[C: Component]:
@property
def manage(self):
'''
Accessing `.manage` queues a cache clear on the external index, as well wipes the
Accessing ``.manage`` queues a cache clear on the external index, as well wipes the
local index.
'''
self.reset_cache = True

View File

@ -10,8 +10,8 @@ from co3.components import Relation, SQLTable
class RelationalDatabase[C: RelationR](Database):
'''
accessor/manager assignments satisfy supertype's type settings;
`TabluarAccessor[Self, C]` is of type `type[RelationalAccessor[Self, C]]`
(and yes, `type[]` specifies that the variable is itself being set to a type or a
``TabluarAccessor[Self, C]`` is of type ``type[RelationalAccessor[Self, C]]``
(and yes, ``type[]`` specifies that the variable is itself being set to a type or a
class, rather than a satisfying _instance_)
'''
_accessor_cls: type[RelationalAccessor[C]] = RelationalAccessor[C]

View File

@ -17,7 +17,8 @@ class Engine:
other type, although it may appear that way when such a type is in fact readily
available).
Dev note: why is this object necessary?
.. admonition:: why is this object necessary?
More specifically, why not just have all the functionality here packed into the
Database by default? The answer is that, realistically, it could be. The type
separation between the Engine and Database is perhaps the least substantiated in
@ -30,7 +31,8 @@ class Engine:
unique Database type), a separate object here would indeed be a waste, as is the
case for any compositional typing scheme.
Dev note:
.. admonition:: dev note
This class is now non-generic. It was originally conceived as a generic, depending
on a "resource spec type" to be help define expected types on initialization.
This simply proved too messy, required generic type propagation to the Database
@ -55,7 +57,7 @@ class Engine:
def _create_manager(self):
'''
Create the session manager needed for connection contexts. This method is called
once by the `.manager` property function when it is first accessed. This method is
once by the ``.manager`` property function when it is first accessed. This method is
separated to isolate the creation logic in inheriting types.
Note that this method takes no explicit arguments. This is primarily because the

View File

@ -77,11 +77,11 @@ class Indexer:
index_on = None,
):
'''
Like `group_by`, but makes a full query to the Accessors table `table_name` and
Like ``group_by``, but makes a full query to the Accessors table ``table_name`` and
caches the results. The processing performed by the GROUP BY is also cached.
Update: `cached_select` and `cached_group_by` now unified by a single
`cached_query` method. This allows better defined GROUP BY caches, that are
Update: ``cached_select`` and ``cached_group_by`` now unified by a single
``cached_query`` method. This allows better defined GROUP BY caches, that are
reactive to the full set of parameters returning the result set (and not just the
table, requiring a full query).
@ -93,12 +93,12 @@ class Indexer:
which will look the same regardless of instance.
Context: this became a clear issue when passing in more
`order_by=<col>.desc()`. The `desc()` causes the index to store the column in
``order_by=<col>.desc()``. The ``desc()`` causes the index to store the column in
an instance-specific way, rather than an easily re-usable, canonical column
reference. Each time the CoreDatabase.files() was being called, for instance,
that @property would be re-evaluated, causing `desc()` to be re-initialized,
that @property would be re-evaluated, causing ``desc()`` to be re-initialized,
and thus look different to the cache. Stringifying everything prevents this
(although this could well be an indication that only a single `cache_block`
(although this could well be an indication that only a single ``cache_block``
should ever be returned be database properties).
Note: on access locks
@ -193,7 +193,7 @@ class Indexer:
):
'''
Post-query "group by"-like aggregation. Creates an index over a set of columns
(`group_by_cols`), and aggregates values from `agg_cols` under the groups.
(``group_by_cols``), and aggregates values from ``agg_cols`` under the groups.
Rows can be dicts or mappings, and columns can be strings or SQLAlchemy columns.
To ensure the right columns are being used for the operation, it's best to pass in
@ -319,49 +319,49 @@ class Indexer:
class CacheBlock:
'''
CacheBlock class
Wraps up a set of query parameters for a specific entity, and provides cached access
to different types of "re-queries" via an associated Indexer.
The goal here is to help build/define entities as the possibly complex transformations
on the base schema that they are. For example, the Note primitive (entity)
incorporates details across `files`, `notes`, `note_conversions`, and
`note_conversion_matter` tables (defined in a single endpoint by a Composer), often
needs to be selected in particular ways (via an Accessor), and results stored for fast
access later on (handled by an Indexer). This pipeline can be daunting and requires
too many moving parts to be handled explicitly everywhere. CacheBlocks wrap up a set
of query "preferences," exposing a simpler interface for downstream access to
entities. It still allows for low-level control over re-grouping/indexing, raw hits to
the actual DB, etc, but keeps things tighter and well-behaved for the Indexer.
.. admonition:: Additional details
You can think of these as the Indexer's "fingers"; they're deployable mini-Indexes
that "send back" results to the class cache, which is "broadcast" to all other
instances for use when necessary.
The goal here is to help build/define entities as the possibly complex
transformations on the base schema that they are. For example, the Note primitive
(entity) incorporates details across ``files``, ``notes``, ``note_conversions``,
and ``note_conversion_matter`` tables (defined in a single endpoint by a
Composer), often needs to be selected in particular ways (via an Accessor), and
results stored for fast access later on (handled by an Indexer). This pipeline can
be daunting and requires too many moving parts to be handled explicitly
everywhere. CacheBlocks wrap up a set of query "preferences," exposing a simpler
interface for downstream access to entities. It still allows for low-level control
over re-grouping/indexing, raw hits to the actual DB, etc, but keeps things
tighter and well-behaved for the Indexer.
Note: Example usage
You can think of these as the Indexer's "fingers"; they're deployable mini-Indexes
that "send back" results to the class cache, which is "broadcast" to all other
instances for use when necessary.
```py
cb = CacheBlock()
.. admonition:: Example usage
# Set up cached queries with chained params or via call:
.. code-block:: python
cb.where(t.notes.c.name=="name").group_by(t.note_conversions.c.format)
cb() # get results
cb = CacheBlock()
# - OR - # (use strings when known)
# Set up cached queries with chained params or via call:
cb.where(t.notes.c.name=="name").group_by('format')
cb() # get results
cb.where(t.notes.c.name=="name").group_by(t.note_conversions.c.format)
cb() # get results
# - OR - # (use kwargs in the call; results returned right away)
# - OR - # (use strings when known)
cb(
where=(t.notes.c.name=="name"),
group_by='format'
)
```
cb.where(t.notes.c.name=="name").group_by('format')
cb() # get results
# - OR - # (use kwargs in the call; results returned right away)
cb(
where=(t.notes.c.name=="name"),
group_by='format'
)
'''
def __init__(
self,

View File

@ -1,6 +1,6 @@
'''
Note: Common on insert behavior
- Tables with unique constraints have been equipped with `sqlite_on_conflict_unique`
- Tables with unique constraints have been equipped with ``sqlite_on_conflict_unique``
flags, enabling conflicting bulk inserts to replace conflicting rows gracefully. No
need to worry about explicitly handling upserts.
- The bulk insert via conn.execute(<insert>,<row_list>) automatically ignores
@ -15,17 +15,17 @@ Note: Options for insert/update model
the right approach since we defer as much to bulk SQL logic, but it's far and away
the worse option b/c prepping all file/note/etc objects is too expensive to
ultimately throw away when finding out an update isn't needed. For example, if we
wanted to perform note updates _inside_ the SQL call (like an `INSERT .. UPDATE ..
IF`, as opposed to determining the objects to insert _outside_ of the SQL call),
wanted to perform note updates _inside_ the SQL call (like an ``INSERT .. UPDATE ..
IF``, as opposed to determining the objects to insert _outside_ of the SQL call),
you would need to bring each of the note's HTML prior to the insert check. There's
no 2-stage processing here where you can check if the note needs to be converted
b/c it's out of date, and only then perform the computation.
2. Instantiate objects sequentially, each time checking with the DB to see if full
processing is needed. This makes much more sense when the full processing is very
expensive, as it is with Note conversion. This would iterate through available notes,
perform a `SELECT` on the target table to see if the note needs updating, and if so
perform a ``SELECT`` on the target table to see if the note needs updating, and if so
perform the remaining computation. Those objects then get added to a "update object
list" to be inserted in bulk, but you make sequential `SELECT` checks before that.
list" to be inserted in bulk, but you make sequential ``SELECT`` checks before that.
The one extra optimization you could maybe make here is doing a full SELECT on the
target table and bring all rows into memory before iterating through the objects.
@ -69,7 +69,7 @@ class SQLManager(RelationalManager[SQLTable]):
of rows and bundle them under a single transaction. This is important for table groups
with foreign keys and cascading deletions: inserts need to be coordinated. Note that
actually collecting the inserts that need to take place is outside the scope of the
Manager (see the Collector). We do, however, implement a `sync` operation that can
Manager (see the Collector). We do, however, implement a ``sync`` operation that can
saturates a router with events (dynamically) and sweeps up inserts on session basis
from an attached collector.
'''

View File

@ -7,23 +7,26 @@ auto-collection and composition.
Example:
mapper = Mapper[sa.Table]()
.. code-block:: python
mapper.attach(
Type,
attr_comp=TypeTable,
coll_comp=CollateTable,
coll_groups={
'name': NameConversions
}
)
mapper = Mapper[sa.Table]()
mapper.attach(
Type,
attr_comp=TypeTable,
coll_comp=CollateTable,
coll_groups={
'name': NameConversions
}
)
.. admonition:: Development log
Development log:
- Overruled design decision: Mappers were previously designed to map from a specific
CO3 hierarchy to a specific Schema. The intention was to allow only related types to
be attached to a single schema, at least under a particular Mapper. The type
restriction has since been removed, however, as it isn't particularly well-founded.
During `collect()`, a particular instance collects data from both its attributes and
During ``collect()``, a particular instance collects data from both its attributes and
its collation actions. It then repeats the same upward for parent types (part of the
same type hierarchy), and down to components (often not part of the same type
hierarchy). As such, to fully collect from a type, the Mapper needs to leave
@ -51,11 +54,11 @@ class Mapper[C: Component]:
attached CO3 types
Additionally, the Mapper manages its own Collector and Composer instances. The
Collector receives the inserts from `.collect()` calls, and will subsequently be
Collector receives the inserts from ``.collect()`` calls, and will subsequently be
"dropped off" at an appropriate Database's Manager to actually perform the requested
inserts (hence why we tie Mappers to Schemas one-to-one).
Dev note:
.. admonition:: Dev note
the Composer needs reconsideration, or at least its positioning directly in this
class. It may be more appropriate to have at the Schema level, or even just
dissolved altogether if arbitrary named Components can be attached to schemas.
@ -135,7 +138,7 @@ class Mapper[C: Component]:
'''
Auto-register a set of types to the Mapper's attached Schema. Associations are
made from types to both attribute and collation component names, through
`attr_name_map` and `coll_name_map`, respectively. Collation targets are inferred
``attr_name_map`` and ``coll_name_map``, respectively. Collation targets are inferred
through the registered groups in each type.
Parameters:
@ -143,7 +146,7 @@ class Mapper[C: Component]:
attr_name_map: function mapping from types/classes to attribute component names
in the attached Mapper Schema
coll_name_map: function mapping from types/classes & action groups to
collation component names in the attached Mapper Schema. `None`
collation component names in the attached Mapper Schema. ``None``
is passed as the action group to retrieve the default
collection target.
'''
@ -192,7 +195,7 @@ class Mapper[C: Component]:
how inserts should be handled for inheritance. ORM would make component
inserts a little easier perhaps, since they can be attached as attributes to
constructed row objects and a sa.Relationship will handle the rest. Granted,
we don't do a whole lot more here: we just call `collect` over those
we don't do a whole lot more here: we just call ``collect`` over those
components, adding them to the collector session all the same.
Parameters:
@ -256,14 +259,15 @@ class Mapper[C: Component]:
class ComposableMapper[C: ComposableComponent](Mapper[C]):
'''
Dev note: class design
.. admonition:: class design
Heavily debating between multiple possible design approaches here. The main
purpose of this subtype is make clear the need for additional compositional
mapping details, namely functions that can produce pairwise join conditions for
both the attribute tree (vertical traversal) and the collation components
(horizontal traversal). Here's a few remarks:
- I want the necessary maps to provided/stored _outside_ of `compose` calls to
- I want the necessary maps to provided/stored *outside* of ``compose`` calls to
reduce overhead for downstream callers. It's awkward to have think about the
exact attr-to-attr associations each time you want a type's associated
composition, especially when they don't change under the same Mapper (i.e.,
@ -275,7 +279,7 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
more.
- Considering the full deprecation for the Composer type, or whether this could be
the place where it serves some purpose. Aesthetically, there's symmetry with the
`collect` and Collector method-type pairing, but that isn't a good enough reason
``collect`` and Collector method-type pairing, but that isn't a good enough reason
to justify a separate type here. The difference is that Collector instances
actually store type references, whereas the considered Composer type would
effectively just be a convenient collection of utility functions. Still possibly
@ -290,21 +294,21 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
* Mappers provide an exoskeleton for a Schema's nodes. It structures Components into
attributes and collation types, and additionally ties them to external CO3
types. The handy analogy here has been that attribute comps connect
_vertically_ (in a tree like fashion; point up for parents and down for
children), and collation comps point _horiztonally_ (or perhaps more aptly,
_outward_; at each node in the attribute tree, you have a "circle" of
*vertically* (in a tree like fashion; point up for parents and down for
children), and collation comps point *horizontally* (or perhaps more aptly,
*outward*; at each node in the attribute tree, you have a "circle" of
collation comps that can point to it, and are not involved as formal tree
nodes. Can maybe think of these like "ornaments" or bulbs or orbitals).
* While the Mappers may provide the "bones," there's no way to communicate
_across_ them. While I might know that one attribute is the "parent" of
another, I don't know _why_ that relationship is there. A Composer, or the
*across* them. While I might know that one attribute is the "parent" of
another, I don't know *why* that relationship is there. A Composer, or the
composer details to be provided to this class, serve as the "nerves" to be
paired with the bone, actually establishing a line of communication. More
specifically, the nerves here are attribute-based mappings between pairs of
Components, i.e., (generalized) join conditions.
- Note that, by the above logic, we should then want/need a type to manage the
functions provided to `attach_many`. These functions help automatically
functions provided to ``attach_many``. These functions help automatically
characterize the shape of the type skeleton in the same way the proposed
Composer wrapper would. In fact, the barebones presentation here is really just
the same two function signatures as are expected by that method. The above
@ -313,14 +317,14 @@ class ComposableMapper[C: ComposableComponent](Mapper[C]):
one goes, the other must as well. This may also help me keep it simpler for the
time being.
- One other aspect of a dedicated Composer type (and by the above point, a
hypothetical type to aid in `attach_many` specification) could have some sort of
hypothetical type to aid in ``attach_many`` specification) could have some sort of
"auto" feature about it. With a clear enough "discovery system," we could
encourage certain kinds of Schemas and components are named and structured. Such
an auto-composer could "scan" all components in a provided Schema and attempt to
find common attributes across tables that are unlinked (i.e., the reused
column names implicit across types in the attribute hierarchy; e.g., File.name
-> Note.name), as well as explicit connections which may suggest collation
attachment (e.g., `note_conversions.name` --FK-> Note.name). This, of course,
attachment (e.g., ``note_conversions.name --FK-> Note.name``). This, of course,
could always be overridden with manual specification, but being aware of some
automatic discovery structures could help constrain schema definitions to be
more in-line with the CO3 operational model. That all being said, this is a

View File

@ -4,7 +4,7 @@ Schema
Collection of related storage components, often representing the data structure of an
entire database. Some databases support multiple schemas, however. In general, a Schema
can wrap up an associated subset of components within a single database, so long as
`Manager.recreate()` supports creating components in separate calls (even if the
``Manager.recreate()`` supports creating components in separate calls (even if the
associated database doesn't explicitly support multiple schemas).
Schema objects are used to:

View File

@ -1,24 +1,26 @@
'''
Example usage for this file's utilities:
# get SA engine, creating folder hierarchy to provided DB path
engine = db.get_engine(<path>)
.. code-block:: python
# execute a single SA statement, returns a CursorResult
select_results = db.sa_execute(engine, sa.select(<table>))
# get SA engine, creating folder hierarchy to provided DB path
engine = db.get_engine(<path>)
# convert raw results to dictionaries, keys corresponding to col names
select_dicts = db.named_results(<table>, select_results)
# execute a single SA statement, returns a CursorResult
select_results = db.sa_execute(engine, sa.select(<table>))
# use table defaults and cols to create compliant insert
insert_dicts = [ db.prepare_insert(<table>, sd) for sd in select_dicts ]
# convert raw results to dictionaries, keys corresponding to col names
select_dicts = db.named_results(<table>, select_results)
# perform a bulk insert
with engine.connect() as connection:
connection.execute(
sa.insert(<table>),
insert_dicts
)
# use table defaults and cols to create compliant insert
insert_dicts = [ db.prepare_insert(<table>, sd) for sd in select_dicts ]
# perform a bulk insert
with engine.connect() as connection:
connection.execute(
sa.insert(<table>),
insert_dicts
)
'''
import time
@ -54,7 +56,7 @@ def deferred_fkey(target, **kwargs):
def deferred_cd_fkey(target, **kwargs):
'''
Prefer this when using FKEYs; need to really justify _not_ having a CASCADE deletion
Prefer this when using FKEYs; need to really justify *not* having a CASCADE deletion
enabled
'''
return deferred_fkey(target, ondelete='CASCADE', **kwargs)
@ -179,7 +181,7 @@ def create_vss0(
embedding_size=384,
):
'''
Create a VSS table
Create a VSS table.
Parameters:
table: either SQLAlchemy table instance, or table name string

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 42689903516d5840d143a46f4ba615c6
config: 31124ef51117182dc672bbc42963e105
tags: 645f666f9bcd5a90fca523b33c5a78b7

View File

@ -200,7 +200,6 @@
</ul>
<p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../reference/test.html">Test</a></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="../reference/documentation/index.html">Documentation</a><input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle navigation of Documentation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../reference/documentation/sphinx.html">Sphinx</a></li>
</ul>

View File

@ -30,8 +30,6 @@ _autoref/co3.rst
:maxdepth: 3
:caption: Contents
reference/test
reference/documentation/index
reference/site/index
```

View File

@ -198,7 +198,6 @@
</ul>
<p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="reference/test.html">Test</a></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="reference/documentation/index.html">Documentation</a><input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle navigation of Documentation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="reference/documentation/sphinx.html">Sphinx</a></li>
</ul>
@ -245,26 +244,34 @@
<h2>_</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.Accessor.html#co3.Accessor.__init__">__init__() (co3.Accessor method)</a>
<li><a href="_autoref/co3.accessors.vss.html#co3.accessors.vss.VSSAccessor.__init__">__init__() (co3.accessors.vss.VSSAccessor method)</a>
<ul>
<li><a href="_autosummary/co3.CO3.html#co3.CO3.__init__">(co3.CO3 method)</a>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector.__init__">(co3.collector.Collector method)</a>
</li>
<li><a href="_autosummary/co3.Collector.html#co3.Collector.__init__">(co3.Collector method)</a>
<li><a href="_autoref/co3.component.html#co3.component.Component.__init__">(co3.component.Component method)</a>
</li>
<li><a href="_autosummary/co3.Component.html#co3.Component.__init__">(co3.Component method)</a>
<li><a href="_autoref/co3.database.html#co3.database.Database.__init__">(co3.database.Database method)</a>
</li>
<li><a href="_autosummary/co3.Database.html#co3.Database.__init__">(co3.Database method)</a>
<li><a href="_autoref/co3.engine.html#co3.engine.Engine.__init__">(co3.engine.Engine method)</a>
</li>
<li><a href="_autosummary/co3.Engine.html#co3.Engine.__init__">(co3.Engine method)</a>
<li><a href="_autoref/co3.engines.html#co3.engines.SQLEngine.__init__">(co3.engines.SQLEngine method)</a>
</li>
<li><a href="_autosummary/co3.Indexer.html#co3.Indexer.__init__">(co3.Indexer method)</a>
<li><a href="_autoref/co3.indexer.html#co3.indexer.CacheBlock.__init__">(co3.indexer.CacheBlock method)</a>
</li>
<li><a href="_autosummary/co3.Manager.html#co3.Manager.__init__">(co3.Manager method)</a>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.__init__">(co3.indexer.Indexer method)</a>
</li>
<li><a href="_autosummary/co3.Mapper.html#co3.Mapper.__init__">(co3.Mapper method)</a>
<li><a href="_autoref/co3.managers.fts.html#co3.managers.fts.FTSManager.__init__">(co3.managers.fts.FTSManager method)</a>
</li>
<li><a href="_autosummary/co3.Schema.html#co3.Schema.__init__">(co3.Schema method)</a>
<li><a href="_autoref/co3.managers.sql.html#co3.managers.sql.SQLManager.__init__">(co3.managers.sql.SQLManager method)</a>
</li>
<li><a href="_autoref/co3.managers.vss.html#co3.managers.vss.VSSManager.__init__">(co3.managers.vss.VSSManager method)</a>
</li>
<li><a href="_autoref/co3.mapper.html#co3.mapper.ComposableMapper.__init__">(co3.mapper.ComposableMapper method)</a>
</li>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.__init__">(co3.mapper.Mapper method)</a>
</li>
<li><a href="_autoref/co3.schema.html#co3.schema.Schema.__init__">(co3.schema.Schema method)</a>
</li>
</ul></li>
</ul></td>
@ -275,58 +282,30 @@
<h2>A</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.Accessor.html#co3.Accessor">Accessor (class in co3)</a>, <a href="_autosummary/co3.html#co3.Accessor">[1]</a>
<ul>
<li><a href="_autoref/co3.accessor.html#co3.accessor.Accessor">(class in co3.accessor)</a>
<li><a href="_autoref/co3.accessor.html#co3.accessor.Accessor">Accessor (class in co3.accessor)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.databases.fts.html#co3.databases.fts.FTSDatabase.accessor">accessor (co3.databases.fts.FTSDatabase attribute)</a>
<ul>
<li><a href="_autoref/co3.databases.vss.html#co3.databases.vss.VSSDatabase.accessor">(co3.databases.vss.VSSDatabase attribute)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.CO3.action_registry">action_registry (co3.CO3 attribute)</a>
<ul>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.action_registry">(co3.co3.CO3 attribute)</a>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.action_registry">action_registry (co3.co3.CO3 attribute)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Schema.add_component">add_component() (co3.Schema method)</a>
<ul>
<li><a href="_autoref/co3.schema.html#co3.schema.Schema.add_component">(co3.schema.Schema method)</a>
<li><a href="_autoref/co3.schema.html#co3.schema.Schema.add_component">add_component() (co3.schema.Schema method)</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.html#co3.Collector.add_insert">add_insert() (co3.Collector method)</a>
<ul>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector.add_insert">(co3.collector.Collector method)</a>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector.add_insert">add_insert() (co3.collector.Collector method)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.managers.sql.html#co3.managers.sql.SQLManager.add_router">add_router() (co3.managers.sql.SQLManager method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Mapper.attach">attach() (co3.Mapper method)</a>
<ul>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.attach">(co3.mapper.Mapper method)</a>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.attach">attach() (co3.mapper.Mapper method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Mapper.attach_many">attach_many() (co3.Mapper method)</a>
<ul>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.attach_many">(co3.mapper.Mapper method)</a>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.attach_many">attach_many() (co3.mapper.Mapper method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.CO3.attributes">attributes (co3.CO3 property)</a>
<ul>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.attributes">(co3.co3.CO3 property)</a>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.attributes">attributes (co3.co3.CO3 property)</a>
</li>
</ul></li>
</ul></td>
</tr></table>
</section>
@ -335,41 +314,25 @@
<h2>C</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.html#co3.Indexer.cache_block">cache_block() (co3.Indexer method)</a>
<ul>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.cache_block">(co3.indexer.Indexer method)</a>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.cache_block">cache_block() (co3.indexer.Indexer method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Indexer.cache_clear">cache_clear() (co3.Indexer method)</a>
<ul>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.cache_clear">(co3.indexer.Indexer method)</a>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.cache_clear">cache_clear() (co3.indexer.Indexer method)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.indexer.html#co3.indexer.CacheBlock">CacheBlock (class in co3.indexer)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Indexer.cached_query">cached_query() (co3.Indexer method)</a>
<ul>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.cached_query">(co3.indexer.Indexer method)</a>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.cached_query">cached_query() (co3.indexer.Indexer method)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.util.regex.html#co3.util.regex.camel_to_snake">camel_to_snake() (in module co3.util.regex)</a>
</li>
<li>
co3
<ul>
<li><a href="_autoref/co3.html#module-co3">module</a>, <a href="_autosummary/co3.html#module-co3">[1]</a>
<li><a href="_autoref/co3.html#module-co3">module</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.CO3.html#co3.CO3">CO3 (class in co3)</a>, <a href="_autosummary/co3.html#co3.CO3">[1]</a>
<ul>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3">(class in co3.co3)</a>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3">CO3 (class in co3.co3)</a>
</li>
</ul></li>
<li>
co3.accessor
@ -489,6 +452,8 @@
<li><a href="_autoref/co3.indexer.html#module-co3.indexer">module</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li>
co3.manager
@ -503,8 +468,6 @@
<li><a href="_autoref/co3.managers.html#module-co3.managers">module</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li>
co3.managers.fts
@ -575,77 +538,41 @@
<li><a href="_autoref/co3.util.types.html#module-co3.util.types">module</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.CO3.collate">collate() (co3.CO3 method)</a>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.collate">collate() (co3.co3.CO3 method)</a>
<ul>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.collate">(co3.co3.CO3 method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.collate">(in module co3)</a>
</li>
<li><a href="_autoref/co3.co3.html#co3.co3.collate">(in module co3.co3)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.CO3.collation_attributes">collation_attributes() (co3.CO3 method)</a>
<ul>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.collation_attributes">(co3.co3.CO3 method)</a>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.collation_attributes">collation_attributes() (co3.co3.CO3 method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Mapper.collect">collect() (co3.Mapper method)</a>
<ul>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.collect">(co3.mapper.Mapper method)</a>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.collect">collect() (co3.mapper.Mapper method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Collector.collect_inserts">collect_inserts() (co3.Collector method)</a>
<ul>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector.collect_inserts">(co3.collector.Collector method)</a>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector.collect_inserts">collect_inserts() (co3.collector.Collector method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.Collector.html#co3.Collector">Collector (class in co3)</a>, <a href="_autosummary/co3.html#co3.Collector">[1]</a>
<ul>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector">(class in co3.collector)</a>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector">Collector (class in co3.collector)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.Component.html#co3.Component">Component (class in co3)</a>, <a href="_autosummary/co3.html#co3.Component">[1]</a>
<ul>
<li><a href="_autoref/co3.component.html#co3.component.Component">(class in co3.component)</a>
<li><a href="_autoref/co3.component.html#co3.component.Component">Component (class in co3.component)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.CO3.components">components (co3.CO3 property)</a>
<ul>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.components">(co3.co3.CO3 property)</a>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.components">components (co3.co3.CO3 property)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.components.html#co3.components.ComposableComponent">ComposableComponent (class in co3.components)</a>
</li>
<li><a href="_autosummary/co3.html#co3.ComposableMapper">ComposableMapper (class in co3)</a>
<ul>
<li><a href="_autoref/co3.mapper.html#co3.mapper.ComposableMapper">(class in co3.mapper)</a>
<li><a href="_autoref/co3.mapper.html#co3.mapper.ComposableMapper">ComposableMapper (class in co3.mapper)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.components.html#co3.components.ComposableComponent.compose">compose() (co3.components.ComposableComponent method)</a>
<ul>
<li><a href="_autoref/co3.components.html#co3.components.Relation.compose">(co3.components.Relation method)</a>
</li>
<li><a href="_autoref/co3.components.html#co3.components.SQLTable.compose">(co3.components.SQLTable method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.ComposableMapper.compose">(co3.ComposableMapper method)</a>
</li>
<li><a href="_autoref/co3.mapper.html#co3.mapper.ComposableMapper.compose">(co3.mapper.ComposableMapper method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Engine.connect">connect() (co3.Engine method)</a>
<li><a href="_autoref/co3.engine.html#co3.engine.Engine.connect">connect() (co3.engine.Engine method)</a>
<ul>
<li><a href="_autoref/co3.engine.html#co3.engine.Engine.connect">(co3.engine.Engine method)</a>
</li>
<li><a href="_autoref/co3.engines.html#co3.engines.SQLEngine.connect">(co3.engines.SQLEngine method)</a>
</li>
</ul></li>
@ -661,18 +588,14 @@
<h2>D</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.Database.html#co3.Database">Database (class in co3)</a>, <a href="_autosummary/co3.html#co3.Database">[1]</a>
<ul>
<li><a href="_autoref/co3.database.html#co3.database.Database">(class in co3.database)</a>
<li><a href="_autoref/co3.database.html#co3.database.Database">Database (class in co3.database)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.util.db.html#co3.util.db.deferred_cd_fkey">deferred_cd_fkey() (in module co3.util.db)</a>
</li>
<li><a href="_autoref/co3.util.db.html#co3.util.db.deferred_fkey">deferred_fkey() (in module co3.util.db)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.util.db.html#co3.util.db.deferred_fkey">deferred_fkey() (in module co3.util.db)</a>
</li>
<li><a href="_autoref/co3.components.html#co3.components.Dictionary">Dictionary (class in co3.components)</a>
</li>
<li><a href="_autoref/co3.indexer.html#co3.indexer.CacheBlock.distinct_on">distinct_on() (co3.indexer.CacheBlock method)</a>
@ -691,14 +614,10 @@
</li>
<li><a href="_autoref/co3.accessors.vss.html#co3.accessors.vss.VSSAccessor.embeddings">embeddings (co3.accessors.vss.VSSAccessor property)</a>
</li>
<li><a href="_autosummary/co3.Engine.html#co3.Engine">Engine (class in co3)</a>, <a href="_autosummary/co3.html#co3.Engine">[1]</a>
<ul>
<li><a href="_autoref/co3.engine.html#co3.engine.Engine">(class in co3.engine)</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.engine.html#co3.engine.Engine">Engine (class in co3.engine)</a>
</li>
<li><a href="_autoref/co3.engines.html#co3.engines.SQLEngine.exec_explicit">exec_explicit() (co3.engines.SQLEngine static method)</a>
</li>
<li><a href="_autoref/co3.engines.html#co3.engines.SQLEngine.execute">execute() (co3.engines.SQLEngine static method)</a>
@ -735,56 +654,36 @@
<h2>G</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.html#co3.Mapper.get_attr_comp">get_attr_comp() (co3.Mapper method)</a>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.get_attr_comp">get_attr_comp() (co3.mapper.Mapper method)</a>
</li>
<li><a href="_autoref/co3.component.html#co3.component.Component.get_attributes">get_attributes() (co3.component.Component method)</a>
<ul>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.get_attr_comp">(co3.mapper.Mapper method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Component.get_attributes">get_attributes() (co3.Component method)</a>
<ul>
<li><a href="_autoref/co3.component.html#co3.component.Component.get_attributes">(co3.component.Component method)</a>
</li>
<li><a href="_autoref/co3.components.html#co3.components.Dictionary.get_attributes">(co3.components.Dictionary method)</a>
</li>
<li><a href="_autoref/co3.components.html#co3.components.SQLTable.get_attributes">(co3.components.SQLTable method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Mapper.get_coll_comp">get_coll_comp() (co3.Mapper method)</a>
<ul>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.get_coll_comp">(co3.mapper.Mapper method)</a>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper.get_coll_comp">get_coll_comp() (co3.mapper.Mapper method)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.components.html#co3.components.SQLTable.get_column_defaults">get_column_defaults() (co3.components.SQLTable method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.util.db.html#co3.util.db.get_column_names_str_table">get_column_names_str_table() (in module co3.util.db)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Schema.get_component">get_component() (co3.Schema method)</a>
<ul>
<li><a href="_autoref/co3.schema.html#co3.schema.Schema.get_component">(co3.schema.Schema method)</a>
<li><a href="_autoref/co3.schema.html#co3.schema.Schema.get_component">get_component() (co3.schema.Schema method)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.util.db.html#co3.util.db.get_engine">get_engine() (in module co3.util.db)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Indexer.group_by">group_by() (co3.Indexer class method)</a>
<li><a href="_autoref/co3.indexer.html#co3.indexer.CacheBlock.group_by">group_by() (co3.indexer.CacheBlock method)</a>
<ul>
<li><a href="_autoref/co3.indexer.html#co3.indexer.CacheBlock.group_by">(co3.indexer.CacheBlock method)</a>
</li>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer.group_by">(co3.indexer.Indexer class method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.CO3.group_registry">group_registry (co3.CO3 attribute)</a>
<ul>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.group_registry">(co3.co3.CO3 attribute)</a>
<li><a href="_autoref/co3.co3.html#co3.co3.CO3.group_registry">group_registry (co3.co3.CO3 attribute)</a>
</li>
</ul></li>
</ul></td>
</tr></table>
</section>
@ -793,25 +692,13 @@
<h2>I</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.html#co3.Database.index">index (co3.Database property)</a>
<li><a href="_autoref/co3.database.html#co3.database.Database.index">index (co3.database.Database property)</a>
</li>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer">Indexer (class in co3.indexer)</a>
</li>
<li><a href="_autoref/co3.database.html#co3.database.Database.insert">insert() (co3.database.Database method)</a>
<ul>
<li><a href="_autoref/co3.database.html#co3.database.Database.index">(co3.database.Database property)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.Indexer.html#co3.Indexer">Indexer (class in co3)</a>, <a href="_autosummary/co3.html#co3.Indexer">[1]</a>
<ul>
<li><a href="_autoref/co3.indexer.html#co3.indexer.Indexer">(class in co3.indexer)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Database.insert">insert() (co3.Database method)</a>
<ul>
<li><a href="_autoref/co3.database.html#co3.database.Database.insert">(co3.database.Database method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Manager.insert">(co3.Manager method)</a>
</li>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager.insert">(co3.manager.Manager method)</a>
</li>
<li><a href="_autoref/co3.managers.sql.html#co3.managers.sql.SQLManager.insert">(co3.managers.sql.SQLManager method)</a>
@ -821,12 +708,8 @@
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.managers.sql.html#co3.managers.sql.SQLManager.insert_many">insert_many() (co3.managers.sql.SQLManager method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Collector.inserts">inserts (co3.Collector property)</a>
<ul>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector.inserts">(co3.collector.Collector property)</a>
<li><a href="_autoref/co3.collector.html#co3.collector.Collector.inserts">inserts (co3.collector.Collector property)</a>
</li>
</ul></li>
</ul></td>
</tr></table>
</section>
@ -845,39 +728,23 @@
<h2>M</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.html#co3.Database.manage">manage (co3.Database property)</a>
<ul>
<li><a href="_autoref/co3.database.html#co3.database.Database.manage">(co3.database.Database property)</a>
<li><a href="_autoref/co3.database.html#co3.database.Database.manage">manage (co3.database.Database property)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.Manager.html#co3.Manager">Manager (class in co3)</a>, <a href="_autosummary/co3.html#co3.Manager">[1]</a>
<ul>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager">(class in co3.manager)</a>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager">Manager (class in co3.manager)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.databases.fts.html#co3.databases.fts.FTSDatabase.manager">manager (co3.databases.fts.FTSDatabase attribute)</a>
<ul>
<li><a href="_autoref/co3.databases.vss.html#co3.databases.vss.VSSDatabase.manager">(co3.databases.vss.VSSDatabase attribute)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Engine.manager">(co3.Engine property)</a>
</li>
<li><a href="_autoref/co3.engine.html#co3.engine.Engine.manager">(co3.engine.Engine property)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.Mapper.html#co3.Mapper">Mapper (class in co3)</a>, <a href="_autosummary/co3.html#co3.Mapper">[1]</a>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper">Mapper (class in co3.mapper)</a>
</li>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager.migrate">migrate() (co3.manager.Manager method)</a>
<ul>
<li><a href="_autoref/co3.mapper.html#co3.mapper.Mapper">(class in co3.mapper)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Manager.migrate">migrate() (co3.Manager method)</a>
<ul>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager.migrate">(co3.manager.Manager method)</a>
</li>
<li><a href="_autoref/co3.managers.fts.html#co3.managers.fts.FTSManager.migrate">(co3.managers.fts.FTSManager method)</a>
</li>
<li><a href="_autoref/co3.managers.sql.html#co3.managers.sql.SQLManager.migrate">(co3.managers.sql.SQLManager method)</a>
@ -891,7 +758,7 @@
module
<ul>
<li><a href="_autoref/co3.html#module-co3">co3</a>, <a href="_autosummary/co3.html#module-co3">[1]</a>
<li><a href="_autoref/co3.html#module-co3">co3</a>
</li>
<li><a href="_autoref/co3.accessor.html#module-co3.accessor">co3.accessor</a>
</li>
@ -986,14 +853,10 @@
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.util.db.html#co3.util.db.populate_fts5">populate_fts5() (in module co3.util.db)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Database.populate_indexes">populate_indexes() (co3.Database method)</a>
<ul>
<li><a href="_autoref/co3.database.html#co3.database.Database.populate_indexes">(co3.database.Database method)</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.database.html#co3.database.Database.populate_indexes">populate_indexes() (co3.database.Database method)</a>
</li>
<li><a href="_autoref/co3.components.html#co3.components.SQLTable.prepare_insert_data">prepare_insert_data() (co3.components.SQLTable method)</a>
</li>
</ul></td>
@ -1004,11 +867,9 @@
<h2>R</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.html#co3.Accessor.raw_select">raw_select() (co3.Accessor method)</a>
<li><a href="_autoref/co3.accessor.html#co3.accessor.Accessor.raw_select">raw_select() (co3.accessor.Accessor method)</a>
<ul>
<li><a href="_autoref/co3.accessor.html#co3.accessor.Accessor.raw_select">(co3.accessor.Accessor method)</a>
</li>
<li><a href="_autoref/co3.accessors.sql.html#co3.accessors.sql.RelationalAccessor.raw_select">(co3.accessors.sql.RelationalAccessor method)</a>
</li>
<li><a href="_autoref/co3.accessors.sql.html#co3.accessors.sql.SQLAccessor.raw_select">(co3.accessors.sql.SQLAccessor method)</a>
@ -1016,13 +877,9 @@
</ul></li>
<li><a href="_autoref/co3.accessors.vss.html#co3.accessors.vss.VSSAccessor.read_embeddings">read_embeddings() (co3.accessors.vss.VSSAccessor method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Database.recreate">recreate() (co3.Database method)</a>
<li><a href="_autoref/co3.database.html#co3.database.Database.recreate">recreate() (co3.database.Database method)</a>
<ul>
<li><a href="_autoref/co3.database.html#co3.database.Database.recreate">(co3.database.Database method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Manager.recreate">(co3.Manager method)</a>
</li>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager.recreate">(co3.manager.Manager method)</a>
</li>
<li><a href="_autoref/co3.managers.fts.html#co3.managers.fts.FTSManager.recreate">(co3.managers.fts.FTSManager method)</a>
@ -1062,38 +919,30 @@
<h2>S</h2>
<table style="width: 100%" class="indextable genindextable"><tr>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autosummary/co3.Schema.html#co3.Schema">Schema (class in co3)</a>, <a href="_autosummary/co3.html#co3.Schema">[1]</a>
<ul>
<li><a href="_autoref/co3.schema.html#co3.schema.Schema">(class in co3.schema)</a>
<li><a href="_autoref/co3.schema.html#co3.schema.Schema">Schema (class in co3.schema)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.accessors.fts.html#co3.accessors.fts.FTSAccessor.search">search() (co3.accessors.fts.FTSAccessor method)</a>
<ul>
<li><a href="_autoref/co3.accessors.vss.html#co3.accessors.vss.VSSAccessor.search">(co3.accessors.vss.VSSAccessor method)</a>
</li>
</ul></li>
<li><a href="_autosummary/co3.html#co3.Accessor.select">select() (co3.Accessor method)</a>
<li><a href="_autoref/co3.accessor.html#co3.accessor.Accessor.select">select() (co3.accessor.Accessor method)</a>
<ul>
<li><a href="_autoref/co3.accessor.html#co3.accessor.Accessor.select">(co3.accessor.Accessor method)</a>
</li>
<li><a href="_autoref/co3.accessors.sql.html#co3.accessors.sql.RelationalAccessor.select">(co3.accessors.sql.RelationalAccessor method)</a>
</li>
<li><a href="_autoref/co3.accessors.sql.html#co3.accessors.sql.SQLAccessor.select">(co3.accessors.sql.SQLAccessor method)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Database.select">(co3.Database method)</a>
</li>
<li><a href="_autoref/co3.database.html#co3.database.Database.select">(co3.database.Database method)</a>
</li>
</ul></li>
<li><a href="_autoref/co3.accessors.sql.html#co3.accessors.sql.RelationalAccessor.select_one">select_one() (co3.accessors.sql.RelationalAccessor method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.accessors.sql.html#co3.accessors.sql.SQLAccessor">SQLAccessor (class in co3.accessors.sql)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="_autoref/co3.databases.sql.html#co3.databases.sql.SQLDatabase">SQLDatabase (class in co3.databases.sql)</a>
</li>
<li><a href="_autoref/co3.engines.html#co3.engines.SQLEngine">SQLEngine (class in co3.engines)</a>
@ -1106,11 +955,9 @@
</li>
<li><a href="_autoref/co3.components.html#co3.components.SQLTable">SQLTable (class in co3.components)</a>
</li>
<li><a href="_autosummary/co3.html#co3.Manager.sync">sync() (co3.Manager method)</a>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager.sync">sync() (co3.manager.Manager method)</a>
<ul>
<li><a href="_autoref/co3.manager.html#co3.manager.Manager.sync">(co3.manager.Manager method)</a>
</li>
<li><a href="_autoref/co3.managers.fts.html#co3.managers.fts.FTSManager.sync">(co3.managers.fts.FTSManager method)</a>
</li>
<li><a href="_autoref/co3.managers.sql.html#co3.managers.sql.SQLManager.sync">(co3.managers.sql.SQLManager method)</a>

View File

@ -200,7 +200,6 @@
</ul>
<p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="reference/test.html">Test</a></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="reference/documentation/index.html">Documentation</a><input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle navigation of Documentation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="reference/documentation/sphinx.html">Sphinx</a></li>
</ul>
@ -247,34 +246,34 @@
<div class="table-wrapper autosummary longtable docutils container">
<table class="autosummary longtable docutils align-default">
<tbody>
<tr class="row-odd"><td><p><a class="reference internal" href="_autosummary/co3.Accessor.html#co3.Accessor" title="co3.Accessor"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Accessor</span></code></a></p></td>
<tr class="row-odd"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Accessor</span></code></p></td>
<td><p>Access wrapper class for complex queries and easy integration with Composer tables.</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="_autosummary/co3.Collector.html#co3.Collector" title="co3.Collector"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Collector</span></code></a></p></td>
<tr class="row-even"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Collector</span></code></p></td>
<td><p></p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="_autosummary/co3.CO3.html#co3.CO3" title="co3.CO3"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.CO3</span></code></a></p></td>
<td><p>CO3: COllate, COllect, COmpose - conversion &amp; DB insertion base</p></td>
<tr class="row-odd"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.CO3</span></code></p></td>
<td><p>Conversion &amp; DB insertion base class</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="_autosummary/co3.Database.html#co3.Database" title="co3.Database"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Database</span></code></a></p></td>
<tr class="row-even"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Database</span></code></p></td>
<td><p>Generic Database definition</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="_autosummary/co3.Indexer.html#co3.Indexer" title="co3.Indexer"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Indexer</span></code></a></p></td>
<tr class="row-odd"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Indexer</span></code></p></td>
<td><p>Indexer class</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="_autosummary/co3.Manager.html#co3.Manager" title="co3.Manager"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Manager</span></code></a></p></td>
<tr class="row-even"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Manager</span></code></p></td>
<td><p>Management wrapper class for table groupings.</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="_autosummary/co3.Mapper.html#co3.Mapper" title="co3.Mapper"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Mapper</span></code></a></p></td>
<tr class="row-odd"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Mapper</span></code></p></td>
<td><p>Mapper base class for housing schema components and managing relationships between CO3 types and storage components (of type C).</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="_autosummary/co3.Component.html#co3.Component" title="co3.Component"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Component</span></code></a></p></td>
<tr class="row-even"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Component</span></code></p></td>
<td><p></p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="_autosummary/co3.Schema.html#co3.Schema" title="co3.Schema"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Schema</span></code></a></p></td>
<tr class="row-odd"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Schema</span></code></p></td>
<td><p></p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="_autosummary/co3.Engine.html#co3.Engine" title="co3.Engine"><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Engine</span></code></a></p></td>
<tr class="row-even"><td><p><code class="xref py py-obj docutils literal notranslate"><span class="pre">co3.Engine</span></code></p></td>
<td><p>Engine base class.</p></td>
</tr>
</tbody>
@ -315,7 +314,6 @@
<div class="toctree-wrapper compound">
<p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="reference/test.html">Test</a></li>
<li class="toctree-l1"><a class="reference internal" href="reference/documentation/index.html">Documentation</a></li>
</ul>
</div>

Binary file not shown.

View File

@ -3,7 +3,7 @@
<head><meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="color-scheme" content="light dark"><meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" /><link rel="next" title="Sphinx" href="sphinx.html" /><link rel="prev" title="Test" href="../test.html" />
<link rel="index" title="Index" href="../../genindex.html" /><link rel="search" title="Search" href="../../search.html" /><link rel="next" title="Sphinx" href="sphinx.html" /><link rel="prev" title="co3.schema module" href="../../_autoref/co3.schema.html" />
<!-- Generated with Sphinx 7.3.7 and Furo 2024.01.29 -->
<title>Documentation - co3 documentation</title>
@ -200,7 +200,6 @@
</ul>
<p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../test.html">Test</a></li>
<li class="toctree-l1 current has-children current-page"><a class="current reference internal" href="#">Documentation</a><input checked="" class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle navigation of Documentation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="sphinx.html">Sphinx</a></li>
</ul>
@ -259,14 +258,14 @@
</div>
<svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
</a>
<a class="prev-page" href="../test.html">
<a class="prev-page" href="../../_autoref/co3.schema.html">
<svg class="furo-related-icon"><use href="#svg-arrow-right"></use></svg>
<div class="page-info">
<div class="context">
<span>Previous</span>
</div>
<div class="title">Test</div>
<div class="title">co3.schema module</div>
</div>
</a>

View File

@ -200,7 +200,6 @@
</ul>
<p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../test.html">Test</a></li>
<li class="toctree-l1 current has-children"><a class="reference internal" href="index.html">Documentation</a><input checked="" class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle navigation of Documentation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul class="current">
<li class="toctree-l2 current current-page"><a class="current reference internal" href="#">Sphinx</a></li>
</ul>

View File

@ -197,7 +197,6 @@
</ul>
<p class="caption" role="heading"><span class="caption-text">Contents</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="reference/test.html">Test</a></li>
<li class="toctree-l1 has-children"><a class="reference internal" href="reference/documentation/index.html">Documentation</a><input class="toctree-checkbox" id="toctree-checkbox-6" name="toctree-checkbox-6" role="switch" type="checkbox"/><label for="toctree-checkbox-6"><div class="visually-hidden">Toggle navigation of Documentation</div><i class="icon"><svg><use href="#svg-arrow-right"></use></svg></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="reference/documentation/sphinx.html">Sphinx</a></li>
</ul>

File diff suppressed because one or more lines are too long

View File

@ -15,13 +15,22 @@ author = 'Sam Griesemer'
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.viewcode",
"myst_parser",
"sphinx.ext.autosummary", # enables a directive to be specified manually that gathers
# module/object summary details in a table
"sphinx.ext.viewcode", # allow viewing source in the HTML pages
"myst_parser", # only really applies to manual docs; docstrings still need RST-like
"sphinx.ext.napoleon", # enables Google-style docstring formats
"sphinx_autodoc_typehints", # external extension that allows arg types to be inferred by type hints
]
autosummary_generate = True
autosummary_imported_members = True
# include __init__ definitions in autodoc
autodoc_default_options = {
'special-members': '__init__',
}
#smartquotes = True
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

View File

@ -1,8 +0,0 @@
# Documentation
```{toctree}
:hidden:
sphinx
```

View File

@ -1,111 +0,0 @@
# Sphinx
The primary driver of this package's documentation is Sphinx's `autodoc` extension,
using the [Furo theme][1].
**High-level details**:
- `sphinx-apidoc` generates package-based documentation to the `_autoref/` directory,
with navigation available under "Autoref" in the sidebar.
- Markdown-based documentation files are manually written under the `reference/`
directory, showing up under "Contents" in the sidebar.
## Detailed directory structure
All files are placed under `docs/sphinx`:
- `_`-prefixed are Sphinx-managed directories
* `_build/html/` houses output HTML files
* `_autoref/` is the target for module-based RST files written by `autodoc`
- `reference/`: houses all manually written documentation (totally separate from
auto-generated package docs)
- `conf.py`: single Sphinx configuration file
- `index.md`: documentation index, setups up a persistent sidebar across all other pages
For manually written documentation under `reference/`, topics are nested as needed. Within
a nested directory `reference/<topic>`, an `index.md` should created with content like:
```
# <Topic>
\`\`\`{toctree}
:hidden:
sub-topic-1.rst
sub-topic-2.rst
...
\`\`\`
```
This will add the nested directory to the sidebar navigation, using the name set under the
top-level header. See [Markdown syntax][#markdown-syntax] for more details on the syntax.
## Sphinx autodoc
Sphinx's `autodoc` extension allows automatic generation of documents according to
(Python) subpackage structure and available docstrings. A few notes here:
- In the `conf.py` file, autodoc is enabled by adding `"sphinx.ext.autodoc"` to
the extensions list. `"sphinx.ext.viewcode"` can also be added to provide
links to source code.
- Documents are actually generated by calling the `sphinx-apidoc` CLI command. The
current Makefile uses the following call:
```sh
sphinx-apidoc --module-first -o docs/sphinx/_autoref/ localsys
```
This writes the automatically generated docs for modules in the package at the
local directory `localsys/` to the `docs/sphinx/_autoref` directory. These are
reStructuredText files by default.
* `--module-first` places the module-level descriptions at the top of the module page.
By default, this is placed at the bottom (oddly), and can be obscured by large lists
of subpackages if this flag isn't provided.
* See available `sphinx-apidoc` options [here][2], as well as more advanced config
[here][3].
## Markdown syntax
The `myst_parser` extension enables Markdown (or something close to it) to be used when
writing documentation files. The Sphinx directives can be difficult to track, and
they change slightly under the MyST Markdown syntax. The following are a few common
blocks:
**Page hierarchies**: the following will generate link hierarchy according to the provided
pages:
```
\`\`\`{toctree}
:maxdepth: <n>
:caption: <caption>
:hidden:
example-file-1
example-file-2
example-dir/index
...
\`\`\`
```
- `:maxdepth:` limits the depth of nesting
- `:caption:` title for the group of pages
- `:hidden:` if provided, links will only show in the sidebar (hidden on the page)
- Constituent files: listed files will be rendered as a link directly. If a listed file
has a `{toctree}` directive, this tree will be rendered in place of the page's link as a
dropdown. The dropdown will be named according to the file's top-level heading, and
clicking directly on the dropdown header will show that page's content. Files found in
the tree will be placed as links under the dropdown, recursively subject to same rules
described here.
**Include files**: the following will include file content
pages:
```
\`\`\`{include} README.md
\`\`\`
```
**Reference directives**
[1]: https://pradyunsg.me/furo/
[2]: https://www.sphinx-doc.org/en/master/man/sphinx-apidoc.html
[3]: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#

View File

@ -3,6 +3,7 @@ sphinx
sphinx-togglebutton
furo
myst-parser
sphinx-autodoc-typehints
sqlalchemy
numpy