Last active
November 2, 2016 09:10
-
-
Save malexer/2593c2e945e94c2f3d4f54212cbbc010 to your computer and use it in GitHub Desktop.
Trying to reimplement SQLAlchemy's query.filter magic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# after using SQLAlchemy I've decided to try my python skills in coding it's filter function magic | |
# without looking into their source code, just for fun | |
# Note: it's not complete, just proof of concept | |
class BindProperty(type): | |
def __new__(cls, name, bases, namespace, **kwds): | |
result = type.__new__(cls, name, bases, dict(namespace)) | |
for name, value in namespace.items(): | |
if isinstance(value, Property): | |
value._update_attribute_name(name) | |
return result | |
class Condition(object): | |
def __init__(self, property_name): | |
self.property_name = property_name | |
def __gt__(self, other): | |
return lambda instance: getattr(instance, self.property_name) > other | |
def __eq__(self, other): | |
return lambda instance: getattr(instance, self.property_name) == other | |
class Property(object): | |
def _update_attribute_name(self, property_name): | |
self.instance_attribute_name = '_%s' % property_name | |
self.condition_checker = Condition(property_name) | |
def __get__(self, instance, owner): | |
if instance is None: | |
return self.condition_checker | |
else: | |
return getattr(instance, self.instance_attribute_name, None) | |
def __set__(self, instance, value): | |
setattr(instance, self.instance_attribute_name, value) | |
class User(object, metaclass=BindProperty): | |
name = Property() | |
age = Property() | |
def __init__(self, name, age): | |
self.name = name | |
self.age = age | |
def __repr__(self): | |
return '<User(name="%s", age=%s)>' % (self.name, self.age) | |
def where(items, *conditions): | |
return [ | |
item for item in items | |
if all([c(item) for c in conditions]) | |
] | |
users = ( | |
User('Alex', 19), | |
User('John', 21), | |
User('Mark', 25), | |
User('John', 15), | |
) | |
print('Source:', users) | |
filtered1 = where(users, User.name == 'John') | |
print('filtered1:', filtered1) | |
filtered2 = where(users, User.age > 18) | |
print('filtered2:', filtered2) | |
filtered3 = where(users, User.name == 'John', User.age > 20) | |
print('filtered3:', filtered3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment