Remix.run Logo
pbalau 42 minutes ago

if self._midnight(today) returns a datetime object, than:

   self.filter(end__gt=self._midnight(today))
will evaluate to:

   self.filter(end__gt=<some_datetime_object>)

While

    self.filter(Field.end > self._midnight(today))
will evaluate to:

   self.filter(<True/False>)
echoangle 19 minutes ago | parent [-]

Not if you do the magic with getattr and comparison overrides. You actually need to do it on the metaclass because the Field as I wrote it isn't an instance but this works:

    from datetime import datetime

    class Filter():
        def __init__(self, name):
            self.name = name
        def __gt__(self, value):
            return {
                "field": self.name,
                "operator": ">",
                "value": value
            }

    class FieldMeta(type):
        def __getattr__(cls, name):
            return Filter(name)

    class Field(metaclass=FieldMeta):
        pass

    print(Field.end > datetime(2024, 1, 1))
This gives:

    {'field': 'end', 'operator': '>', 'value': datetime.datetime(2024, 1, 1, 0, 0)}
You can make python return arbitrary values for comparisons by overriding __gt__ (and lt, eq) on the first operand (which we control here since it is a Field class), it doesn't have to be a bool.

Edit:

You can even make a little adapter to use this with the current filter system if you really want to:

    from datetime import datetime

    class Filter():
        def __init__(self, name):
            self.name = name
        def __gt__(self, value):
            return {
                "field": self.name,
                "operator": "gt",
                "value": value
            }
        
        def __lt__(self, value):
            return {
                "field": self.name,
                "operator": "lt",
                "value": value
            }
        
        def __eq__(self, value):
            return {
                "field": self.name,
                "operator": "eq",
                "value": value
            }

    class FieldMeta(type):
        def __getattr__(cls, name):
            return Filter(name)

    class Field(metaclass=FieldMeta):
        pass

    def _(*args):
        kwargs = {}
        for arg in args:
            k = arg["field"] + "__" + arg["operator"]
            kwargs[k] = arg["value"]
        return kwargs

    def filter(**kwargs):
        for k, v in kwargs.items():
            print(f"{k} = {v}")

    filter(**_(Field.end > datetime(2024, 1, 1)))
This prints

end__gt = 2024-01-01 00:00:00