spulec / freezegun

Let your Python tests travel through time
Apache License 2.0
4.14k stars 267 forks source link

consider overriding == on FakeDatetimeMeta #549

Open kurtbrose opened 2 months ago

kurtbrose commented 2 months ago

I just spent an hour debugging a weird interaction with datetime != datetime the first time a particular branch of code got run inside a freezegun block.

My fix (after much fiddling around) was issubclass(type_, datetime) instead of type_ == datetime.

I notice that FakeDatetimeMeta overrides __instancecheck__ and __subclasscheck__ to appear to be a datetime. Has it also been discussed overriding __eq__?

Here's what the class would look like with the new method: https://github.com/spulec/freezegun/blob/master/freezegun/api.py#L355-L362

class FakeDatetimeMeta(FakeDateMeta):
    @classmethod
    def __instancecheck__(self, obj: Any) -> bool:
        return isinstance(obj, real_datetime)

    @classmethod
    def __subclasscheck__(cls, subclass: Any) -> bool:
        return issubclass(subclass, real_datetime)

   def __eq__(cls, other: type) -> bool:
        return other is cls or other is real_datetime

Here's fiddling around at the REPL to double-check overriding __eq__ on a metaclass works as expected (at least in newer Python 3):

>>> class Meta(type):
...     def __eq__(self, other): return True
... 
>>> class SameAsEverything(metaclass=Meta): pass
... 
>>> SameAsEverything == int
True
kurtbrose commented 2 months ago

I did a quick search but didn't find any prior issues on this topic. If this is a repeat, maybe it would be a good idea to add a comment or docstring explaining why overriding __eq__ is hard? (Maybe it breaks with older python?)

kurtbrose commented 2 months ago

Also, thanks very much for maintaining this open source library! I appreciate your generosity.