This commit is a fairly large chunk of code that fixes a previously
annoying and nasty bug causing cached_properties to not be cleared.
Alongside this bug fix I took the opportunity to refactor the entire
methdology behind cached properties, and bind them more strictly to the
behavior of models.
Prior to this commit, cached_properties where not be properly reset upon
a model's `update` method being called due to some invalid code. Along
with this issue, the actual behavior of cached properties landed in a
weird in-between/gray area where they had to support both non-model and
model use cases.
The new version of cached_property is strictly for use with models, and
another version `simple_cached_property` was added to support other use
cases. The new cached_property simply builds an actual `property` within
the metaclass. This is fairly efficient, and also reduces the surface
area of behavior.
When writing this I messed around with a few ideas, including allowing
the user of `cached_property` to define a linkage between the property
and fields that should invalidate its cached value, but this was both
messy and introduced massive cognitive load on understand when a
cached_property should be cleared. Although this version is slighty less
efficient, I'm very much in favor of it vs the alternatives I tried.
For some reason when I initially built disco I made these types binary.
They are not binary. They are ascii hash-strings. So lets make them
strings. This fixes the Python 3 oddities described in #29 related to
formatting byte strings into normal strings.
This naming scheme was garbage and always tripped me up. In favor of
having a more intuitive (and less _technically_ correct) interface,
we'll swap the name up.
There where various oddities and bugs here, namely:
- Guild kept its initial `presences` list even though this is basically
useless, and was never kept up-to-date
- State did not properly use all the fields of presence_update, and was
creating some annoying recursive oddities w/ user and presence binding
GUILD_UPDATES are cool and special and of course they are partial.
Although this is logical, our type/models autoinitialize some fields by
default (which is actually fairly sane). However when this happens, we
smash these new blank mappings over the previously updated state.
Instead we should just ignore fields that don't come in GUILD_UPDATEs,
and save our state.