No project description provided
Project description
SpeciPy
SpeciPy simplifies the implementation of the Specification pattern in Python, enabling easy creation and evaluation of flexible rules and criteria.
📋 Table of Contents
📥 Installation
To install Interpy with pip, you can use the following command:
pip install specipy
If you are using poetry you can use the command:
poetry add specipy
🚀 Usage
SpeciPy provides a clean and powerful implementation of the Specification Pattern in Python. It helps you encapsulate business rules or filtering logic in a reusable and composable way.
Below are practical examples of how to use specipy in real-world scenarios:
Defining and using a simple specification
from specipy import Specification
class IsEven(Specification):
def is_satisfied_by(self, candidate: int) -> bool:
return candidate % 2 == 0
spec = IsEven()
print(spec.is_satisfied_by(4)) # True
print(spec.is_satisfied_by(7)) # False
Combining specifications with boolean logic
from specipy import Specification
class IsEven(Specification):
def is_satisfied_by(self, candidate):
return candidate % 2 == 0
class IsPositive(Specification):
def is_satisfied_by(self, candidate):
return candidate > 0
spec = IsEven() & IsPositive()
print(spec.is_satisfied_by(4)) # True (even and positive)
print(spec.is_satisfied_by(-2)) # False (even but negative)
print(spec.is_satisfied_by(3)) # False (odd)
You can also use | for OR and ~ for NOT:
spec = IsEven() | IsPositive()
print(spec.is_satisfied_by(-3)) # False
print(spec.is_satisfied_by(3)) # True
Filtering collections with specifications
from specipy import filter_by_spec, Specification
class StartsWithA(Specification):
def is_satisfied_by(self, candidate):
return candidate.lower().startswith("a")
names = ["Alice", "Bob", "anna", "Charles"]
spec = StartsWithA()
filtered = filter_by_spec(names, spec)
print(list(filtered)) # ['Alice', 'anna']
Validating complex domain rules
class HasBalance(Specification):
def is_satisfied_by(self, account):
return account.balance > 0
class IsActive(Specification):
def is_satisfied_by(self, account):
return account.active
class Account:
def __init__(self, balance, active):
self.balance = balance
self.active = active
account = Account(balance=100, active=True)
spec = HasBalance() & IsActive()
print(spec.is_satisfied_by(account)) # True
This allows rules to be isolated, tested independently, and composed into more complex conditions.
Dynamic one-off specifications with lambdas
from specipy import lambda_spec
is_even = lambda_spec(lambda x: x % 2 == 0)
print(is_even.is_satisfied_by(10)) # True
Perfect for quick filters or dynamic rule creation without declaring classes.
📈 Roadmap / Future Goals
We plan to continue growing specipy into a robust, developer-friendly tool for business rule modeling. Some ideas we plan to explore:
✅ Planned Features
-
__str__ / __repr__for debugging Clearer and descriptive output when printing specifications, like:print(GreaterThanSpecification(10)) # Output: GreaterThanSpecification(10)
-
all_satisfied(specs) / any_satisfied(specs) Allows you to combine multiple specifications from a list dynamically:
specs = [ lambda_spec(lambda x: x > 10), lambda_spec(lambda x: x % 2 == 0), ] assert all_satisfied(specs)(12) # True assert any_satisfied(specs)(9) # False
-
spec.as_predicate() method Converts a specification into a simple callable predicate (function returning bool), making it easy to integrate with native Python functions like filter(), map(), or any functional programming context.
spec = GreaterThanSpecification(5) list(filter(spec.as_predicate(), [1, 6, 8])) # [6, 8]
🤝 Contributing
Specipy is designed to grow with the community. If you have ideas for new features, improvements, or bug fixes, we warmly welcome your contributions! Feel free to open issues, discuss enhancements, or submit pull requests. Together, we can make this library even more powerful and developer-friendly.
If you would like to contribute to Specipy, please follow these steps:
- Fork the repository
git clone git@github.com:danieljoris/specipy.git - Create a branch for your feature
git checkout -b feature/your-feature - Commit your changes
git commit -m 'Add your feature - Push to the branch
git push origin feature/your-feature - Open a Pull Request
📜 License
This project is licensed under the MIT License. See the LICENSE file for more details.
📧 Contact
Feel free to adjust and add more features as needed. If you need anything more specific or additional adjustments, let me know!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file specipy-0.1.2.tar.gz.
File metadata
- Download URL: specipy-0.1.2.tar.gz
- Upload date:
- Size: 4.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a0c2168b4374d61a116543668be2e52dd692ec2650f64de562a69e779edc3e8
|
|
| MD5 |
e69bcfd80f50843d9952194f1376f136
|
|
| BLAKE2b-256 |
4f2afa0af8f9ca41bf4604c0c94b73759b11aec9c22582134a9706309fd2bb95
|
File details
Details for the file specipy-0.1.2-py3-none-any.whl.
File metadata
- Download URL: specipy-0.1.2-py3-none-any.whl
- Upload date:
- Size: 5.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30ff3592d851cea5005f7516f24b35c16b9d7f54e83b5cc23948bf5f5a33703a
|
|
| MD5 |
aa66ef35a0dfdf13233edf56ea830dc4
|
|
| BLAKE2b-256 |
f3494ea5f52b9b966aef60f0e78f906814475d5378829f60fa3e3277fb595f97
|