Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,6 @@ dmypy.json
# AUTO DOCS
docs/src/api/*.md
docs/src/.vuepress/apiPages.js

# Claude Code session files
.claude/
5 changes: 4 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = mayim
version = 1.1.0
version = 1.2.0
description = The NOT ORM hydrator
long_description = file: README.md
long_description_content_type = text/markdown
Expand All @@ -13,6 +13,9 @@ classifiers =
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Programming Language :: Python :: 3.13

[options]
zip_safe = False
Expand Down
3 changes: 1 addition & 2 deletions src/mayim/base/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,7 @@ def get_hydrator(self, name: Optional[str] = None) -> Hydrator:
return self._hydrators.get(name, self.hydrator)

@classmethod
def _load(cls, strict: bool) -> None:
...
def _load(cls, strict: bool) -> None: ...

@staticmethod
def is_query_name(obj) -> bool:
Expand Down
46 changes: 36 additions & 10 deletions src/mayim/base/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,16 @@ def __init_subclass__(cls) -> None:
BaseInterface.registered_interfaces.add(cls)

@abstractmethod
def _setup_pool(self):
...
def _setup_pool(self): ...

@abstractmethod
async def open(self):
...
async def open(self): ...

@abstractmethod
async def close(self):
...
async def close(self): ...

@abstractmethod
def connection(self, timeout: Optional[float] = None):
...
def connection(self, timeout: Optional[float] = None): ...

def __init__(
self,
Expand All @@ -54,6 +50,8 @@ def __init__(
password: Optional[str] = None,
db: Optional[int] = None,
query: Optional[str] = None,
min_size: int = 1,
max_size: Optional[int] = None,
) -> None:
"""DB class initialization.

Expand All @@ -64,6 +62,8 @@ def __init__(
password (str, optional): DB password
db (int, optional): DB db. Defaults to 1
query (str, optional): DB query parameters. Defaults to None
min_size (int, optional): Minimum number of connections in pool. Defaults to 1
max_size (int, optional): Maximum number of connections in pool. Defaults to None
"""

if dsn and host:
Expand Down Expand Up @@ -96,6 +96,8 @@ def __init__(
self._password = password
self._db = db
self._query = query
self._min_size = min_size
self._max_size = max_size
self._full_dsn: Optional[str] = None
self._connection: ContextVar[Any] = ContextVar(
"connection", default=None
Expand All @@ -117,10 +119,26 @@ def _populate_connection_args(self):
dsn = self.dsn or ""
if dsn:
parts = urlparse(dsn)
# Default values for common database ports
defaults = {
"port": (
5432
if "postgres" in dsn
else 3306 if "mysql" in dsn else None
),
"hostname": "localhost",
"username": None,
"password": None,
"path": "/",
"query": "",
}
for key, mapping in URLPARSE_MAPPING.items():
if not getattr(self, mapping.key):
value = getattr(parts, key, None) # or TODO: make defaults
setattr(self, mapping.key, mapping.cast(value))
value = getattr(parts, key, None)
if value is None:
value = defaults.get(key)
if value is not None:
setattr(self, mapping.key, mapping.cast(value))

def _populate_dsn(self):
self._dsn = (
Expand Down Expand Up @@ -172,6 +190,14 @@ def db(self):
def full_dsn(self):
return self._full_dsn

@property
def min_size(self):
return self._min_size

@property
def max_size(self):
return self._max_size

def existing_connection(self):
return self._connection.get()

Expand Down
9 changes: 3 additions & 6 deletions src/mayim/exception.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
class MayimError(Exception):
...
class MayimError(Exception): ...


class RecordNotFound(MayimError):
...
class RecordNotFound(MayimError): ...


class MissingSQL(MayimError):
...
class MissingSQL(MayimError): ...
3 changes: 1 addition & 2 deletions src/mayim/extension/quart_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
Quart = type("Quart", (), {}) # type: ignore


class Default:
...
class Default: ...


_default = Default()
Expand Down
3 changes: 1 addition & 2 deletions src/mayim/extension/starlette_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
Starlette = type("Starlette", (), {}) # type: ignore


class Default:
...
class Default: ...


_default = Default()
Expand Down
37 changes: 24 additions & 13 deletions src/mayim/lazy/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,50 @@
class LazyPool(BaseInterface):
_singleton = None
_derivative: Optional[Type[BaseInterface]]
_derived_instance: Optional[BaseInterface]

def __new__(cls, *args, **kwargs):
if cls._singleton is None:
cls._singleton = super().__new__(cls)
cls._singleton._derivative = None
cls._singleton._derived_instance = None
cls._singleton._derivative_dsn = ""
cls._singleton._min_size = 1
cls._singleton._max_size = None
return cls._singleton

def _setup_pool(self):
...
def _setup_pool(self): ...

def _populate_dsn(self):
...
def _populate_dsn(self): ...

def _populate_connection_args(self):
...
def _populate_connection_args(self): ...

async def open(self):
...
async def open(self): ...

async def close(self):
...
async def close(self): ...

def connection(self, timeout: Optional[float] = None):
...
def connection(self, timeout: Optional[float] = None): ...

def set_derivative(self, interface_class: Type[BaseInterface]) -> None:
self._derivative = interface_class

def set_dsn(self, dsn: str) -> None:
self._derivative_dsn = dsn

def set_sizing(
self, min_size: int = 1, max_size: Optional[int] = None
) -> None:
self._min_size = min_size
self._max_size = max_size

def derive(self) -> BaseInterface:
if not self._derivative:
raise MayimError("No interface available to derive")
return self._derivative(dsn=self._derivative_dsn)
if self._derived_instance:
return self._derived_instance
self._derived_instance = self._derivative(
dsn=self._derivative_dsn,
min_size=self._min_size,
max_size=self._max_size,
)
return self._derived_instance
Loading