Support unicode objects for paths

Use sys.getfilesystemencoding() for encoding
This commit is contained in:
hofmockel 2014-01-16 08:51:01 +01:00
parent b4fb12589d
commit 6277f9ab5c
5 changed files with 43 additions and 9 deletions

View file

@ -8,7 +8,7 @@ Database object
.. py:method:: __init__(db_name, Options opts, read_only=False) .. py:method:: __init__(db_name, Options opts, read_only=False)
:param string db_name: Name of the database to open :param unicode db_name: Name of the database to open
:param opts: Options for this specific database :param opts: Options for this specific database
:type opts: :py:class:`rocksdb.Options` :type opts: :py:class:`rocksdb.Options`
:param bool read_only: If ``True`` the database is opened read-only. :param bool read_only: If ``True`` the database is opened read-only.

View file

@ -329,7 +329,7 @@ Options object
and the db data dir's absolute path will be used as the log file and the db data dir's absolute path will be used as the log file
name's prefix. name's prefix.
| *Type:* ``string`` | *Type:* ``unicode``
| *Default:* ``""`` | *Default:* ``""``
.. py:attribute:: wal_dir .. py:attribute:: wal_dir
@ -340,7 +340,7 @@ Options object
If it is non empty, the log files will be in kept the specified dir. If it is non empty, the log files will be in kept the specified dir.
When destroying the db, all log files in wal_dir and the dir itself is deleted When destroying the db, all log files in wal_dir and the dir itself is deleted
| *Type:* ``string`` | *Type:* ``unicode``
| *Default:* ``""`` | *Default:* ``""``
.. py:attribute:: disable_seek_compaction .. py:attribute:: disable_seek_compaction

View file

@ -7,6 +7,7 @@ from cython.operator cimport dereference as deref
from cpython.string cimport PyString_AsString from cpython.string cimport PyString_AsString
from cpython.string cimport PyString_Size from cpython.string cimport PyString_Size
from cpython.string cimport PyString_FromString from cpython.string cimport PyString_FromString
from cpython.unicode cimport PyUnicode_Decode
from std_memory cimport shared_ptr from std_memory cimport shared_ptr
cimport options cimport options
@ -24,6 +25,7 @@ from slice_ cimport slice_to_str
from slice_ cimport str_to_slice from slice_ cimport str_to_slice
from status cimport Status from status cimport Status
import sys
from interfaces import MergeOperator as IMergeOperator from interfaces import MergeOperator as IMergeOperator
from interfaces import AssociativeMergeOperator as IAssociativeMergeOperator from interfaces import AssociativeMergeOperator as IAssociativeMergeOperator
from interfaces import FilterPolicy as IFilterPolicy from interfaces import FilterPolicy as IFilterPolicy
@ -64,6 +66,23 @@ cdef check_status(const Status& st):
###################################################### ######################################################
cdef string bytes_to_string(bytes path) except *:
return string(PyBytes_AsString(path), PyBytes_Size(path))
## only for filsystem paths
cdef string path_to_string(object path) except *:
if isinstance(path, bytes):
return bytes_to_string(path)
if isinstance(path, unicode):
path = path.encode(sys.getfilesystemencoding())
return bytes_to_string(path)
else:
raise TypeError("Wrong type for path: %s" % path)
cdef object string_to_path(string path):
fs_encoding = sys.getfilesystemencoding()
return PyUnicode_Decode(path.c_str(), path.size(), fs_encoding, "replace")
## Here comes the stuff for the comparator ## Here comes the stuff for the comparator
@cython.internal @cython.internal
cdef class PyComparator(object): cdef class PyComparator(object):
@ -609,15 +628,15 @@ cdef class Options(object):
property db_log_dir: property db_log_dir:
def __get__(self): def __get__(self):
return self.opts.db_log_dir return string_to_path(self.opts.db_log_dir)
def __set__(self, value): def __set__(self, value):
self.opts.db_log_dir = value self.opts.db_log_dir = path_to_string(value)
property wal_dir: property wal_dir:
def __get__(self): def __get__(self):
return self.opts.wal_dir return string_to_path(self.opts.wal_dir)
def __set__(self, value): def __set__(self, value):
self.opts.wal_dir = value self.opts.wal_dir = path_to_string(value)
property disable_seek_compaction: property disable_seek_compaction:
def __get__(self): def __get__(self):
@ -946,14 +965,14 @@ cdef class DB(object):
check_status( check_status(
db.DB_OpenForReadOnly( db.DB_OpenForReadOnly(
deref(opts.opts), deref(opts.opts),
db_name, path_to_string(db_name),
cython.address(self.db), cython.address(self.db),
False)) False))
else: else:
check_status( check_status(
db.DB_Open( db.DB_Open(
deref(opts.opts), deref(opts.opts),
db_name, path_to_string(db_name),
cython.address(self.db))) cython.address(self.db)))
self.opts = opts self.opts = opts

View file

@ -24,6 +24,12 @@ class TestDB(unittest.TestCase, TestHelper):
def tearDown(self): def tearDown(self):
self._close_db() self._close_db()
def test_unicode_path(self):
name = b'/tmp/M\xc3\xbcnchen'.decode('utf8')
rocksdb.DB(name, rocksdb.Options(create_if_missing=True))
self.addCleanup(shutil.rmtree, name)
self.assertTrue(os.path.isdir(name))
def test_get_none(self): def test_get_none(self):
self.assertIsNone(self.db.get('xxx')) self.assertIsNone(self.db.get('xxx'))

View file

@ -52,3 +52,12 @@ class TestOptions(unittest.TestCase):
ob = rocksdb.LRUCache(100) ob = rocksdb.LRUCache(100)
opts.block_cache = ob opts.block_cache = ob
self.assertEqual(ob, opts.block_cache) self.assertEqual(ob, opts.block_cache)
def test_unicode_path(self):
name = b'/tmp/M\xc3\xbcnchen'.decode('utf8')
opts = rocksdb.Options()
opts.db_log_dir = name
opts.wal_dir = name
self.assertEqual(name, opts.db_log_dir)
self.assertEqual(name, opts.wal_dir)