bottle-lmdb 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: bottle-lmdb
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author: Kimikazu Kato
|
|
6
|
+
Author-email: Kimikazu Kato <kimikazu@gmail.com>
|
|
7
|
+
Requires-Dist: bottle>=0.12.25
|
|
8
|
+
Requires-Dist: lmdb>=3.0.0
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# bottle-lmdb
|
|
13
|
+
Lightning Memory-Mapped Database (LMDB) plugin for Bottle.
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from bottle import Bottle
|
|
19
|
+
from bottle_lmdb import LMDBPlugin
|
|
20
|
+
|
|
21
|
+
app = Bottle()
|
|
22
|
+
plugin = LMDBPlugin("/path/to/db")
|
|
23
|
+
app.install(plugin)
|
|
24
|
+
|
|
25
|
+
@app.get("/write/<key>/<value>")
|
|
26
|
+
def write(key, value, db):
|
|
27
|
+
with db.begin(write=True) as txn:
|
|
28
|
+
txn.put(key.encode(), value.encode())
|
|
29
|
+
return "ok"
|
|
30
|
+
|
|
31
|
+
@app.get("/read/<key>")
|
|
32
|
+
def read(key, db):
|
|
33
|
+
with db.begin() as txn:
|
|
34
|
+
value = txn.get(key.encode())
|
|
35
|
+
return value.decode() if value else "not found"
|
|
36
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# bottle-lmdb
|
|
2
|
+
Lightning Memory-Mapped Database (LMDB) plugin for Bottle.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from bottle import Bottle
|
|
8
|
+
from bottle_lmdb import LMDBPlugin
|
|
9
|
+
|
|
10
|
+
app = Bottle()
|
|
11
|
+
plugin = LMDBPlugin("/path/to/db")
|
|
12
|
+
app.install(plugin)
|
|
13
|
+
|
|
14
|
+
@app.get("/write/<key>/<value>")
|
|
15
|
+
def write(key, value, db):
|
|
16
|
+
with db.begin(write=True) as txn:
|
|
17
|
+
txn.put(key.encode(), value.encode())
|
|
18
|
+
return "ok"
|
|
19
|
+
|
|
20
|
+
@app.get("/read/<key>")
|
|
21
|
+
def read(key, db):
|
|
22
|
+
with db.begin() as txn:
|
|
23
|
+
value = txn.get(key.encode())
|
|
24
|
+
return value.decode() if value else "not found"
|
|
25
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "bottle-lmdb"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Add your description here"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Kimikazu Kato", email = "kimikazu@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"bottle>=0.12.25",
|
|
12
|
+
"lmdb>=3.0.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = ["uv_build>=0.8.22,<0.9.0"]
|
|
17
|
+
build-backend = "uv_build"
|
|
18
|
+
|
|
19
|
+
[dependency-groups]
|
|
20
|
+
dev = [
|
|
21
|
+
"httpx>=0.28.1",
|
|
22
|
+
"mypy>=2.4.1",
|
|
23
|
+
"pytest>=9.2.0",
|
|
24
|
+
"tox-uv>=1.36.1",
|
|
25
|
+
]
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import typing
|
|
3
|
+
import lmdb
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LMDBPlugin:
|
|
7
|
+
name = "lmdb"
|
|
8
|
+
api = 2
|
|
9
|
+
|
|
10
|
+
def __init__(self, db_path: str, **kwargs) -> None:
|
|
11
|
+
"""Initialize the plugin.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
db_path: Path to the LMDB database directory.
|
|
15
|
+
**kwargs: Extra options forwarded to ``lmdb.Environment``.
|
|
16
|
+
The ``keyword`` option sets the route keyword argument
|
|
17
|
+
name used to inject the environment (default: ``"db"``).
|
|
18
|
+
"""
|
|
19
|
+
self._db_path = db_path
|
|
20
|
+
self._kwargs = kwargs.copy()
|
|
21
|
+
self._env: None | lmdb.Environment = None
|
|
22
|
+
if "keyword" in kwargs:
|
|
23
|
+
keyword = self._kwargs["keyword"]
|
|
24
|
+
del self._kwargs["keyword"]
|
|
25
|
+
else:
|
|
26
|
+
keyword = "db"
|
|
27
|
+
self._keyword: str = keyword
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def env(self) -> lmdb.Environment:
|
|
31
|
+
"""Return the LMDB environment, opening it lazily on first access.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
lmdb.Environment: The environment for ``db_path``.
|
|
35
|
+
"""
|
|
36
|
+
# When a work process access this first time db is initialized
|
|
37
|
+
if self._env is None:
|
|
38
|
+
self._env = lmdb.Environment(self._db_path, **self._kwargs)
|
|
39
|
+
return self._env
|
|
40
|
+
|
|
41
|
+
def apply(self, callback: typing.Callable, route) -> typing.Callable:
|
|
42
|
+
"""Wrap a route callback to inject the LMDB environment.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
callback: The original route callback.
|
|
46
|
+
route: The Bottle route object (unused).
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
A wrapper that passes the environment to the callback
|
|
50
|
+
via the configured keyword argument.
|
|
51
|
+
"""
|
|
52
|
+
keyword = route.config.get("lmdb.keyword", self._keyword)
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
args = inspect.signature(route.callback).parameters
|
|
56
|
+
except (TypeError, ValueError):
|
|
57
|
+
return callback
|
|
58
|
+
if keyword not in args:
|
|
59
|
+
return callback
|
|
60
|
+
|
|
61
|
+
def wrapper(*a, **ka):
|
|
62
|
+
ka[keyword] = self.env
|
|
63
|
+
return callback(*a, **ka)
|
|
64
|
+
|
|
65
|
+
return wrapper
|
|
File without changes
|