Skip to main content

🔍 pfylter PyPI GitHub

pfylter is a lightweight, flexible, and extensible Python framework for applying composable filters to arbitrary data. It’s built using the composite design pattern, allowing complex logical conditions to be expressed and reused cleanly.


📑 Table of Contents


🚀 Features

  • ✅ Define your own filters by subclassing AbstractFilter
  • ✅ Combine filters using logical AND (AllFilters) or OR (AnyFilter)
  • ✅ Support for generic data types (strings, numbers, objects, etc.)
  • ✅ Clean, readable syntax using list comprehensions and type hints
  • ✅ Perfect for data processing, rule engines, and validation pipelines

📦 Installation

pip install pfylter

✨ Quick Start

These simple examples with number uses the LambdaFilter class to build filters based on lambda functions.

Let's start with a simple filter to get numbers greater than 5 or it's oposite condition using NotFilter.

from pfylter.core import LambdaFilter, NotFilter, AllFilters, AnyFilter

example = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

print('Numbers greater than 5:')
print(LambdaFilter(lambda x: x > 5).apply(example))  # [6, 7, 8, 9, 10]

print('Numbers equal or lower than 5:')
print(NotFilter(LambdaFilter(lambda x: x > 5)).apply(example))  # [1, 2, 3, 4, 5]

Now, use AllFilters and AnyFilter to create filters by aggregating other filters. When AllFilters is used, only elements that meet all filters in the list are kept.

print('Numbers greater than 5 and divisible by two:')
print(AllFilters([
    LambdaFilter(lambda x: x > 5),
    LambdaFilter(lambda x: x % 2 == 0)
]).apply(example))  # [6, 8, 10]

print('Numbers greater than 5 and divisible by three:')
print(AllFilters([
    LambdaFilter(lambda x: x > 5),
    LambdaFilter(lambda x: x % 3 == 0)
]).apply(example))  # [6, 9]

When AnyFilter, elements that meet any of the filters in the list are kept (i.e. meet any of the filters is enough to be in the output).

print('Numbers greater than 5 or divisible by two:')
print(AnyFilter([
    LambdaFilter(lambda x: x > 5),
    LambdaFilter(lambda x: x % 2 == 0)
]).apply(example))  # [2, 4, 6, 7, 8, 9, 10]

🧩 Predefined String Filters

The pfylter.strings module provides ready-to-use filters for common string operations:

  • LenFilter(length): keeps strings of a given length.
  • LengthRangeFilter(min, max): keeps strings of length within the specified range.
  • EndsWithFilter(prefix): keeps strings that start with a prefix.
  • StartsWithFilter(prefix): keeps strings that end with a prefix.
  • ContainsFilter(substring): keeps strings that contain a substring.
  • RegexFilter(substring): keeps strings that match the specified regular expression.

Starting with a list of strings, here we have some uses of these basic filters.

from pfylter.strings import LenFilter, StartsWithFilter, ContainsFilter, NotFilter
from pfylter.core import AllFilters, AnyFilter

example = ['A', 'ABCD', 'B', 'BCDE', 'C', 'AAAAAAA']

print('Strings containing "BC":')
print(ContainsFilter('BC').apply(example))

print('Strings with length one:')
print(LenFilter(1).apply(example))

print('Strings with length different than one:')
print(NotFilter(LenFilter(1)).apply(example))

print('Strings with length four and starting with "A":')
print(AllFilters([LenFilter(4), StartsWithFilter('A')]).apply(example))  

print('Strings with length four or starting with "A":')
print(AnyFilter([LenFilter(4), StartsWithFilter('A')]).apply(example))

More complex filters can be created creating an AnyFilter with two AllFilters objects to output all strings that either have length four and start with "A" or have length one and start with "B".

print('Strings with length four and starting with "A" or length one and starting with "B":')
print(AnyFilter([
    AllFilters([LenFilter(4), StartsWithFilter('A')]),
    AllFilters([LenFilter(1), StartsWithFilter('B')])
]).apply(example))  # ['ABCD', 'B']

Finally, the NotFilter can be combined with AllFilters or AnyFilter to create exclusion filters. These two examples are equivalent and allow excluding strings that contain "BC" (this excludes "ABCD" and "BCDE") or have length 1 (this excludes "A", "B, and "C").

print('Exclude any string that includes BC or has length 1 (using AllFilters):')
print(AllFilters([NotFilter(LenFilter(1)), NotFilter(ContainsFilter('BC'))]).apply(example))  # ['AAAAAAA']

print('Exclude any string that includes BC or has length 1 (using AnyFilter):')
print(NotFilter(AnyFilter([ContainsFilter('BC'), LenFilter(1)])).apply(example))  # ['AAAAAAA']

🛠 Creating Custom Filters

You can define custom filters by inheriting from AbstractFilter:

from pfylter import AbstractFilter

class GreaterThanFilter(AbstractFilter[int]):
    def __init__(self, threshold: int):
        self.threshold = threshold

    def keep(self, instance: int) -> bool:
        return instance > self.threshold

Now you can use this filter in combination with others!


📝 License

MIT License — see LICENSE file for details.


🤝 Contributing

Feel free to open issues or pull requests. All feedback is welcome!

Metadata

Release files for pfylter 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pfylter 0.3.0
File Size Uploaded
pfylter-0.3.0.tar.gz 5.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pfylter 0.3.0
File Interpreter ABI Platform
pfylter-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 11.1 kB

Release files / pfylter-0.3.0.tar.gz

Download URL pfylter-0.3.0.tar.gz
Size 5.5 kB
Tags Source
SHA-256 checksum
How to use checksums
da7f56c79ff439ff0b597d7025218f13bf7b49bdeffba9a972ba05655ef8e72c
BLAKE2b-256 checksum
How to use checksums
7599b91c83b4e7b91636137109f25e50f18c1ce7992a1ffdece624f931e410b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.12

Release files / pfylter-0.3.0-py3-none-any.whl

Download URL pfylter-0.3.0-py3-none-any.whl
Size 5.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0a0dfe2febc4a828cc83fa747aecdb8e5db8bb75da27204328779946833160d3
BLAKE2b-256 checksum
How to use checksums
c918015e8c2a11c5284c64c01c9872c4c8c495d0fb7b26dc3ac6c6d1f67fd735
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.11.12

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page