ldap-filter


Nameldap-filter JSON
Version 1.0.1 PyPI version JSON
download
home_pageNone
SummaryA Python utility library for working with Lightweight Directory Access Protocol (LDAP) filters.
upload_time2024-10-22 21:25:01
maintainerNone
docs_urlNone
authorNone
requires_python>=3.4
licenseThe MIT License (MIT) Copyright (c) 2018 Stephen Ewell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords ldap filter rfc4515 utility development
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            # Python LDAP Filter · [![Latest Version](https://img.shields.io/pypi/v/ldap-filter.svg)](https://pypi.python.org/pypi/ldap-filter) [![License](https://img.shields.io/pypi/l/ldap-filter.svg)](https://pypi.python.org/pypi/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](https://github.com/tapmodo/node-ldap-filters) project. The filters produced by the library are based on [RFC 4515](https://tools.ietf.org/html/rfc4515).

**Note:** This project is currently only compatible with Python 3.4 or higher.

# Usage #

## Installation ##

Install via pip:

``` bash
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:

``` python
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.

``` python
output = Filter.attribute('name').equal_to('bob')  # (name=bob)
```

#### Methods:

- **Attribute.present()** - Tests if an attribute is present.
    - *Output:* `(attribute=*)`

- **Attribute.equal_to(value)** - Tests if an attribute is equal to the provided `value`.
    - *Output:* `(attribute=value)`

- **Attribute.contains(value)** - Tests if an attribute contains the provided `value`.
    - *Output:* `(attribute=*value*)`

- **Attribute.starts_with(value)** - Tests if an attribute starts with the provided `value`.
    - *Output:* `(attribute=value*)`

- **Attribute.ends_with(value)** - Tests if an attribute ends with the provided `value`.
    - *Output:* `(attribute=*value)`

- **Attribute.approx(value)** - Tests if an attribute is an approximate match to the provided `value`.
    - *Output:* `(attribute~=value)`

- **Attribute.gte(value)** - Tests if an attribute is greater than or equal to the provided `value`.
    - *Output:* `(attribute>=value)`

- **Attribute.lte(value)** - Tests if an attribute is less than or equal to the provided `value`.
    - *Output:* `(attribute<=value)`

- **Attribute.raw(value)** - Allows for a custom filter with escaped `value` output.
    - *Output:* `(attribute=value)`



### Logical Methods

Logical methods are used to aggregate simple attribute filters. You can nest as many logical methods as needed to produce complex filters.

``` python
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`, or `Group` objects.
    - *Output:* `(&(filt=1)(filt=2)..)`

- **Filter.OR(filt)** - Accepts a list of `Filter`, `Attribute`, or `Group` objects.
    - *Output:* `(|(filt=1)(filt=2)..)`

- **Filter.NOT(filt)** - Accepts a single `Attribute` object.
    - *Output:* `(!(filt=1))`

## 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.

``` python
input = '(|(name=bob)(name=bill))'

Filter.parse(input)
```

If an invalid LDAP filter string is passed a `ParseError` exception will be thrown.

``` python
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.

``` python
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.

``` python
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

``` python
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.

``` python
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).

``` python
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:

``` bash
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](https://en.wikipedia.org/wiki/MIT_License). Copyright 2024 Stephen Ewell

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "ldap-filter",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.4",
    "maintainer_email": null,
    "keywords": "ldap, filter, rfc4515, utility, development",
    "author": null,
    "author_email": "Stephen Ewell <steve@ewell.io>",
    "download_url": "https://files.pythonhosted.org/packages/35/6c/54b3c28c1431c7c64c4b610fb5c83721a5598a59f38c59a45db9518a80b1/ldap_filter-1.0.1.tar.gz",
    "platform": null,
    "description": "# Python LDAP Filter &middot; [![Latest Version](https://img.shields.io/pypi/v/ldap-filter.svg)](https://pypi.python.org/pypi/ldap-filter) [![License](https://img.shields.io/pypi/l/ldap-filter.svg)](https://pypi.python.org/pypi/ldap-filter)\n\n> Build, generate, and validate LDAP filters\n\n\nA Python 3 utility library for working with Lightweight Directory Access Protocol (LDAP) filters.\n\nThis project is a Python port of the [node-ldap-filters](https://github.com/tapmodo/node-ldap-filters) project. The filters produced by the library are based on [RFC 4515](https://tools.ietf.org/html/rfc4515).\n\n**Note:** This project is currently only compatible with Python 3.4 or higher.\n\n# Usage #\n\n## Installation ##\n\nInstall via pip:\n\n``` bash\npip install ldap-filter\n```\n\n## Building a Filter ##\n\nThis 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.\n\nThe following is a quick example of how you might build a filter programmatically:\n\n``` python\nfrom ldap_filter import Filter\n\noutput = Filter.AND([\n    Filter.attribute('name').equal_to('bob'),\n    Filter.attribute('mail').ends_with('@example.com'),\n    Filter.OR([\n        Filter.attribute('dept').equal_to('accounting'),\n        Filter.attribute('dept').equal_to('operations')\n    ])\n])\n\nprint(output.to_string())  # (&(name=bob)(mail=*@example.com)(|(dept=accounting)(dept=operations)))\n```\n\n\n### Attribute Methods\n\nAttribute 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.\n\n``` python\noutput = Filter.attribute('name').equal_to('bob')  # (name=bob)\n```\n\n#### Methods:\n\n- **Attribute.present()** - Tests if an attribute is present.\n    - *Output:* `(attribute=*)`\n\n- **Attribute.equal_to(value)** - Tests if an attribute is equal to the provided `value`.\n    - *Output:* `(attribute=value)`\n\n- **Attribute.contains(value)** - Tests if an attribute contains the provided `value`.\n    - *Output:* `(attribute=*value*)`\n\n- **Attribute.starts_with(value)** - Tests if an attribute starts with the provided `value`.\n    - *Output:* `(attribute=value*)`\n\n- **Attribute.ends_with(value)** - Tests if an attribute ends with the provided `value`.\n    - *Output:* `(attribute=*value)`\n\n- **Attribute.approx(value)** - Tests if an attribute is an approximate match to the provided `value`.\n    - *Output:* `(attribute~=value)`\n\n- **Attribute.gte(value)** - Tests if an attribute is greater than or equal to the provided `value`.\n    - *Output:* `(attribute>=value)`\n\n- **Attribute.lte(value)** - Tests if an attribute is less than or equal to the provided `value`.\n    - *Output:* `(attribute<=value)`\n\n- **Attribute.raw(value)** - Allows for a custom filter with escaped `value` output.\n    - *Output:* `(attribute=value)`\n\n\n\n### Logical Methods\n\nLogical methods are used to aggregate simple attribute filters. You can nest as many logical methods as needed to produce complex filters.\n\n``` python\noutput = Filter.OR([\n    Filter.attribute('name').equal_to('bob'),\n    Filter.attribute('name').equal_to('bill')\n])\n\nprint(output)  # (|(name=bob)(name=bill))\n```\n\n#### Methods:\n\n- **Filter.AND(filt)** - Accepts a list of `Filter`, `Attribute`, or `Group` objects.\n    - *Output:* `(&(filt=1)(filt=2)..)`\n\n- **Filter.OR(filt)** - Accepts a list of `Filter`, `Attribute`, or `Group` objects.\n    - *Output:* `(|(filt=1)(filt=2)..)`\n\n- **Filter.NOT(filt)** - Accepts a single `Attribute` object.\n    - *Output:* `(!(filt=1))`\n\n## Filter Parsing ##\n\nThe `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.\n\n``` python\ninput = '(|(name=bob)(name=bill))'\n\nFilter.parse(input)\n```\n\nIf an invalid LDAP filter string is passed a `ParseError` exception will be thrown.\n\n``` python\nfrom ldap_filter import Filter, ParseError\n\n\ninput = '(|(name=bob)name=bill))'\n\ntry:\n    Filter.parse(input)\nexcept ParseError as e:\n    print(e)\n```\n\n*Error Output:*\n\n```\nLine 1: expected [\\x20], [\\x09], \"\\r\\n\", \"\\n\", '(', ')'\n(|(name=bob)name=bill)\n            ^\n```\n\n## Simplifying Filters ##\n\nThe `Filter.simplify()` method can be used to eliminate unnecessary AND/OR filters that only have one child node.\n\n``` python\ninput = '(&(name=bob))'\ncomplex = Filter.parse(input)\n\nprint(complex.simplify())  # (name=bob)\n```\n\n## Filter Output ##\n\nThere are a few options for getting a string output from your `Filter` object with optional custom formatting.\n\n### Simple String ###\n\nYou 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.\n\n``` python\noutput = Filter.AND([\n    Filter.attribute('name').equal_to('bob'),\n    Filter.attribute('mail').ends_with('@example.com'),\n])\n\n# Filter.to_string() output.\nprint(output.to_string())  # (&(name=bob)(mail=*@example.com))\n\n# Typecast output.\nprint(str(output)) # (&(name=bob)(mail=*@example.com))\n\n# String concatenate output\nprint('LDAP Filter: ' + output) # LDAP Filter: (&(name=bob)(mail=*@example.com))\n```\n\n### Beautified String ###\n\nThe `Filter.to_string()` method provides additional formatting options to produce beautified filter strings.\n\nYou can get the default beautified format by passing `True` to the `Filter.to_string(indent)` method\n\n``` python\noutput = Filter.AND([\n    Filter.attribute('name').equal_to('bob'),\n    Filter.attribute('mail').ends_with('@example.com'),\n    Filter.OR([\n        Filter.attribute('dept').equal_to('accounting'),\n        Filter.attribute('dept').equal_to('operations')\n    ])\n])\n\nprint(output.to_string(True))\n```\n\n*Default Beautified Output:*\n\n```\n(&\n    (name=bob)\n    (mail=*@example.com)\n    (|\n        (dept=accounting)\n        (dept=operations)\n    )\n)\n```\n\nor 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.\n\n``` python\noutput = Filter.AND([\n    Filter.attribute('name').equal_to('bob'),\n    Filter.attribute('mail').ends_with('@example.com'),\n    Filter.OR([\n        Filter.attribute('dept').equal_to('accounting'),\n        Filter.attribute('dept').equal_to('operations')\n    ])\n])\n\nprint(output.to_string(2, '.'))\n```\n\n*Custom Beautified Output:*\n\n```\n(&\n..(name=bob)\n..(mail=*@example.com)\n..(|\n....(dept=accounting)\n....(dept=operations)\n..)\n)\n```\n\n## Filter Matching ##\n\nThe `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).\n\n``` python\nfilt = Filter.AND([\n    Filter.attribute('department').equal_to('accounting'),\n    Filter.NOT(\n        Filter.attribute('status').equal_to('terminated')\n    )\n])\n\nemployee1 = {\n    'name': 'Bob Smith',\n    'department': 'Accounting',\n    'status': 'Active'\n}\n\nprint(filt.match(employee1))  # True\n\nemployee2 = {\n    'name': 'Jane Brown',\n    'department': 'Accounting',\n    'status': 'Terminated'\n}\n\nprint(filt.match(employee2))  # False\n\nemployee3 = {\n    'name': 'Bob Smith',\n    'department': 'Marketing',\n    'status': 'Active'\n}\n\nprint(filt.match(employee3))  # False\n\n```\n\n# Unit Tests\n\nIn order to run the test suite the pytest library is required. You can install pytest by running:\n\n``` bash\npip install pytest\n```\n\nTo run the unit tests simply type `pytest` in the projects root directory\n\n# Home Page\n\nProject home page is https://github.com/SteveEwell/python-ldap-filter\n\n# License\n\nThe **Python LDAP Filter** project is open source software released under the [MIT licence](https://en.wikipedia.org/wiki/MIT_License). Copyright 2024 Stephen Ewell\n",
    "bugtrack_url": null,
    "license": "The MIT License (MIT)  Copyright (c) 2018 Stephen Ewell  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
    "summary": "A Python utility library for working with Lightweight Directory Access Protocol (LDAP) filters.",
    "version": "1.0.1",
    "project_urls": {
        "Homepage": "https://github.com/SteveEwell/python-ldap-filter"
    },
    "split_keywords": [
        "ldap",
        " filter",
        " rfc4515",
        " utility",
        " development"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d1d4f2213e236d78937e2636dcf7d40cdaf6cdd53e760415512e1302677022c4",
                "md5": "cf1b8b03a5e9d20923e5b3b4bcdb06b1",
                "sha256": "d0691b58d7fc867e3c24663122773e7ebccdda35b2f35caa9bff30357a9807ab"
            },
            "downloads": -1,
            "filename": "ldap_filter-1.0.1-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "cf1b8b03a5e9d20923e5b3b4bcdb06b1",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": ">=3.4",
            "size": 12936,
            "upload_time": "2024-10-22T21:25:00",
            "upload_time_iso_8601": "2024-10-22T21:25:00.130741Z",
            "url": "https://files.pythonhosted.org/packages/d1/d4/f2213e236d78937e2636dcf7d40cdaf6cdd53e760415512e1302677022c4/ldap_filter-1.0.1-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "356c54b3c28c1431c7c64c4b610fb5c83721a5598a59f38c59a45db9518a80b1",
                "md5": "7fb577d3a066a5a3e5aae510298a00c4",
                "sha256": "b0b0b51ff8b681459dc9cb958c1238cb941b39d03280213c2d1f2cd142acbedf"
            },
            "downloads": -1,
            "filename": "ldap_filter-1.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "7fb577d3a066a5a3e5aae510298a00c4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.4",
            "size": 17735,
            "upload_time": "2024-10-22T21:25:01",
            "upload_time_iso_8601": "2024-10-22T21:25:01.317275Z",
            "url": "https://files.pythonhosted.org/packages/35/6c/54b3c28c1431c7c64c4b610fb5c83721a5598a59f38c59a45db9518a80b1/ldap_filter-1.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-10-22 21:25:01",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "SteveEwell",
    "github_project": "python-ldap-filter",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": false,
    "tox": true,
    "lcname": "ldap-filter"
}
        
Elapsed time: 0.34001s