Python LDAP Filter ·

Build, generate, and validate LDAP filters
A Python 3 utility library for working with Lightweight Directory Access Protocol (LDAP) filters.
This project is a Python port of the node-ldap-filters project. The filters produced by the library are based on RFC 4515.
Note: This project is currently only compatible with Python 3.4 or higher.
Usage
Installation
Install via pip:
pip install ldap-filter
Building a Filter
This library exposes a number of APIs that allow you to build filters programmatically. The logical and attribute methods of the Filter object can be combined in a number of ways to generate filters ranging from very simple to very complex.
The following is a quick example of how you might build a filter programmatically:
from ldap_filter import Filter
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
Filter.OR([
Filter.attribute('dept').equal_to('accounting'),
Filter.attribute('dept').equal_to('operations')
])
])
print(output.to_string()) # (&(name=bob)(mail=*@example.com)(|(dept=accounting)(dept=operations)))
Attribute Methods
Attribute methods are used to create LDAP attribute filter strings. The Filter.attribute(name) method returns an Attribute object that the following filter methods can be applied to.
output = Filter.attribute('name').equal_to('bob') # (name=bob)
Methods:
-
Attribute.present() - Tests if an attribute is present.
- Output:
(attribute=*)
- Output:
-
Attribute.equal_to(value) - Tests if an attribute is equal to the provided
value.- Output:
(attribute=value)
- Output:
-
Attribute.contains(value) - Tests if an attribute contains the provided
value.- Output:
(attribute=*value*)
- Output:
-
Attribute.starts_with(value) - Tests if an attribute starts with the provided
value.- Output:
(attribute=value*)
- Output:
-
Attribute.ends_with(value) - Tests if an attribute ends with the provided
value.- Output:
(attribute=*value)
- Output:
-
Attribute.approx(value) - Tests if an attribute is an approximate match to the provided
value.- Output:
(attribute~=value)
- Output:
-
Attribute.gte(value) - Tests if an attribute is greater than or equal to the provided
value.- Output:
(attribute>=value)
- Output:
-
Attribute.lte(value) - Tests if an attribute is less than or equal to the provided
value.- Output:
(attribute<=value)
- Output:
-
Attribute.raw(value) - Allows for a custom filter with escaped
valueoutput.- Output:
(attribute=value)
- Output:
Logical Methods
Logical methods are used to aggregate simple attribute filters. You can nest as many logical methods as needed to produce complex filters.
output = Filter.OR([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('name').equal_to('bill')
])
print(output) # (|(name=bob)(name=bill))
Methods:
-
Filter.AND(filt) - Accepts a list of
Filter,Attribute, orGroupobjects.- Output:
(&(filt=1)(filt=2)..)
- Output:
-
Filter.OR(filt) - Accepts a list of
Filter,Attribute, orGroupobjects.- Output:
(|(filt=1)(filt=2)..)
- Output:
-
Filter.NOT(filt) - Accepts a single
Attributeobject.- Output:
(!(filt=1))
- Output:
Filter Parsing
The Filter.parse(input) method can be used to create a Filter object from an existing LDAP filter. This method can also be used to determine if a string is a valid LDAP filter or not.
input = '(|(name=bob)(name=bill))'
Filter.parse(input)
If an invalid LDAP filter string is passed a ParseError exception will be thrown.
from ldap_filter import Filter, ParseError
input = '(|(name=bob)name=bill))'
try:
Filter.parse(input)
except ParseError as e:
print(e)
Error Output:
Line 1: expected [\x20], [\x09], "\r\n", "\n", '(', ')'
(|(name=bob)name=bill)
^
Simplifying Filters
The Filter.simplify() method can be used to eliminate unnecessary AND/OR filters that only have one child node.
input = '(&(name=bob))'
complex = Filter.parse(input)
print(complex.simplify()) # (name=bob)
Filter Output
There are a few options for getting a string output from your Filter object with optional custom formatting.
Simple String
You can get simple filter string by calling the Filter.to_string() method. The Filter class also implements Python's __str__ method, allowing you to type cast the Filter object directly to a string or concatenate with other strings.
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
])
# Filter.to_string() output.
print(output.to_string()) # (&(name=bob)(mail=*@example.com))
# Typecast output.
print(str(output)) # (&(name=bob)(mail=*@example.com))
# String concatenate output
print('LDAP Filter: ' + output) # LDAP Filter: (&(name=bob)(mail=*@example.com))
Beautified String
The Filter.to_string() method provides additional formatting options to produce beautified filter strings.
You can get the default beautified format by passing True to the Filter.to_string(indent) method
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
Filter.OR([
Filter.attribute('dept').equal_to('accounting'),
Filter.attribute('dept').equal_to('operations')
])
])
print(output.to_string(True))
Default Beautified Output:
(&
(name=bob)
(mail=*@example.com)
(|
(dept=accounting)
(dept=operations)
)
)
or you can customize the output by passing the indent and/or indt_char parameters to Filter.to_string(indent, indt_char). The indent parameter accepts an integer value while the indt_char parameter accepts any string or character value.
output = Filter.AND([
Filter.attribute('name').equal_to('bob'),
Filter.attribute('mail').ends_with('@example.com'),
Filter.OR([
Filter.attribute('dept').equal_to('accounting'),
Filter.attribute('dept').equal_to('operations')
])
])
print(output.to_string(2, '.'))
Custom Beautified Output:
(&
..(name=bob)
..(mail=*@example.com)
..(|
....(dept=accounting)
....(dept=operations)
..)
)
Filter Matching
The Filter.match(data) method allows you to evaluate a Python dictionary with attributes against an LDAP filter. The method will return True if a match is found or False if there is no match (or if an attribute matches a NOT exclusion).
filt = Filter.AND([
Filter.attribute('department').equal_to('accounting'),
Filter.NOT(
Filter.attribute('status').equal_to('terminated')
)
])
employee1 = {
'name': 'Bob Smith',
'department': 'Accounting',
'status': 'Active'
}
print(filt.match(employee1)) # True
employee2 = {
'name': 'Jane Brown',
'department': 'Accounting',
'status': 'Terminated'
}
print(filt.match(employee2)) # False
employee3 = {
'name': 'Bob Smith',
'department': 'Marketing',
'status': 'Active'
}
print(filt.match(employee3)) # False
Unit Tests
In order to run the test suite the pytest library is required. You can install pytest by running:
pip install pytest
To run the unit tests simply type pytest in the projects root directory
Home Page
Project home page is https://github.com/SteveEwell/python-ldap-filter
License
The Python LDAP Filter project is open source software released under the MIT licence. Copyright 2024 Stephen Ewell
Metadata
Release files for ldap-filter 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ldap_filter-1.0.1.tar.gz | 17.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ldap_filter-1.0.1-py2.py3-none-any.whl | Python 2, Python 3 | none | any | Details |
Total release size: 30.7 kB
Release files / ldap_filter-1.0.1.tar.gz
| Download URL | ldap_filter-1.0.1.tar.gz |
|---|---|
| Size | 17.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b0b0b51ff8b681459dc9cb958c1238cb941b39d03280213c2d1f2cd142acbedf
|
|
BLAKE2b-256 checksum How to use checksums |
356c54b3c28c1431c7c64c4b610fb5c83721a5598a59f38c59a45db9518a80b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.12.4
|
Release files / ldap_filter-1.0.1-py2.py3-none-any.whl
| Download URL | ldap_filter-1.0.1-py2.py3-none-any.whl |
|---|---|
| Size | 12.9 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
d0691b58d7fc867e3c24663122773e7ebccdda35b2f35caa9bff30357a9807ab
|
|
BLAKE2b-256 checksum How to use checksums |
d1d4f2213e236d78937e2636dcf7d40cdaf6cdd53e760415512e1302677022c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.12.4
|