Compare commits
	
		
			2 Commits
		
	
	
		
			c2e09b2c10
			...
			b726f495b6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b726f495b6 | |||
| d449b18725 | 
| @ -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,6 +2,7 @@ from typing import Protocol | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Resource: | class Resource: | ||||||
|  |     def content(self) -> BinaryIO: | ||||||
|         pass |         pass | ||||||
| 
 | 
 | ||||||
| class SelectableResource(Protocol): | class SelectableResource(Protocol): | ||||||
|  | |||||||
| @ -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 | ||||||
|  | 
 | ||||||
| @ -2,6 +2,9 @@ | |||||||
| requires = ["setuptools", "wheel", "setuptools-git-versioning>=2.0,<3"] | requires = ["setuptools", "wheel", "setuptools-git-versioning>=2.0,<3"] | ||||||
| build-backend = "setuptools.build_meta" | build-backend = "setuptools.build_meta" | ||||||
| 
 | 
 | ||||||
|  | [tool.setuptools-git-versioning] | ||||||
|  | enabled = true | ||||||
|  | 
 | ||||||
| [project] | [project] | ||||||
| name = "co3" | name = "co3" | ||||||
| description = "Lightweight Python ORM for hierarchical storage management" | description = "Lightweight Python ORM for hierarchical storage management" | ||||||
| @ -37,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" | ||||||
|  | |||||||
| @ -1,12 +0,0 @@ | |||||||
| # -- sphinx docs -- |  | ||||||
| sphinx |  | ||||||
| sphinx-togglebutton |  | ||||||
| furo |  | ||||||
| myst-parser |  | ||||||
| sphinx-autodoc-typehints |  | ||||||
| 
 |  | ||||||
| sqlalchemy |  | ||||||
| numpy |  | ||||||
| wcmatch |  | ||||||
| 
 |  | ||||||
| pytest |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user