1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/lib/ldb/_ldb_text.py
Petr Viktorin d584d5ee2a pyldb: Split text/byte strings for compatibility with Python 3
Compatibility with Python 2, and backwards compatibility on Python 2,
is kept.

Under Python 3, DNs, attribute names, filters, controls are always text
(unicode) strings, encoded to/from UTF-8 for storage.
Attribute values are byte strings.

When creating DNs and attribute values, both text and bytes are accepted.
This allows creating messages from homogeneous dicts.

LDB Messages and MessageElements have a .text attribute, which offers
a text view on the contents: any value retrieved from it will be a text
string. The wrapper is implemented in a new Python module.

Thanks to Stefan Metzmacher for const warning fixes

Signed-off-by: Petr Viktorin <pviktori@redhat.com>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2015-11-05 18:04:24 +01:00

149 lines
3.5 KiB
Python

# Text wrapper for ldb bindings
#
# Copyright (C) 2015 Petr Viktorin <pviktori@redhat.com>
# Published under the GNU LGPLv3 or later
import sys
import functools
import ldb
def _recursive_encode(obj):
if isinstance(obj, bytes):
return obj
elif isinstance(obj, str):
return obj.encode('utf-8')
else:
return [_recursive_encode(o) for o in obj]
class _WrapBase(object):
@classmethod
def _wrap(cls, wrapped):
self = cls.__new__(cls)
self._wrapped = wrapped
return self
def __len__(self):
return len(self._wrapped)
def __eq__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped == other._wrapped
else:
return self._wrapped == other
def __ne__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped != other._wrapped
else:
return self._wrapped != other
def __lt__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped < other._wrapped
else:
return self._wrapped < other
def __le__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped >= other._wrapped
else:
return self._wrapped >= other
def __gt__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped > other._wrapped
else:
return self._wrapped > other
def __ge__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped >= other._wrapped
else:
return self._wrapped >= other
def __repr__(self):
return '%s.text' % repr(self._wrapped)
class MessageElementTextWrapper(_WrapBase):
"""Text interface for a LDB message element"""
def __iter__(self):
for item in self._wrapped:
yield item.decode('utf-8')
def __getitem__(self, key):
result = self._wrapped[key]
if result is None:
return None
else:
return result.decode('utf-8')
@property
def flags(self):
return self._wrapped.flags
@property
def set_flags(self):
return self._wrapped.set_flags
_wrap_element = MessageElementTextWrapper._wrap
class MessageTextWrapper(_WrapBase):
"""Text interface for a LDB message"""
def __getitem__(self, key):
result = self._wrapped[key]
if result is None:
return None
else:
return _wrap_element(result)
def get(self, *args, **kwargs):
result = self._wrapped.get(*args, **kwargs)
if isinstance(result, ldb.MessageElement):
return _wrap_element(result)
elif isinstance(result, bytes):
return result.decode('utf-8')
else:
return result
def __setitem__(self, key, item):
self._wrapped[key] = _recursive_encode(item)
def __delitem__(self, key):
del self._wrapped[key]
def elements(self):
return [_wrap_element(el) for el in self._wrapped.elements()]
def items(self):
return [(attr, _wrap_element(el)) for attr, el in self._wrapped.items()]
@property
def keys(self):
return self._wrapped.keys
@property
def remove(self):
return self._wrapped.remove
@property
def add(self):
return self._wrapped.add
@property
def dn(self):
return self._wrapped.dn
@dn.setter
def dn(self, new_value):
self._wrapped.dn = new_value