hashing of FontProperties

The following code show how the FontProperties is currently hashed.

     def __hash__(self):
        l = self.__dict__.items()
        l.sort()
        return hash(repr(l))

The hash does not account user's rcParams setting. And due to the font
caching, findfont(FontProperties()) returns the same font even if user
changes the rcParams["font.family"] and other parameters.

So, I propose to change it to something like below.

    def __hash__(self):
        l = [(k, getattr(self, "get" + k)()) for k in self.__dict__]
        return hash(repr(l))

The other change I want to make is the behavior of the findfont(None).
As of now, it returns "fontManager.defaultFont" which is set when
fontManager is initialized. Therefore, it returns same font even if
user change the rcParams. I prefer to have "findfont(None) ==
findfont(FontProperties())".

Unless others object, I'll commit the changes to the trunk.

Regards,

-JJ

Jae-Joon Lee wrote:

The following code show how the FontProperties is currently hashed.

     def __hash__(self):
        l = self.__dict__.items()
        l.sort()
        return hash(repr(l))

The hash does not account user's rcParams setting. And due to the font
caching, findfont(FontProperties()) returns the same font even if user
changes the rcParams["font.family"] and other parameters.

So, I propose to change it to something like below.

    def __hash__(self):
        l = [(k, getattr(self, "get" + k)()) for k in self.__dict__]
        return hash(repr(l))
  

You'll need to maintain the call to sort in there, since dictionaries don't make any guarantee about ordering. But otherwise, that seems like a reasonable solution to the problem. There was a bug report about this on the list recently.

The other change I want to make is the behavior of the findfont(None).
As of now, it returns "fontManager.defaultFont" which is set when
fontManager is initialized. Therefore, it returns same font even if
user change the rcParams. I prefer to have "findfont(None) ==
findfont(FontProperties())".
  

That should be fine.

Unless others object, I'll commit the changes to the trunk.
  

Sure. Just be careful not to change the pickled cache file format if possible (it doesn't seem like what you propose will do that) -- but that always causes upgrade headaches when that cache format changes.

Mike