1 """Provide a more Pythonic and object-oriented interface to ldb."""
4 # Swig interface to Samba
6 # Copyright (C) Tim Potter 2006
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, see <http://www.gnu.org/licenses/>.
25 # - should an empty dn be represented as None, or an empty string?
27 # - should single-valued attributes be a string, or a list with one
33 # Global initialisation
35 result
= ldb_global_init()
38 raise LdbError
, (result
, 'ldb_global_init failed')
42 class LdbError(Exception):
43 """An exception raised when a ldb error occurs.
44 The exception data is a tuple consisting of the ldb number and a
45 string description of the error."""
51 """A class representing a ldb message as a Python dictionary."""
54 self
.mem_ctx
= talloc_init(None)
55 self
.msg
= ldb_msg_new(self
.mem_ctx
)
58 if self
.mem_ctx
is not None:
59 talloc_free(self
.mem_ctx
)
63 # Make the dn attribute of the object dynamic
65 def __getattr__(self
, attr
):
67 return ldb_dn_linearize(None, self
.msg
.dn
)
68 return self
.__dict
__[attr
]
70 def __setattr__(self
, attr
, value
):
72 self
.msg
.dn
= ldb_dn_explode(self
.msg
, value
)
73 if self
.msg
.dn
== None:
74 err
= LDB_ERR_INVALID_DN_SYNTAX
75 raise LdbError(err
, ldb_strerror(err
))
77 self
.__dict
__[attr
] = value
79 # Get and set individual elements
81 def __getitem__(self
, key
):
83 elt
= ldb_msg_find_element(self
.msg
, key
)
86 raise KeyError, "No such attribute '%s'" % key
88 return [ldb_val_array_getitem(elt
.values
, i
)
89 for i
in range(elt
.num_values
)]
91 def __setitem__(self
, key
, value
):
92 ldb_msg_remove_attr(self
.msg
, key
)
93 if type(value
) in (list, tuple):
94 [ldb_msg_add_value(self
.msg
, key
, v
) for v
in value
]
96 ldb_msg_add_value(self
.msg
, key
, value
)
98 # Dictionary interface
99 # TODO: move to iterator based interface
102 return self
.msg
.num_elements
105 return [ldb_message_element_array_getitem(self
.msg
.elements
, i
).name
106 for i
in range(self
.msg
.num_elements
)]
109 return [self
[k
] for k
in self
.keys()]
112 return [(k
, self
[k
]) for k
in self
.keys()]
116 def sanity_check(self
):
117 return ldb_msg_sanity_check(self
.msg
)
120 """A class representing a binding to a ldb file."""
122 def __init__(self
, url
, flags
= 0):
123 """Initialise underlying ldb."""
125 self
.mem_ctx
= talloc_init('mem_ctx for ldb 0x%x' % id(self
))
126 self
.ldb_ctx
= ldb_init(self
.mem_ctx
)
128 result
= ldb_connect(self
.ldb_ctx
, url
, flags
, None)
130 if result
!= LDB_SUCCESS
:
131 raise LdbError
, (result
, ldb_strerror(result
))
134 """Called when the object is to be garbage collected."""
138 """Close down a ldb."""
139 if self
.mem_ctx
is not None:
140 talloc_free(self
.mem_ctx
)
144 def _ldb_call(self
, fn
, *args
):
145 """Call a ldb function with args. Raise a LdbError exception
146 if the function returns a non-zero return value."""
150 if result
!= LDB_SUCCESS
:
151 raise LdbError
, (result
, ldb_strerror(result
))
153 def search(self
, expression
):
154 """Search a ldb for a given expression."""
156 self
._ldb
_call
(ldb_search
, self
.ldb_ctx
, None, LDB_SCOPE_DEFAULT
,
159 return [LdbMessage(ldb_message_ptr_array_getitem(result
.msgs
, ndx
))
160 for ndx
in range(result
.count
)]
162 def delete(self
, dn
):
165 _dn
= ldb_dn_explode(self
.ldb_ctx
, dn
)
167 self
._ldb
_call
(ldb_delete
, self
.ldb_ctx
, _dn
)
169 def rename(self
, olddn
, newdn
):
172 _olddn
= ldb_dn_explode(self
.ldb_ctx
, olddn
)
173 _newdn
= ldb_dn_explode(self
.ldb_ctx
, newdn
)
175 self
._ldb
_call
(ldb_rename
, self
.ldb_ctx
, _olddn
, _newdn
)
178 self
._ldb
_call
(ldb_add
, self
.ldb_ctx
, m
.msg
)