python-tkvdb


Namepython-tkvdb JSON
Version 0.2.3 PyPI version JSON
download
home_pagehttps://github.com/vladimir-g/python-tkvdb/
SummaryCython wrapper for tkvdb radix trie key-value database
upload_time2024-08-22 23:21:32
maintainerNone
docs_urlNone
authorVladimir Gorbunov
requires_python>=3.5
licenseISC
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # python-tkvdb

Python-tkvdb is a Cython wrapper for
[tkvdb](https://github.com/vmxdev/tkvdb) trie key-value
database. Python 3 is required.

Code isn't well tested in production environments.

## Installation

This is a typical python/cython package that uses setuptools build
system.

### From PyPi

The most simple way of installing is using `pip`:

    pip install python-tkvdb

Considering that package is using Cython, C compiler may be required
for building if suitable wheel for current platform isn't found.

### Downloading

Original tkvdb sources are included as submodule, so when installing
from git please use `git clone --recursive` for cloning, or init
submodules after with `git submodule update --init
--recursive`. Custom sources may also be provided in `tkvdb/`
subdirectory before build.

Source archives that were made with `python setup.py sdist` contain
generated C-code without `.pyx` files as Cython official documentation
recommends. Cython header files (`.pxd`) still provided though.

Package also can be distributed as python wheels. With wheels no
additional post-installation actions are required.

Initialization and usage of virtualenv or alternatives aren't
properly described in this manual, so use them by you own discretion.

### Building

Project uses Cython to generate C extension for Python. To build
package, you need to have C compiler and build tools.

For installation from the source archive, Cython isn't required, but
git versions require it. Source directory also includes
`pyproject.toml` (PEP 518), so if your build tool uses it, Cython
would be installed anyway.

To make common tasks easier, project contains simple Makefile that may
be used instad of pip/python commands. It isn't a requirement, so `pip
install .` also works. For additional reference, look into
[Makefile](Makefile).

Install example with virtualenv:

    cd python-tkvdb/
    python -m venv env
    source ./env/bin/activate
    make

Both Makefile and setup.py uses ``USE_CYTHON`` env variable (int, 0/1)
to determine if Cython (cythonize) would be started before extension
building. Cython needs to be installed in local environment for
this. Default value is 1 for make.

Makefile also has ``PYTHON`` env var that allows overriding python
interpreter path. Default value is just ``python``.

Example usage:

    USE_CYTHON=1 PYTHON=./env/bin/python make build

Make commands:

- `build` -- just build extension with `python setup.py build_ext`.
- `install` -- run `pip install`. Extension would be built if needed.
- no arguments (just `make`) -- alias for `install`.
- `dist` -- create wheel and sdist archive.
- `test` -- run unit tests
- `clean` -- remove generated code, compiled objects and distribution
archives.
- `uninstall` -- remove previously installed package (through `pip`)

After installing module `tkvdb` must be importable in the Python environment.

## Usage

Original `tkvdb` uses pretty specific terminology for some actions
(like transaction), so it is recommended to first consult with
original documentation anyway. Thread-safety notes and some caveats
are also described in the original README file.

Python-tkvdb provides pythonic-style wrapper for most parts of the original
library.

Most object have destructors that call `free` internally and do memory
management on garbage collection, but don't forget that this is
wrapper for C library.

Some code examples may also be found in [tests code](tests/).

### Modules

Project is splitted into multiple python modules:

- `ctkvdb` -- Cython wrapper with C definitions from `tkvdb.h`.
- `tkvdb.db` -- database object and initialization. Also imported in
  `__init__.py` (i.e. main `tkvdb` module).
- `tkvdb.transaction` -- transaction (actually main input/output.
  interface). Wrapper around ``tkvdb_tr``.
- `tkvdb.cursor` -- transaction cursors for iteration. Wrapper around `tkvdb_cursor`.
- `tkvdb.iterators` -- pythonic iterators for `tkvdb.cursor`.
- `tkvdb.errors` -- all db-related exceptions that code may throw.
- `tkvdb.params` -- database and transaction params. Wrapper around `tkvdb_params`.

### Database initialization

Database is wrapped into the `Tkvdb` object from `tkvdb` or `tkvdb.db`
modules. At this time only path to database file is
supported. Parameters (`tkvdb.params.Params`) optionally may be passed
to constructor.

```python
from tkvdb import Tkvdb

db = Tkvdb(path_to_db_file)
# some code
db.close()
```

Context manager (`with` statment) that includes auto closing is also
available:

```python
with Tkvdb(path_to_db_file) as db:
    # some code
    with db.transaction() as tr:
        # more code
```

Attributes (readonly):
- `path: str` -- path to database file.
- `is_opened: bool` -- shows that database is initialized properly.

Methods (may raise exceptions):
- `Tkvdb(path: str, params: tkvdb.params.Params = None)` (constructor)
  -- create database instance.
- `close()` -- close database.
- `transaction(params: tkvdb.params.Params = None) ->
  tkvdb.transaction.Transaction` -- create transaction.

There is also Cython method `get_db` that returns `tkvdb_db *`
pointer.

### Transactions

Transactions are basic way to do any operation with database. Consult
with original documentation about transaction term, because it doesn't
mean same thing as in other database systems.

**Input and ouput uses `bytes` type for everything**. Encode and
decode strings if needed.

Parameters (`tkvdb.params.Params`) optionally may be passed to
constructor.

Transaction must be created from database instance (described in
previous part):

```python
transaction = db.transaction()
transaction.begin()
transaction.put(b'key', b'value')
transaction.commit() # or transaction.rollback()
print(transaction.getvalue(b'key'))
transaction.free()
```

Pythonic `with` statment also available:

```python
with db.transaction() as tr:
    tr.put(b'key', b'value')
    tr.commit()
    print(tr.getvalue(b'key'))
```

Note that `with` statement *does not do commit, but rollbacks on
exception*. Do `commit` or `rollback` with your own code, or don't do
anything (implies rollback-like behavior). Transaction is started
(`begin`) automatically and will be freed (`free`) at exit from `with`
block though.

Transaction also has Python dict-like interface:

- `__getitem__` and `__setitem__`
- `get(key, default=None)`
- `keys()`, `values()` and `items()` iterators

```python
with db.transaction() as tr:
    tr[b'key'] = b'value'
    print(tr.get(b'other-key', b'default')) # prints b'default'
    tr.commit()
    print(tr[b'key']) # prints b'value'

    # Iterators
    for key in tr: # or tr.keys()
        print(key)
    for key, value in tr.items():
        print(key, value)
    for value in tr.values():
        print(value)
```

Multiple keys may be deleted by `delete` method using optional
`prefix` argument (default `False`). Passing `True` allows deleting
keys starting from prefix. Dict-like `del` operator always deletes
only exact key.

Attributes (readonly):
- `is_initialized: bool` -- shows that transaction underlying
  structures are initialized properly.
- `is_started: bool` -- shows that `begin()` method was called.
- `is_changed: bool` -- shows that transaction had any uncommited
  changes (i.e. `put()` was used).
- `ram_only: bool` -- indicates that transaction is RAM-only.

Transaction methods. Most of them may raise an exception:

- `Transaction(ram_only=True, params: tkvdb.params.Params = None)`
  (constructor) -- create transaction instance. Must be called
  manually only for RAM-only usage, otherwise `db.transaction()` must
  be used instead.
- `begin()` -- starts transaction, calls underlying `tkvdb_tr->begin()`.
- `getvalue(key: bytes) -> bytes` -- get value by key.
- `put(key: bytes)` -- insert value into db by key.
- `get(key: bytes, default: bytes = None) -> bytes` -- dict-like get with
  default value.
- `delete(key: bytes, prefix=False)` -- delete value by key. With
  `prefix=True` all keys staring with `key` will be deleted.
- `__getitem__`, `__setitem__`, `__delitem__` -- dict-like methods.
- `__contains__` -- allows usage of `in` operator.
- `free()` -- free transaction (called in `with` statement
  automatically).
- `keys()`, `values()`, `items()` -- return dict-like iterators.
- `cursor(seek_key=None, seek_type=Seek.EQ)` -- return transaction
  cursor (see `Cursors`), with optional seek.


#### RAM-only transactions

Transactions also may be used in RAM-only mode. These transactions don't
require database file and use less memory. They are cleared on
`commit()` or `rollback()`. See more about RAM-only transactions in
original documentation.

Use `tkvdb.Transaction()` constructor to create RAM-only transaction
without database. This transaction may also be used with `with`
statement, same auto-begin rules apply. Example:

```python
with Transaction() as tr:
    tr[b'key'] = b'value'
    print(tr[b'key'])  # prints b'value'
    tr.commit()  # clears transaction
```

### Iterators

Transaction can be traversed using iterators. It is also the main way
for iterating through database contents.

Module `tkvdb.iterators` provides three dict-like iterators that use
`tkvdb.cursor.Cursor` inside:

- `tkvdb.iterators.KeysIterator` -- iterating over keys.
- `tkvdb.iterators.ValuesIterator` -- iterating over values.
- `tkvdb.iterators.ItemsIterator` -- iterating over key-value pair.

They can be used with transaction:

```python
with db.transaction() as tr:
    for key in tr:  # or tr.keys()
        print(tr[key])
    for value in tr.values():
        print(value)
    for key, value in tr.items():
        print(key, value)
```

In all loops new instance of `Cursor` is used.

They also can be used with cursor:

```python
with db.transaction() as tr:
    with tr.cursor() as c:
        for key in c:
            print(c.key(), c.keysize())
```

Notice that cursor iterators use same underlying `Cursor` object, so
they would iterate from same place where cursor stopped before:

```python
with db.transaction() as tr:
    with tr.cursor() as c:
        c.first()
        # do some iteration with c.next()
        for key in c:
            print(key)  # it wouldn't be first key
            if something:
                break
        for value in c.values():  # starts from last iterated key
            print(value)
```

Reverse iteration is available through the standard `reversed`
function. Iterators and transaction have required methods for this.
For new cursors iteration will start from the end using
`tkvdb.cursor.Cursor.last`.

```python
with db.transaction() as tr:
    for key in reversed(tr):
        print(key)
    # All iterator types allow this
    for key, value in reversed(tr.items()):
        print(key, value)

with db.transaction() as tr:
    with tr.cursor() as c:
        for key in reversed(c):
            print(key)
    with tr.cursor() as c:
        for value in reversed(c.values()):
            print(value)
```

Cursors created from transacton can used for searching (as shorthand
for `tkvdb.cursor.Cursor.seek()`). More information in next section.

```python
with db.transaction() as tr:
    with tr.cursor(seek_key=b'seek-tr-31', seek_type=Seek.GE) as c:
        print(c.key())
```

### Cursors

Cursors are used to iterate through database contents. They are
defined in `tkvdb.cursor` module, C implementation is wrapped in
`tkvdb.cursor.Cursor` class.

Cursors are attached to transaction and created by
`Transacion.cursor()` method. They also may be created directly.

Although cursors are sole way to iterate and seek in tkvdb, it is
better and easier to use python-style iterators for
such purposes.

Example usage:

```python
with db.transaction() as tr:
    with tr.cursor() as c:
        c.first()
        while True:
            print(c.key(), c.value())
            try:
                c.next()
            except tkvdb.errors.NotFoundError:
                break
```

Cursor also may be used without `with` statement, it would be freed
anyway on garbage collection:

```python
with db.transaction() as tr:
    c = tr.cursor():
    c.first()
    # ...
```

Notice: `first` and `next` methods throw `tkvdb.errors.EmptyError` on
empty database, not `NotFoundError`. Cursors may be iterated by using
iterators (see previous section).

Cursor also may be iterated in reverse order using `prev()`
method. Another method called `last()` moves cursor to last record and
often useful for the reverse iteration.

Cursor can be used for search with `seek()` method. This allows
searching k-v pair by prefix using seek criteria. Criterias are
defined in `tkvdb.cursor.Seek` enum:

- `Seek.EQ` -- search for the exact key match.
- `Seek.LE` -- search for less (in terms of memcmp()) or equal key.
- `Seek.GE` -- search for greater (in terms of memcmp()) or equal key.

Seeking is also may be initiated using `Transaction.cursor()` method
(see more in `Transactions` section).

```python
from tkvdb.cursor import Seek

with db.transaction() as tr:
    with tr.cursor() as c:
        c.seek(b'key', Seek.EQ)
        key = c.key()
        # ...
        c.next()

    with tr.cursor(seek_key=b'key') as c:
        # ...
```

Attributes (readonly):
- `is_initialized: bool` -- shows that cursor underlying
  structures are initialized properly.
- `is_started: bool` -- shows that `first()` method was called.

Cursor methods.

- `first()` -- move cursor to first item in database.
- `last()` -- move cursor to last item in database.
- `next()` -- move cursor to next item in database.
- `prev()` -- move cursor to previous item in database.
- `key() -> bytes` -- get current key.
- `val() -> bytes` -- get current value.
- `keysize() -> int` -- get current key size.
- `valsize() -> int` -- get current value size.
- `free()` -- free cursor.
- `__iter__()` -- returns `tkvdb.iterators.KeysIterator`.
- `seek(key: bytes, seek: tkvdb.cursor.Seek)` -- search key by
  criteria.
- `keys()`, `values()`, `items()` -- return dict-like iterators.

### Params

Params are used to specify different options for database and/or
transactions. They are defined in `tkvdb.params` module: the C
implementation (`tkvdb_params` struct) is wrapped by
`tkvdb.params.Params` class, and param values are wrapped by the
`tkvdb.params.Param` enum.

Parameter names transfomed using CamelCase, example: 

```
TKVDB_PARAM_TR_DYNALLOC => TrDynalloc
TKVDB_PARAM_CURSOR_STACK_DYNALLOC => CursorStackDynalloc
```

Available parameters in `tkvdb.params.Param` enum:

- `TrDynalloc` -- `TKVDB_PARAM_TR_DYNALLOC`
- `TrLimit` -- `TKVDB_PARAM_TR_LIMIT`
- `Alignval` -- `TKVDB_PARAM_ALIGNVAL`
- `Autobegin` -- `TKVDB_PARAM_AUTOBEGIN`
- `CursorStackDynalloc` -- `TKVDB_PARAM_CURSOR_STACK_DYNALLOC`
- `CursorStackLimit` -- `TKVDB_PARAM_CURSOR_STACK_LIMIT`
- `CursorKeyDynalloc` -- `TKVDB_PARAM_CURSOR_KEY_DYNALLOC`
- `CursorKeyLimit` -- `TKVDB_PARAM_CURSOR_KEY_LIMIT`
- `DbfileOpenFlags` -- `TKVDB_PARAM_DBFILE_OPEN_FLAGS`

Consult with original `tkvdb` documentation for params meaning and
possible values.

Params usage:

```python
from tkvdb.params import Params, Param

# Passing params to database
params = Params({Param.Autobegin: 1})  # set params at init
with Tkvdb(path, params) as db:
    # Params also will be passed to db transactions
    with db.transaction() as tr:
        # ...
    # Transaction may use own params
    params = Params()
    params.set(Param.TrLimit, 100)
    with db.transaction(params) as tr:
        # ...

# Setting params after init
params = Params()
params.set(Param.Autobegin, 1)
tr = Transaction(params=params)  # RAM-only transaction
```

As in original `tkvdb` code, params from database are passed to
db-bound transaction, if they aren't overrided directly by passing
another `Params` instance to transaction.

Python implementation also stores all set params and stores them in
internal `values` dict. Notice that it tracks only params that were
set directly, so default values aren't known to `Params` wrapper.

Params attributes:
- `is_initialized: bool` -- shows that params underlying structures
  are initialized properly.

Params methods:
- `Params(params=None)` (constructor) -- create params
  instance. Argument `params` may be dict with param names and values.
- `get_values()` -- return all set params.
- `get(param: tkvdb.params.Param)` -- return single param value.
- `set(param: tkvdb.params.Param, value: int)` -- set param value.
- `free()` -- free params object.

There is also Cython method `get_params` that returns `tkvdb_params *`
pointer.

### Errors

Error classes are defined in `tkvdb.errors` module. Every non-ok
return value from the underlying C code is converted to python
Exception. Only `TKVDB_RES.TKVDB_OK` considered as success.

Consult with original documentation for error codes meaning.

One exception from this rule is
`tkvdb.transaction.Transaction.__getitem__()` (dict-like access) that
raises `KeyError` for python compatibility.

Examples:

```python
from tkvdb.errors import EmptyError, NotFoundError, NotStartedError

# ...
tr = db.transaction()
try:
    print(tr.getvalue(b'key'))
except (NotFoundError, EmptyError):
    print('key not found')
except NotStartedError:
    print('transaction not started')

with db.transaction() as tr:
    try:
        print(tr[b'key'])
    except KeyError:
        print('key not found')
```

Note that tkvdb raises `EmptyError` (`TKVDB_RES.TKVDB_EMPTY` return
code), not `NotFoundError` when key is not found in empty database,

Errors:

- `Error` -- base class for all tkvdb-related errors.
- `IoError` -- `TKVDB_RES.TKVDB_IO_ERROR` code.
- `LockedError` -- `TKVDB_RES.TKVDB_LOCKED` code.
- `EmptyError` -- `TKVDB_RES.TKVDB_EMPTY` code.
- `NotFoundError` -- `TKVDB_RES.TKVDB_NOT_FOUND` code.
- `EnomemError` -- `TKVDB_RES.TKVDB_ENOMEM` code.
- `CorruptedError` -- `TKVDB_RES.TKVDB_CORRUPTED` code.
- `NotStartedError` -- `TKVDB_RES.TKVDB_NOT_STARTED` code.
- `ModifiedError` -- `TKVDB_RES.TKVDB_MODIFIED` code.


## License

Python-tkvdb is licensed under ISC license as original tkvdb project.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/vladimir-g/python-tkvdb/",
    "name": "python-tkvdb",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.5",
    "maintainer_email": null,
    "keywords": null,
    "author": "Vladimir Gorbunov",
    "author_email": "vsg@suburban.me",
    "download_url": "https://files.pythonhosted.org/packages/9a/c8/79f69b89352c8d434ec4f703c1c97cacb1ad151637a9272ad3340d119ef7/python_tkvdb-0.2.3.tar.gz",
    "platform": null,
    "description": "# python-tkvdb\n\nPython-tkvdb is a Cython wrapper for\n[tkvdb](https://github.com/vmxdev/tkvdb) trie key-value\ndatabase. Python 3 is required.\n\nCode isn't well tested in production environments.\n\n## Installation\n\nThis is a typical python/cython package that uses setuptools build\nsystem.\n\n### From PyPi\n\nThe most simple way of installing is using `pip`:\n\n    pip install python-tkvdb\n\nConsidering that package is using Cython, C compiler may be required\nfor building if suitable wheel for current platform isn't found.\n\n### Downloading\n\nOriginal tkvdb sources are included as submodule, so when installing\nfrom git please use `git clone --recursive` for cloning, or init\nsubmodules after with `git submodule update --init\n--recursive`. Custom sources may also be provided in `tkvdb/`\nsubdirectory before build.\n\nSource archives that were made with `python setup.py sdist` contain\ngenerated C-code without `.pyx` files as Cython official documentation\nrecommends. Cython header files (`.pxd`) still provided though.\n\nPackage also can be distributed as python wheels. With wheels no\nadditional post-installation actions are required.\n\nInitialization and usage of virtualenv or alternatives aren't\nproperly described in this manual, so use them by you own discretion.\n\n### Building\n\nProject uses Cython to generate C extension for Python. To build\npackage, you need to have C compiler and build tools.\n\nFor installation from the source archive, Cython isn't required, but\ngit versions require it. Source directory also includes\n`pyproject.toml` (PEP 518), so if your build tool uses it, Cython\nwould be installed anyway.\n\nTo make common tasks easier, project contains simple Makefile that may\nbe used instad of pip/python commands. It isn't a requirement, so `pip\ninstall .` also works. For additional reference, look into\n[Makefile](Makefile).\n\nInstall example with virtualenv:\n\n    cd python-tkvdb/\n    python -m venv env\n    source ./env/bin/activate\n    make\n\nBoth Makefile and setup.py uses ``USE_CYTHON`` env variable (int, 0/1)\nto determine if Cython (cythonize) would be started before extension\nbuilding. Cython needs to be installed in local environment for\nthis. Default value is 1 for make.\n\nMakefile also has ``PYTHON`` env var that allows overriding python\ninterpreter path. Default value is just ``python``.\n\nExample usage:\n\n    USE_CYTHON=1 PYTHON=./env/bin/python make build\n\nMake commands:\n\n- `build` -- just build extension with `python setup.py build_ext`.\n- `install` -- run `pip install`. Extension would be built if needed.\n- no arguments (just `make`) -- alias for `install`.\n- `dist` -- create wheel and sdist archive.\n- `test` -- run unit tests\n- `clean` -- remove generated code, compiled objects and distribution\narchives.\n- `uninstall` -- remove previously installed package (through `pip`)\n\nAfter installing module `tkvdb` must be importable in the Python environment.\n\n## Usage\n\nOriginal `tkvdb` uses pretty specific terminology for some actions\n(like transaction), so it is recommended to first consult with\noriginal documentation anyway. Thread-safety notes and some caveats\nare also described in the original README file.\n\nPython-tkvdb provides pythonic-style wrapper for most parts of the original\nlibrary.\n\nMost object have destructors that call `free` internally and do memory\nmanagement on garbage collection, but don't forget that this is\nwrapper for C library.\n\nSome code examples may also be found in [tests code](tests/).\n\n### Modules\n\nProject is splitted into multiple python modules:\n\n- `ctkvdb` -- Cython wrapper with C definitions from `tkvdb.h`.\n- `tkvdb.db` -- database object and initialization. Also imported in\n  `__init__.py` (i.e. main `tkvdb` module).\n- `tkvdb.transaction` -- transaction (actually main input/output.\n  interface). Wrapper around ``tkvdb_tr``.\n- `tkvdb.cursor` -- transaction cursors for iteration. Wrapper around `tkvdb_cursor`.\n- `tkvdb.iterators` -- pythonic iterators for `tkvdb.cursor`.\n- `tkvdb.errors` -- all db-related exceptions that code may throw.\n- `tkvdb.params` -- database and transaction params. Wrapper around `tkvdb_params`.\n\n### Database initialization\n\nDatabase is wrapped into the `Tkvdb` object from `tkvdb` or `tkvdb.db`\nmodules. At this time only path to database file is\nsupported. Parameters (`tkvdb.params.Params`) optionally may be passed\nto constructor.\n\n```python\nfrom tkvdb import Tkvdb\n\ndb = Tkvdb(path_to_db_file)\n# some code\ndb.close()\n```\n\nContext manager (`with` statment) that includes auto closing is also\navailable:\n\n```python\nwith Tkvdb(path_to_db_file) as db:\n    # some code\n    with db.transaction() as tr:\n        # more code\n```\n\nAttributes (readonly):\n- `path: str` -- path to database file.\n- `is_opened: bool` -- shows that database is initialized properly.\n\nMethods (may raise exceptions):\n- `Tkvdb(path: str, params: tkvdb.params.Params = None)` (constructor)\n  -- create database instance.\n- `close()` -- close database.\n- `transaction(params: tkvdb.params.Params = None) ->\n  tkvdb.transaction.Transaction` -- create transaction.\n\nThere is also Cython method `get_db` that returns `tkvdb_db *`\npointer.\n\n### Transactions\n\nTransactions are basic way to do any operation with database. Consult\nwith original documentation about transaction term, because it doesn't\nmean same thing as in other database systems.\n\n**Input and ouput uses `bytes` type for everything**. Encode and\ndecode strings if needed.\n\nParameters (`tkvdb.params.Params`) optionally may be passed to\nconstructor.\n\nTransaction must be created from database instance (described in\nprevious part):\n\n```python\ntransaction = db.transaction()\ntransaction.begin()\ntransaction.put(b'key', b'value')\ntransaction.commit() # or transaction.rollback()\nprint(transaction.getvalue(b'key'))\ntransaction.free()\n```\n\nPythonic `with` statment also available:\n\n```python\nwith db.transaction() as tr:\n    tr.put(b'key', b'value')\n    tr.commit()\n    print(tr.getvalue(b'key'))\n```\n\nNote that `with` statement *does not do commit, but rollbacks on\nexception*. Do `commit` or `rollback` with your own code, or don't do\nanything (implies rollback-like behavior). Transaction is started\n(`begin`) automatically and will be freed (`free`) at exit from `with`\nblock though.\n\nTransaction also has Python dict-like interface:\n\n- `__getitem__` and `__setitem__`\n- `get(key, default=None)`\n- `keys()`, `values()` and `items()` iterators\n\n```python\nwith db.transaction() as tr:\n    tr[b'key'] = b'value'\n    print(tr.get(b'other-key', b'default')) # prints b'default'\n    tr.commit()\n    print(tr[b'key']) # prints b'value'\n\n    # Iterators\n    for key in tr: # or tr.keys()\n        print(key)\n    for key, value in tr.items():\n        print(key, value)\n    for value in tr.values():\n        print(value)\n```\n\nMultiple keys may be deleted by `delete` method using optional\n`prefix` argument (default `False`). Passing `True` allows deleting\nkeys starting from prefix. Dict-like `del` operator always deletes\nonly exact key.\n\nAttributes (readonly):\n- `is_initialized: bool` -- shows that transaction underlying\n  structures are initialized properly.\n- `is_started: bool` -- shows that `begin()` method was called.\n- `is_changed: bool` -- shows that transaction had any uncommited\n  changes (i.e. `put()` was used).\n- `ram_only: bool` -- indicates that transaction is RAM-only.\n\nTransaction methods. Most of them may raise an exception:\n\n- `Transaction(ram_only=True, params: tkvdb.params.Params = None)`\n  (constructor) -- create transaction instance. Must be called\n  manually only for RAM-only usage, otherwise `db.transaction()` must\n  be used instead.\n- `begin()` -- starts transaction, calls underlying `tkvdb_tr->begin()`.\n- `getvalue(key: bytes) -> bytes` -- get value by key.\n- `put(key: bytes)` -- insert value into db by key.\n- `get(key: bytes, default: bytes = None) -> bytes` -- dict-like get with\n  default value.\n- `delete(key: bytes, prefix=False)` -- delete value by key. With\n  `prefix=True` all keys staring with `key` will be deleted.\n- `__getitem__`, `__setitem__`, `__delitem__` -- dict-like methods.\n- `__contains__` -- allows usage of `in` operator.\n- `free()` -- free transaction (called in `with` statement\n  automatically).\n- `keys()`, `values()`, `items()` -- return dict-like iterators.\n- `cursor(seek_key=None, seek_type=Seek.EQ)` -- return transaction\n  cursor (see `Cursors`), with optional seek.\n\n\n#### RAM-only transactions\n\nTransactions also may be used in RAM-only mode. These transactions don't\nrequire database file and use less memory. They are cleared on\n`commit()` or `rollback()`. See more about RAM-only transactions in\noriginal documentation.\n\nUse `tkvdb.Transaction()` constructor to create RAM-only transaction\nwithout database. This transaction may also be used with `with`\nstatement, same auto-begin rules apply. Example:\n\n```python\nwith Transaction() as tr:\n    tr[b'key'] = b'value'\n    print(tr[b'key'])  # prints b'value'\n    tr.commit()  # clears transaction\n```\n\n### Iterators\n\nTransaction can be traversed using iterators. It is also the main way\nfor iterating through database contents.\n\nModule `tkvdb.iterators` provides three dict-like iterators that use\n`tkvdb.cursor.Cursor` inside:\n\n- `tkvdb.iterators.KeysIterator` -- iterating over keys.\n- `tkvdb.iterators.ValuesIterator` -- iterating over values.\n- `tkvdb.iterators.ItemsIterator` -- iterating over key-value pair.\n\nThey can be used with transaction:\n\n```python\nwith db.transaction() as tr:\n    for key in tr:  # or tr.keys()\n        print(tr[key])\n    for value in tr.values():\n        print(value)\n    for key, value in tr.items():\n        print(key, value)\n```\n\nIn all loops new instance of `Cursor` is used.\n\nThey also can be used with cursor:\n\n```python\nwith db.transaction() as tr:\n    with tr.cursor() as c:\n        for key in c:\n            print(c.key(), c.keysize())\n```\n\nNotice that cursor iterators use same underlying `Cursor` object, so\nthey would iterate from same place where cursor stopped before:\n\n```python\nwith db.transaction() as tr:\n    with tr.cursor() as c:\n        c.first()\n        # do some iteration with c.next()\n        for key in c:\n            print(key)  # it wouldn't be first key\n            if something:\n                break\n        for value in c.values():  # starts from last iterated key\n            print(value)\n```\n\nReverse iteration is available through the standard `reversed`\nfunction. Iterators and transaction have required methods for this.\nFor new cursors iteration will start from the end using\n`tkvdb.cursor.Cursor.last`.\n\n```python\nwith db.transaction() as tr:\n    for key in reversed(tr):\n        print(key)\n    # All iterator types allow this\n    for key, value in reversed(tr.items()):\n        print(key, value)\n\nwith db.transaction() as tr:\n    with tr.cursor() as c:\n        for key in reversed(c):\n            print(key)\n    with tr.cursor() as c:\n        for value in reversed(c.values()):\n            print(value)\n```\n\nCursors created from transacton can used for searching (as shorthand\nfor `tkvdb.cursor.Cursor.seek()`). More information in next section.\n\n```python\nwith db.transaction() as tr:\n    with tr.cursor(seek_key=b'seek-tr-31', seek_type=Seek.GE) as c:\n        print(c.key())\n```\n\n### Cursors\n\nCursors are used to iterate through database contents. They are\ndefined in `tkvdb.cursor` module, C implementation is wrapped in\n`tkvdb.cursor.Cursor` class.\n\nCursors are attached to transaction and created by\n`Transacion.cursor()` method. They also may be created directly.\n\nAlthough cursors are sole way to iterate and seek in tkvdb, it is\nbetter and easier to use python-style iterators for\nsuch purposes.\n\nExample usage:\n\n```python\nwith db.transaction() as tr:\n    with tr.cursor() as c:\n        c.first()\n        while True:\n            print(c.key(), c.value())\n            try:\n                c.next()\n            except tkvdb.errors.NotFoundError:\n                break\n```\n\nCursor also may be used without `with` statement, it would be freed\nanyway on garbage collection:\n\n```python\nwith db.transaction() as tr:\n    c = tr.cursor():\n    c.first()\n    # ...\n```\n\nNotice: `first` and `next` methods throw `tkvdb.errors.EmptyError` on\nempty database, not `NotFoundError`. Cursors may be iterated by using\niterators (see previous section).\n\nCursor also may be iterated in reverse order using `prev()`\nmethod. Another method called `last()` moves cursor to last record and\noften useful for the reverse iteration.\n\nCursor can be used for search with `seek()` method. This allows\nsearching k-v pair by prefix using seek criteria. Criterias are\ndefined in `tkvdb.cursor.Seek` enum:\n\n- `Seek.EQ` -- search for the exact key match.\n- `Seek.LE` -- search for less (in terms of memcmp()) or equal key.\n- `Seek.GE` -- search for greater (in terms of memcmp()) or equal key.\n\nSeeking is also may be initiated using `Transaction.cursor()` method\n(see more in `Transactions` section).\n\n```python\nfrom tkvdb.cursor import Seek\n\nwith db.transaction() as tr:\n    with tr.cursor() as c:\n        c.seek(b'key', Seek.EQ)\n        key = c.key()\n        # ...\n        c.next()\n\n    with tr.cursor(seek_key=b'key') as c:\n        # ...\n```\n\nAttributes (readonly):\n- `is_initialized: bool` -- shows that cursor underlying\n  structures are initialized properly.\n- `is_started: bool` -- shows that `first()` method was called.\n\nCursor methods.\n\n- `first()` -- move cursor to first item in database.\n- `last()` -- move cursor to last item in database.\n- `next()` -- move cursor to next item in database.\n- `prev()` -- move cursor to previous item in database.\n- `key() -> bytes` -- get current key.\n- `val() -> bytes` -- get current value.\n- `keysize() -> int` -- get current key size.\n- `valsize() -> int` -- get current value size.\n- `free()` -- free cursor.\n- `__iter__()` -- returns `tkvdb.iterators.KeysIterator`.\n- `seek(key: bytes, seek: tkvdb.cursor.Seek)` -- search key by\n  criteria.\n- `keys()`, `values()`, `items()` -- return dict-like iterators.\n\n### Params\n\nParams are used to specify different options for database and/or\ntransactions. They are defined in `tkvdb.params` module: the C\nimplementation (`tkvdb_params` struct) is wrapped by\n`tkvdb.params.Params` class, and param values are wrapped by the\n`tkvdb.params.Param` enum.\n\nParameter names transfomed using CamelCase, example: \n\n```\nTKVDB_PARAM_TR_DYNALLOC => TrDynalloc\nTKVDB_PARAM_CURSOR_STACK_DYNALLOC => CursorStackDynalloc\n```\n\nAvailable parameters in `tkvdb.params.Param` enum:\n\n- `TrDynalloc` -- `TKVDB_PARAM_TR_DYNALLOC`\n- `TrLimit` -- `TKVDB_PARAM_TR_LIMIT`\n- `Alignval` -- `TKVDB_PARAM_ALIGNVAL`\n- `Autobegin` -- `TKVDB_PARAM_AUTOBEGIN`\n- `CursorStackDynalloc` -- `TKVDB_PARAM_CURSOR_STACK_DYNALLOC`\n- `CursorStackLimit` -- `TKVDB_PARAM_CURSOR_STACK_LIMIT`\n- `CursorKeyDynalloc` -- `TKVDB_PARAM_CURSOR_KEY_DYNALLOC`\n- `CursorKeyLimit` -- `TKVDB_PARAM_CURSOR_KEY_LIMIT`\n- `DbfileOpenFlags` -- `TKVDB_PARAM_DBFILE_OPEN_FLAGS`\n\nConsult with original `tkvdb` documentation for params meaning and\npossible values.\n\nParams usage:\n\n```python\nfrom tkvdb.params import Params, Param\n\n# Passing params to database\nparams = Params({Param.Autobegin: 1})  # set params at init\nwith Tkvdb(path, params) as db:\n    # Params also will be passed to db transactions\n    with db.transaction() as tr:\n        # ...\n    # Transaction may use own params\n    params = Params()\n    params.set(Param.TrLimit, 100)\n    with db.transaction(params) as tr:\n        # ...\n\n# Setting params after init\nparams = Params()\nparams.set(Param.Autobegin, 1)\ntr = Transaction(params=params)  # RAM-only transaction\n```\n\nAs in original `tkvdb` code, params from database are passed to\ndb-bound transaction, if they aren't overrided directly by passing\nanother `Params` instance to transaction.\n\nPython implementation also stores all set params and stores them in\ninternal `values` dict. Notice that it tracks only params that were\nset directly, so default values aren't known to `Params` wrapper.\n\nParams attributes:\n- `is_initialized: bool` -- shows that params underlying structures\n  are initialized properly.\n\nParams methods:\n- `Params(params=None)` (constructor) -- create params\n  instance. Argument `params` may be dict with param names and values.\n- `get_values()` -- return all set params.\n- `get(param: tkvdb.params.Param)` -- return single param value.\n- `set(param: tkvdb.params.Param, value: int)` -- set param value.\n- `free()` -- free params object.\n\nThere is also Cython method `get_params` that returns `tkvdb_params *`\npointer.\n\n### Errors\n\nError classes are defined in `tkvdb.errors` module. Every non-ok\nreturn value from the underlying C code is converted to python\nException. Only `TKVDB_RES.TKVDB_OK` considered as success.\n\nConsult with original documentation for error codes meaning.\n\nOne exception from this rule is\n`tkvdb.transaction.Transaction.__getitem__()` (dict-like access) that\nraises `KeyError` for python compatibility.\n\nExamples:\n\n```python\nfrom tkvdb.errors import EmptyError, NotFoundError, NotStartedError\n\n# ...\ntr = db.transaction()\ntry:\n    print(tr.getvalue(b'key'))\nexcept (NotFoundError, EmptyError):\n    print('key not found')\nexcept NotStartedError:\n    print('transaction not started')\n\nwith db.transaction() as tr:\n    try:\n        print(tr[b'key'])\n    except KeyError:\n        print('key not found')\n```\n\nNote that tkvdb raises `EmptyError` (`TKVDB_RES.TKVDB_EMPTY` return\ncode), not `NotFoundError` when key is not found in empty database,\n\nErrors:\n\n- `Error` -- base class for all tkvdb-related errors.\n- `IoError` -- `TKVDB_RES.TKVDB_IO_ERROR` code.\n- `LockedError` -- `TKVDB_RES.TKVDB_LOCKED` code.\n- `EmptyError` -- `TKVDB_RES.TKVDB_EMPTY` code.\n- `NotFoundError` -- `TKVDB_RES.TKVDB_NOT_FOUND` code.\n- `EnomemError` -- `TKVDB_RES.TKVDB_ENOMEM` code.\n- `CorruptedError` -- `TKVDB_RES.TKVDB_CORRUPTED` code.\n- `NotStartedError` -- `TKVDB_RES.TKVDB_NOT_STARTED` code.\n- `ModifiedError` -- `TKVDB_RES.TKVDB_MODIFIED` code.\n\n\n## License\n\nPython-tkvdb is licensed under ISC license as original tkvdb project.\n",
    "bugtrack_url": null,
    "license": "ISC",
    "summary": "Cython wrapper for tkvdb radix trie key-value database",
    "version": "0.2.3",
    "project_urls": {
        "Homepage": "https://github.com/vladimir-g/python-tkvdb/"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a6c445e32be4c86158b8c7f6f755af6924b5bff9c2e2178d035a4d95cd33d092",
                "md5": "f22da44ad2e19df938f4f3ad16431420",
                "sha256": "bf45449f53ec32493b5532fdb45a60059897a4c3035d2bc634c7a122a344ae1d"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "f22da44ad2e19df938f4f3ad16431420",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.5",
            "size": 1859095,
            "upload_time": "2024-08-22T23:20:58",
            "upload_time_iso_8601": "2024-08-22T23:20:58.692343Z",
            "url": "https://files.pythonhosted.org/packages/a6/c4/45e32be4c86158b8c7f6f755af6924b5bff9c2e2178d035a4d95cd33d092/python_tkvdb-0.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "64fc1344e0894dce63800f5eb8c68317697f346969ec35b831fc289b7ab483d5",
                "md5": "33026ecadd1e0ce14a4a324019ed11d6",
                "sha256": "8a8e44ae35e6187b73d9257a56146ff8722eade5aa28146989dd511997cb56c8"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "33026ecadd1e0ce14a4a324019ed11d6",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.5",
            "size": 2011242,
            "upload_time": "2024-08-22T23:21:01",
            "upload_time_iso_8601": "2024-08-22T23:21:01.585591Z",
            "url": "https://files.pythonhosted.org/packages/64/fc/1344e0894dce63800f5eb8c68317697f346969ec35b831fc289b7ab483d5/python_tkvdb-0.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3f00b26b6181163e90eda5a7bbfcd45413762b49b30fe1621d6dc911374e4ccc",
                "md5": "78dacb3bd3c84cfdc80ea2a7201535e1",
                "sha256": "19e14d60a5f206935181da7f31e9f9616ab1aa90aac2f1a173a2380f256754d1"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "78dacb3bd3c84cfdc80ea2a7201535e1",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.5",
            "size": 2001957,
            "upload_time": "2024-08-22T23:21:17",
            "upload_time_iso_8601": "2024-08-22T23:21:17.564748Z",
            "url": "https://files.pythonhosted.org/packages/3f/00/b26b6181163e90eda5a7bbfcd45413762b49b30fe1621d6dc911374e4ccc/python_tkvdb-0.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "218c59447ab390917378920dbdf222a486c781eb8826c7d6ab0c864f0481c655",
                "md5": "a07d997f00d3596d9e645fcbe3f31bf9",
                "sha256": "a2754ce78eb5c0c6e22191ba47203019fcb9880c97984d0475bcd60cb683fa90"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "a07d997f00d3596d9e645fcbe3f31bf9",
            "packagetype": "bdist_wheel",
            "python_version": "cp36",
            "requires_python": ">=3.5",
            "size": 1683347,
            "upload_time": "2024-08-22T23:21:20",
            "upload_time_iso_8601": "2024-08-22T23:21:20.273028Z",
            "url": "https://files.pythonhosted.org/packages/21/8c/59447ab390917378920dbdf222a486c781eb8826c7d6ab0c864f0481c655/python_tkvdb-0.2.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4a83d06cc4f6139712afaeae0bb361f713ad1da1fd8f9c9237aef1cb3e289016",
                "md5": "f18df27ea7ce423e79546d43e679c0e2",
                "sha256": "7e953116d6aa2c6b7e304929b81983349949f572ac582d2422fafb0944e5eb1e"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "f18df27ea7ce423e79546d43e679c0e2",
            "packagetype": "bdist_wheel",
            "python_version": "cp37",
            "requires_python": ">=3.5",
            "size": 1772710,
            "upload_time": "2024-08-22T23:21:23",
            "upload_time_iso_8601": "2024-08-22T23:21:23.036037Z",
            "url": "https://files.pythonhosted.org/packages/4a/83/d06cc4f6139712afaeae0bb361f713ad1da1fd8f9c9237aef1cb3e289016/python_tkvdb-0.2.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4c92cdaadf4a200395071b1f2ebb5c1893e85c99f222e90fbde3c00180e7de69",
                "md5": "c551bbd8806045d6965aaac4fffadfd5",
                "sha256": "fd464f2da0c3d44c3364a677da216441306cdc55059a9a3b2779023d64f40631"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "c551bbd8806045d6965aaac4fffadfd5",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.5",
            "size": 1873974,
            "upload_time": "2024-08-22T23:21:25",
            "upload_time_iso_8601": "2024-08-22T23:21:25.272469Z",
            "url": "https://files.pythonhosted.org/packages/4c/92/cdaadf4a200395071b1f2ebb5c1893e85c99f222e90fbde3c00180e7de69/python_tkvdb-0.2.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cab9325ca1d401f22d65d5cba4f351fc57a83c9aa382c3e5f894ad7f2ff57834",
                "md5": "4113a72d3421478a8e6832ee0f2531e6",
                "sha256": "03dee3e00c2c7821b1f545b26101a4f3066e2765f82a3d248d86a4de533f30ec"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "4113a72d3421478a8e6832ee0f2531e6",
            "packagetype": "bdist_wheel",
            "python_version": "cp39",
            "requires_python": ">=3.5",
            "size": 1876969,
            "upload_time": "2024-08-22T23:21:27",
            "upload_time_iso_8601": "2024-08-22T23:21:27.533194Z",
            "url": "https://files.pythonhosted.org/packages/ca/b9/325ca1d401f22d65d5cba4f351fc57a83c9aa382c3e5f894ad7f2ff57834/python_tkvdb-0.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "90295330e78cbaba97158358a5884848446493f4ec9935e288bd3b99fa77acb6",
                "md5": "237bd78ccbf942673f20f84410f69e4a",
                "sha256": "1313435f6550564a0c6a01ee4d4cb9bd3ace561cc73e8243efaaa40bb7cd46f5"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "237bd78ccbf942673f20f84410f69e4a",
            "packagetype": "bdist_wheel",
            "python_version": "pp310",
            "requires_python": ">=3.5",
            "size": 357466,
            "upload_time": "2024-08-22T23:21:29",
            "upload_time_iso_8601": "2024-08-22T23:21:29.109340Z",
            "url": "https://files.pythonhosted.org/packages/90/29/5330e78cbaba97158358a5884848446493f4ec9935e288bd3b99fa77acb6/python_tkvdb-0.2.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a09aeafd29121e2a19b575987deb0f2786ccd5572e1325b9eb0e6d800323fe87",
                "md5": "e52a8272f5295d902044cc54516351a0",
                "sha256": "689f2a68d800998c66aa873f0bf00d101e611a31f8609f3e3bcc37a789381908"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "e52a8272f5295d902044cc54516351a0",
            "packagetype": "bdist_wheel",
            "python_version": "pp39",
            "requires_python": ">=3.5",
            "size": 356984,
            "upload_time": "2024-08-22T23:21:30",
            "upload_time_iso_8601": "2024-08-22T23:21:30.688744Z",
            "url": "https://files.pythonhosted.org/packages/a0/9a/eafd29121e2a19b575987deb0f2786ccd5572e1325b9eb0e6d800323fe87/python_tkvdb-0.2.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9ac879f69b89352c8d434ec4f703c1c97cacb1ad151637a9272ad3340d119ef7",
                "md5": "a1c6276304f05140534417d6d93c1373",
                "sha256": "0338c3b84a1faac09c4fe0edae484aeb609798d29d639215b28e70c733f7de79"
            },
            "downloads": -1,
            "filename": "python_tkvdb-0.2.3.tar.gz",
            "has_sig": false,
            "md5_digest": "a1c6276304f05140534417d6d93c1373",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.5",
            "size": 471580,
            "upload_time": "2024-08-22T23:21:32",
            "upload_time_iso_8601": "2024-08-22T23:21:32.316212Z",
            "url": "https://files.pythonhosted.org/packages/9a/c8/79f69b89352c8d434ec4f703c1c97cacb1ad151637a9272ad3340d119ef7/python_tkvdb-0.2.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-22 23:21:32",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "vladimir-g",
    "github_project": "python-tkvdb",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "python-tkvdb"
}
        
Elapsed time: 0.48326s