begin medium/resource refactor (intermediate state)
This commit is contained in:
parent
d449b18725
commit
b726f495b6
@ -5,8 +5,8 @@ etc. Objects inheriting from the `CO3` base class can then define data transform
|
|||||||
that connect to database components, and can be automatically collected for coordinated
|
that connect to database components, and can be automatically collected for coordinated
|
||||||
database insertion.
|
database insertion.
|
||||||
|
|
||||||
`co3` attempts to provide a general interface for interacting with a storage media (e.g.,
|
`co3` attempts to provide a general interface for interacting with storage media (e.g.,
|
||||||
database, pickled objects, VSS framework, in-memory key-value stores, etc). The following
|
databases, pickled objects, VSS framework, in-memory key-value stores, etc). The following
|
||||||
top-level classes capture the bulk of the operational model:
|
top-level classes capture the bulk of the operational model:
|
||||||
|
|
||||||
- **Database**: reference to a storage medium, with an `Accessor` for accessing data,
|
- **Database**: reference to a storage medium, with an `Accessor` for accessing data,
|
||||||
|
@ -13,7 +13,7 @@ class Engine:
|
|||||||
derivative Engines, like SQLEngine, mostly just wrap another engine-like object, this
|
derivative Engines, like SQLEngine, mostly just wrap another engine-like object, this
|
||||||
is not the rule. That is, inheriting Engine subtypes shouldn't necessarily expect to
|
is not the rule. That is, inheriting Engine subtypes shouldn't necessarily expect to
|
||||||
rely on another object per se, and if such an object is required, _this_ is the class
|
rely on another object per se, and if such an object is required, _this_ is the class
|
||||||
is meant to be skeleton to supports its creation (and not merely a wrapper for some
|
meant to be the skeleton that supports its creation (and not merely a wrapper for some
|
||||||
other type, although it may appear that way when such a type is in fact readily
|
other type, although it may appear that way when such a type is in fact readily
|
||||||
available).
|
available).
|
||||||
|
|
@ -1,12 +1,11 @@
|
|||||||
'''
|
|
||||||
Component
|
|
||||||
|
|
||||||
General wrapper for storage components to be used in various database contexts. Relations
|
|
||||||
can be thought of generally as named data containers/entities serving as a fundamental
|
|
||||||
abstractions within particular storage protocols.
|
|
||||||
'''
|
|
||||||
|
|
||||||
class Component[T]:
|
class Component[T]:
|
||||||
|
'''
|
||||||
|
Component
|
||||||
|
|
||||||
|
General wrapper for storage components to be used in various database contexts. Relations
|
||||||
|
can be thought of generally as named data containers/entities serving as a fundamental
|
||||||
|
abstractions within particular storage protocols.
|
||||||
|
'''
|
||||||
def __init__(self, name, obj: T):
|
def __init__(self, name, obj: T):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
@ -19,4 +18,3 @@ class Component[T]:
|
|||||||
|
|
||||||
def get_attributes(self):
|
def get_attributes(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
24
co3/domain.py
Normal file
24
co3/domain.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
from co3 import Resource
|
||||||
|
|
||||||
|
|
||||||
|
class Domain[R: Resource]:
|
||||||
|
'''
|
||||||
|
General Domain class
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
def __init__(self, content):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_resource(self, url: URL) -> Resource:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def connect(self, timeout=None):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
class SelectableDomain(Domain):
|
||||||
|
def select(self, component, *args, **kwargs):
|
||||||
|
raise NotImplementedError
|
@ -1,10 +1,12 @@
|
|||||||
|
#from co3.resources.disk import DiskResource
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from co3.util import paths
|
from co3.util import paths
|
||||||
from co3.resource import SelectableResource
|
from co3.resource import SelectableDomain
|
||||||
|
|
||||||
|
|
||||||
class DiskResource(SelectableResource):
|
class DiskDomain(SelectableDomain):
|
||||||
def select(
|
def select(
|
||||||
self,
|
self,
|
||||||
path_list: str | Path | list[str | Path],
|
path_list: str | Path | list[str | Path],
|
0
co3/domains/disk.py
Normal file
0
co3/domains/disk.py
Normal file
@ -75,7 +75,7 @@ class SQLManager(RelationalManager[SQLTable]):
|
|||||||
'''
|
'''
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
'''
|
'''
|
||||||
The insert lock is a *reentrant lock*, meaning the same thread can acquire the
|
The insert lock is a *re-entrant lock*, meaning the same thread can acquire the
|
||||||
lock again without deadlocking (simplifying across methods of this class that
|
lock again without deadlocking (simplifying across methods of this class that
|
||||||
need it).
|
need it).
|
||||||
'''
|
'''
|
||||||
@ -112,11 +112,13 @@ class SQLManager(RelationalManager[SQLTable]):
|
|||||||
def insert(
|
def insert(
|
||||||
self,
|
self,
|
||||||
connection,
|
connection,
|
||||||
component,
|
component: SQLTable,
|
||||||
inserts: list[dict],
|
inserts: list[dict],
|
||||||
commit=True
|
commit=True
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
|
Insert a group of
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
'''
|
'''
|
||||||
with self._insert_lock:
|
with self._insert_lock:
|
||||||
@ -135,6 +137,13 @@ class SQLManager(RelationalManager[SQLTable]):
|
|||||||
Perform provided table inserts, aligning the insert format of
|
Perform provided table inserts, aligning the insert format of
|
||||||
``Collector.collect_inserts()``.
|
``Collector.collect_inserts()``.
|
||||||
|
|
||||||
|
Note that the regular ``insert`` actually supports the usual notion of a "bulk
|
||||||
|
insert," inserting many entries under a single table. This method simply supports
|
||||||
|
the same but across multiple tables. It does so by just making calls to
|
||||||
|
``insert()`` after grouping entries for each component in the provided ``inserts``
|
||||||
|
dict, only committing the transaction after all components inserts have been
|
||||||
|
staged.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
inserts: component-indexed dictionary of insert lists
|
inserts: component-indexed dictionary of insert lists
|
||||||
'''
|
'''
|
||||||
|
58
co3/medium.py
Normal file
58
co3/medium.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import logging
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class Medium[R: Resource]:
|
||||||
|
'''
|
||||||
|
Medium base class.
|
||||||
|
|
||||||
|
A Resource space
|
||||||
|
'''
|
||||||
|
def __init__(self, scope):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def connect(self, timeout=None):
|
||||||
|
'''
|
||||||
|
Open a connection to the database specified by the resource. Exactly what the
|
||||||
|
returned connection looks like remains relatively unconstrained given the wide
|
||||||
|
variety of possible database interactions. This function should be invoked in
|
||||||
|
with-statement contexts, constituting an "interaction session" with the database
|
||||||
|
(i.e., allowing several actions to be performed using the same connection).
|
||||||
|
'''
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def execute(self, query: Query[QL]):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BrowsableMedium[R: Resource](Medium[R]):
|
||||||
|
def browse(self, uri: URI[R]):
|
||||||
|
'''
|
||||||
|
Analog for Read (CRUD), SELECT (SQL), GET (REST)
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ABCDMedium[R: Resource](BrowsableMedium[R]):
|
||||||
|
def append(self, uri: URI[R], resource: R):
|
||||||
|
'''
|
||||||
|
Analog for Create (CRUD), INSERT (SQL), POST/PUT (REST)
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def change(self, uri: URI[R], resource: R):
|
||||||
|
'''
|
||||||
|
Analog for Update (CRUD), UPDATE (SQL), PUT/PATCH (REST)
|
||||||
|
|
||||||
|
Can a URI be another object? Component for ex; could inherit from URI I guess
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
def delete(self, uri: URI[R]):
|
||||||
|
'''
|
||||||
|
Analog for Delete (CRUD), DELETE (SQL), DELETE (REST)
|
||||||
|
'''
|
||||||
|
pass
|
@ -2,7 +2,8 @@ from typing import Protocol
|
|||||||
|
|
||||||
|
|
||||||
class Resource:
|
class Resource:
|
||||||
pass
|
def content(self) -> BinaryIO:
|
||||||
|
pass
|
||||||
|
|
||||||
class SelectableResource(Protocol):
|
class SelectableResource(Protocol):
|
||||||
def select(self, component, *args, **kwargs):
|
def select(self, component, *args, **kwargs):
|
||||||
|
@ -1 +0,0 @@
|
|||||||
from co3.resources.disk import DiskResource
|
|
15
co3/uri.py
Normal file
15
co3/uri.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from urllib import parse
|
||||||
|
|
||||||
|
|
||||||
|
class URI:
|
||||||
|
def __init__(self, url_str: str):
|
||||||
|
self.url_str = url_str
|
||||||
|
|
||||||
|
class URL(URI):
|
||||||
|
def __init__(self, url_str: str):
|
||||||
|
self.url_str = url_str
|
||||||
|
|
||||||
|
class URN(URI):
|
||||||
|
def __init__(self, url_str: str):
|
||||||
|
self.url_str = url_str
|
||||||
|
|
@ -40,6 +40,7 @@ docs = [
|
|||||||
"furo",
|
"furo",
|
||||||
"myst-parser",
|
"myst-parser",
|
||||||
]
|
]
|
||||||
|
jupyter = ["ipykernel"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://doc.olog.io/co3"
|
Homepage = "https://doc.olog.io/co3"
|
||||||
|
Loading…
Reference in New Issue
Block a user