or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-bonsai

Python 3 module for accessing LDAP directory servers with async framework support and Active Directory integration.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/bonsai@1.5.x

To install, run

npx @tessl/cli install tessl/pypi-bonsai@1.5.0

0

# Bonsai

1

2

A comprehensive Python LDAP library for accessing LDAP directory servers with asynchronous framework support and Windows Active Directory integration. Bonsai provides a pythonic interface with high-performance C extensions, dictionary-like LDAP entry handling, and extensive async framework support.

3

4

## Package Information

5

6

- **Package Name**: bonsai

7

- **Language**: Python

8

- **Installation**: `pip install bonsai`

9

10

## Core Imports

11

12

```python

13

import bonsai

14

```

15

16

Common imports for LDAP operations:

17

18

```python

19

from bonsai import LDAPClient, LDAPConnection, LDAPEntry, LDAPDN, LDAPURL

20

```

21

22

For async operations:

23

24

```python

25

from bonsai.asyncio import AIOLDAPConnection

26

from bonsai.gevent import GeventLDAPConnection

27

from bonsai.tornado import TornadoLDAPConnection

28

from bonsai.trio import TrioLDAPConnection

29

```

30

31

## Basic Usage

32

33

```python

34

from bonsai import LDAPClient

35

36

# Create LDAP client

37

client = LDAPClient("ldap://localhost")

38

client.set_credentials("SIMPLE", user="cn=admin,dc=example,dc=com", password="secret")

39

40

# Connect and perform operations

41

with client.connect() as conn:

42

# Search for entries

43

results = conn.search("dc=example,dc=com", 2)

44

45

# Access entry attributes

46

for entry in results:

47

print(f"DN: {entry.dn}")

48

print(f"Attributes: {dict(entry)}")

49

50

# Create new entry

51

new_entry = LDAPEntry("cn=newuser,dc=example,dc=com")

52

new_entry['objectClass'] = ['person', 'organizationalPerson']

53

new_entry['cn'] = 'newuser'

54

new_entry['sn'] = 'User'

55

56

# Add to directory

57

conn.add(new_entry)

58

```

59

60

## Architecture

61

62

Bonsai's architecture is built around several key components:

63

64

- **LDAPClient**: Configuration and connection factory for LDAP servers

65

- **LDAPConnection**: Active connection object providing all LDAP operations

66

- **LDAPEntry**: Dictionary-like interface for LDAP entries with change tracking

67

- **LDAPDN**: Distinguished name parsing and manipulation

68

- **LDAPURL**: LDAP URL parsing and construction

69

70

The library uses native LDAP libraries (libldap on Unix, WinLDAP on Windows) written in C for high performance, while providing a pythonic interface with automatic change tracking and comprehensive error handling.

71

72

## Capabilities

73

74

### Core LDAP Operations

75

76

Essential LDAP functionality including client configuration, connection management, entry operations, distinguished name handling, and URL parsing. These components provide the foundation for all LDAP interactions.

77

78

```python { .api }

79

class LDAPClient:

80

def __init__(self, url: str) -> None: ...

81

def connect(self, is_async: bool = False) -> LDAPConnection: ...

82

def set_credentials(self, mechanism: str, **kwargs) -> None: ...

83

84

class LDAPConnection:

85

def search(self, base: str, scope: int, filter_exp: str = None, **kwargs) -> list[LDAPEntry]: ...

86

def add(self, entry: LDAPEntry) -> None: ...

87

def modify(self, entry: LDAPEntry) -> None: ...

88

def delete(self, dn: str) -> None: ...

89

90

class LDAPEntry:

91

def __init__(self, dn: str) -> None: ...

92

def __getitem__(self, key: str) -> LDAPValueList: ...

93

def __setitem__(self, key: str, value) -> None: ...

94

```

95

96

[Core LDAP Operations](./core-ldap.md)

97

98

### Asynchronous Framework Support

99

100

Native integration with multiple Python async frameworks including asyncio, gevent, tornado, and trio. Each framework provides specialized connection classes optimized for their respective event loops.

101

102

```python { .api }

103

class AIOLDAPConnection(LDAPConnection):

104

async def search(self, base: str, scope: int, **kwargs) -> list[LDAPEntry]: ...

105

async def add(self, entry: LDAPEntry) -> None: ...

106

107

class GeventLDAPConnection(LDAPConnection):

108

def search(self, base: str, scope: int, **kwargs) -> list[LDAPEntry]: ...

109

110

class TornadoLDAPConnection(LDAPConnection):

111

def search(self, base: str, scope: int, **kwargs) -> Future[list[LDAPEntry]]: ...

112

```

113

114

[Async Framework Support](./async-frameworks.md)

115

116

### Active Directory Integration

117

118

Comprehensive Windows Active Directory support including Security Identifiers (SID), Access Control Lists (ACL), Security Descriptors, and User Account Control flags.

119

120

```python { .api }

121

class SID:

122

def __init__(self, sid_string: str) -> None: ...

123

def __str__(self) -> str: ...

124

125

class SecurityDescriptor:

126

def __init__(self, descriptor: bytes) -> None: ...

127

@property

128

def owner(self) -> SID: ...

129

@property

130

def dacl(self) -> ACL: ...

131

132

class UserAccountControl:

133

def __init__(self, value: int) -> None: ...

134

@property

135

def account_disabled(self) -> bool: ...

136

```

137

138

[Active Directory Support](./active-directory.md)

139

140

### Connection Pooling

141

142

Connection pool management for handling multiple concurrent LDAP connections with automatic lifecycle management and configurable pool sizes.

143

144

```python { .api }

145

class ConnectionPool:

146

def __init__(self, client: LDAPClient, minconn: int = 1, maxconn: int = 10) -> None: ...

147

def get(self) -> LDAPConnection: ...

148

def put(self, conn: LDAPConnection) -> None: ...

149

```

150

151

[Connection Pooling](./connection-pooling.md)

152

153

### LDIF Format Support

154

155

Read and write LDAP Data Interchange Format (LDIF) files for data import/export and backup operations.

156

157

```python { .api }

158

class LDIFReader:

159

def __init__(self, input_file) -> None: ...

160

def parse(self) -> Iterator[tuple[str, dict]]: ...

161

162

class LDIFWriter:

163

def __init__(self, output_file) -> None: ...

164

def write_entry(self, dn: str, entry: dict) -> None: ...

165

```

166

167

[LDIF Support](./ldif-support.md)

168

169

### Utilities and Error Handling

170

171

Utility functions for escaping LDAP filter expressions and attribute values, plus comprehensive exception hierarchy for robust error handling.

172

173

```python { .api }

174

def escape_filter_exp(expression: str) -> str: ...

175

def escape_attribute_value(value: str) -> str: ...

176

def get_vendor_info() -> dict: ...

177

178

class LDAPError(Exception):

179

def __init__(self, error_message: str, error_code: int = None) -> None: ...

180

181

class AuthenticationError(LDAPError): ...

182

class ConnectionError(LDAPError): ...

183

```

184

185

[Utilities and Errors](./utilities-errors.md)

186

187

## Types

188

189

```python { .api }

190

from enum import IntEnum

191

192

class LDAPSearchScope(IntEnum):

193

BASE = 0

194

ONELEVEL = 1

195

SUBTREE = 2

196

197

class LDAPModOp(IntEnum):

198

ADD = 0

199

DELETE = 1

200

REPLACE = 2

201

202

class LDAPValueList(list):

203

def __init__(self, items=None) -> None: ...

204

def append(self, item) -> None: ...

205

def extend(self, items) -> None: ...

206

def insert(self, index: int, item) -> None: ...

207

def remove(self, item) -> None: ...

208

def clear(self) -> None: ...

209

210

@property

211

def added(self) -> set: ...

212

213

@property

214

def deleted(self) -> set: ...

215

216

@property

217

def status(self) -> int: ...

218

219

class LDAPSearchIter:

220

def __init__(self, conn: "LDAPConnection", base: str, scope: int, **kwargs) -> None: ...

221

def __iter__(self) -> "LDAPSearchIter": ...

222

def __next__(self) -> "LDAPEntry": ...

223

def acquire_next_page(self) -> None: ...

224

225

@property

226

def cookie(self) -> Optional[bytes]: ...

227

228

@property

229

def estimated_list_count(self) -> int: ...

230

231

class LDAPReference:

232

def __init__(self, client: "LDAPClient", references: List[Union[str, "LDAPURL"]]) -> None: ...

233

234

@property

235

def client(self) -> "LDAPClient": ...

236

237

@property

238

def references(self) -> List["LDAPURL"]: ...

239

```