How to make a singleton?
Before, the following used to work.
_singleton_insts: dict[type, object] = {}
class SingletonMixin:
"""Singleton class.
This class is a mixin that can be used to create singletons.
Examples
--------
>>> class MySingleton(SingletonMixin):
... pass
>>> a = MySingleton()
>>> b = MySingleton()
>>> a is b
True
"""
def __new__(cls, /, *_: Any, **__: Any) -> "Self":
# Check if instance already exists
if cls in _singleton_insts:
return cast("Self", _singleton_insts[cls])
# Create new instance and cache it
self = object.__new__(cls)
_singleton_insts[cls] = self
return self
Now the _is_initializing checker calls .remove() but this errors because the singleton's __new__ bypasses the initialization process.
Is there a better pattern I should be using, or should I push a PR so that .remove() doesn't error if the id hash isn't present?
This is Hyrum's law at its finest 😄
So I wonder if the correct choice here would be for you to override the metaclass instead? As it is you'll still be paying the overhead of __check_init__, and/or subject to whatever else type(Module).__call__ may end up with over time. (Although realistically it's probably stable now.)
If that doesn't work for any reason then I agree your solution sounds reasonable :)
Any chance you'd accept a PR for ModuleMeta to implement a singleton class argument?
class MyModule(Module, singleton=True): ...
I think probably not I'm afraid – that this niche enough that it's better for users to provide their own implementation. :)
Fair. Then I'll probably make a micro-library called Oncequinox that vendors just the metaclass subclass.
The ~subclass~ metaclass is private. Any way it can be made public? Maybe in internal?
Guesing you mean the metaclass - in this case then type(eqx.Module) might be what you're after?
I suppose I could try
ModuleMeta: type[type[eqx.Module]] = type(eqx.Module)
to try to make static checkers happy, but in general type(eqx.Module) will not.
https://pypi.org/project/oncequinox/
https://github.com/patrick-kidger/equinox/pull/1135