From b720de21f02e12f70b6791a25272c9fe851456fb Mon Sep 17 00:00:00 2001 From: Alexander Kazeka Date: Tue, 22 Sep 2015 11:29:00 +0300 Subject: [PATCH] Version bump: ran 2to3, changed buffer to memoryview, updated setup and tox config --- .travis.yml | 2 +- README.rst | 3 +++ park.py | 54 ++++++++++++++++++++++++++++++------------- setup.py | 4 ++-- test-requirements.txt | 6 ++--- test_park.py | 8 +++---- tox.ini | 2 +- 7 files changed, 52 insertions(+), 27 deletions(-) diff --git a/.travis.yml b/.travis.yml index d95f21d..83e2345 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: python python: + - "3.4" - "2.7" - - "2.6" install: pip install -r test-requirements.txt --use-mirrors script: sh run-tests diff --git a/README.rst b/README.rst index 75f783c..b93bf90 100644 --- a/README.rst +++ b/README.rst @@ -1,3 +1,6 @@ +.. image:: https://travis-ci.org/litl/park.svg?branch=master :alt: Build Status +.. image:: https://coveralls.io/repos/litl/park/badge.svg?branch=master :alt: Coverage Status + Park is a persistent key-value API for Python with ordered traversal of keys. Both keys and values are binary safe. It's similar in use to LevelDB, but has no dependencies outside the Python standard library. diff --git a/park.py b/park.py index ecfba0d..95f77e6 100644 --- a/park.py +++ b/park.py @@ -1,7 +1,5 @@ # coding: utf-8 -# Copyright 2012 litl, LLC. All Rights Reserved. - -__version__ = "1.0.0" +# Copyright 2012-2015 litl, LLC. All Rights Reserved. import abc import itertools @@ -9,10 +7,28 @@ import os import sqlite3 +__version__ = "1.1.0" + logger = logging.getLogger(__name__) __all__ = ["SQLiteStore", "KVStore"] +import sys +if sys.version_info < (3,): + def b(x): + return x + + def un_b(x): + return x +else: + import codecs + + def b(x): + return codecs.latin_1_encode(x)[0] + + def un_b(x): + return codecs.latin_1_decode(x)[0] + class KVStore(object): """An abstract key-value interface with support for range iteration.""" @@ -244,7 +260,7 @@ def __init__(self, path): self.conn = sqlite3.connect(path) # Don't create unicode objects for retrieved values - self.conn.text_factory = buffer + self.conn.text_factory = memoryview # Disable the SQLite cache. Its pages tend to get swapped # out, even if the database file is in buffer cache. @@ -284,15 +300,16 @@ def get(self, key, default=None): q = "SELECT value FROM kv WHERE key = ?" c = self.conn.cursor() - row = c.execute(q, (sqlite3.Binary(key),)).fetchone() + row = c.execute(q, (sqlite3.Binary(b(key)),)).fetchone() if not row: return default - return bytes(row[0]) + return un_b(bytes(row[0])) def put(self, key, value): q = "INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)" - self.conn.execute(q, (sqlite3.Binary(key), sqlite3.Binary(value))) + self.conn.execute(q, + (sqlite3.Binary(b(key)), sqlite3.Binary(b(value)))) self.conn.commit() def put_many(self, items): @@ -301,14 +318,15 @@ def put_many(self, items): blob = sqlite3.Binary for batch in ibatch(items, 30000): - items = ((blob(key), blob(value)) for key, value in batch) + items = ((blob(b(key)), blob(b(value))) + for key, value in batch) c.executemany(q, items) self.conn.commit() def delete(self, key): q = "DELETE FROM kv WHERE key = ?" - self.conn.execute(q, (sqlite3.Binary(key),)) + self.conn.execute(q, (sqlite3.Binary(b(key)),)) self.conn.commit() def delete_many(self, keys): @@ -317,19 +335,23 @@ def delete_many(self, keys): blob = sqlite3.Binary for batch in ibatch(keys, 30000): - items = ((blob(key),) for key in batch) + items = ((blob(b(key)),) for key in batch) c.executemany(q, items) self.conn.commit() def _range_where(self, key_from=None, key_to=None): if key_from is not None and key_to is None: + key_from = b(key_from) return "WHERE key >= :key_from" if key_from is None and key_to is not None: + key_to = b(key_to) return "WHERE key <= :key_to" if key_from is not None and key_to is not None: + key_from = b(key_from) + key_to = b(key_to) return "WHERE key BETWEEN :key_from AND :key_to" return "" @@ -339,25 +361,25 @@ def items(self, key_from=None, key_to=None): % self._range_where(key_from, key_to) if key_from is not None: - key_from = sqlite3.Binary(key_from) + key_from = sqlite3.Binary(b(key_from)) if key_to is not None: - key_to = sqlite3.Binary(key_to) + key_to = sqlite3.Binary(b(key_to)) c = self.conn.cursor() for key, value in c.execute(q, dict(key_from=key_from, key_to=key_to)): - yield bytes(key), bytes(value) + yield un_b(bytes(key)), un_b(bytes(value)) def keys(self, key_from=None, key_to=None): q = "SELECT key FROM kv %s ORDER BY key " \ % self._range_where(key_from, key_to) if key_from is not None: - key_from = sqlite3.Binary(key_from) + key_from = sqlite3.Binary(b(key_from)) if key_to is not None: - key_to = sqlite3.Binary(key_to) + key_to = sqlite3.Binary(b(key_to)) c = self.conn.cursor() for key, in c.execute(q, dict(key_from=key_from, key_to=key_to)): - yield bytes(key) + yield un_b(bytes(key)) diff --git a/setup.py b/setup.py index 91fd0cd..82895fa 100755 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ # Load the test requirements. These are in a separate file so they can # be accessed from Travis CI and tox. with open("test-requirements.txt") as fd: - tests_require = list(fd.xreadlines()) + tests_require = list(fd) setup( @@ -25,7 +25,7 @@ py_modules=["park"], setup_requires=[ - "unittest2==0.5.1" + "unittest2==1.1.0" ], test_suite="unittest2.collector", diff --git a/test-requirements.txt b/test-requirements.txt index 01847e2..153a2a4 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,3 @@ -coverage==3.5.2 -pep8==1.3.3 -pyflakes==0.5.0 +coverage==4.0 +pep8==1.6.2 +pyflakes==1.0.0 diff --git a/test_park.py b/test_park.py index e6e7b7d..22b24e2 100644 --- a/test_park.py +++ b/test_park.py @@ -1,5 +1,5 @@ # coding: utf-8 -# Copyright 2012 litl, LLC. All Rights Reserved. +# Copyright 2012-2015 litl, LLC. All Rights Reserved. import operator import os @@ -189,12 +189,12 @@ def test_items(self): ("nine", "value9") ]) - for key, value in put_items.items(): + for key, value in list(put_items.items()): self.store.put(key, value) # Sorted order is: eight five four nine one seven six three two keys = list(self.store.items()) - expected = sorted(put_items.items(), key=operator.itemgetter(0)) + expected = sorted(list(put_items.items()), key=operator.itemgetter(0)) self.assertEqual(expected, keys) # Test key_from on keys that are present and missing in the db @@ -260,7 +260,7 @@ def test_context_manager(self): class TestIbatch(unittest.TestCase): def test_ibatch(self): - items = range(10) + items = list(range(10)) batches = park.ibatch(items, 3) diff --git a/tox.ini b/tox.ini index 3ffd161..9cac59b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py26, py27 +envlist = py27, py34 [testenv] deps=