12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- from sympy.core.basic import Basic
- from sympy.core.numbers import Rational
- from sympy.core.singleton import S, Singleton
- def test_Singleton():
- class MySingleton(Basic, metaclass=Singleton):
- pass
- MySingleton() # force instantiation
- assert MySingleton() is not Basic()
- assert MySingleton() is MySingleton()
- assert S.MySingleton is MySingleton()
- class MySingleton_sub(MySingleton):
- pass
- MySingleton_sub()
- assert MySingleton_sub() is not MySingleton()
- assert MySingleton_sub() is MySingleton_sub()
- def test_singleton_redefinition():
- class TestSingleton(Basic, metaclass=Singleton):
- pass
- assert TestSingleton() is S.TestSingleton
- class TestSingleton(Basic, metaclass=Singleton):
- pass
- assert TestSingleton() is S.TestSingleton
- def test_names_in_namespace():
- # Every singleton name should be accessible from the 'from sympy import *'
- # namespace in addition to the S object. However, it does not need to be
- # by the same name (e.g., oo instead of S.Infinity).
- # As a general rule, things should only be added to the singleton registry
- # if they are used often enough that code can benefit either from the
- # performance benefit of being able to use 'is' (this only matters in very
- # tight loops), or from the memory savings of having exactly one instance
- # (this matters for the numbers singletons, but very little else). The
- # singleton registry is already a bit overpopulated, and things cannot be
- # removed from it without breaking backwards compatibility. So if you got
- # here by adding something new to the singletons, ask yourself if it
- # really needs to be singletonized. Note that SymPy classes compare to one
- # another just fine, so Class() == Class() will give True even if each
- # Class() returns a new instance. Having unique instances is only
- # necessary for the above noted performance gains. It should not be needed
- # for any behavioral purposes.
- # If you determine that something really should be a singleton, it must be
- # accessible to sympify() without using 'S' (hence this test). Also, its
- # str printer should print a form that does not use S. This is because
- # sympify() disables attribute lookups by default for safety purposes.
- d = {}
- exec('from sympy import *', d)
- for name in dir(S) + list(S._classes_to_install):
- if name.startswith('_'):
- continue
- if name == 'register':
- continue
- if isinstance(getattr(S, name), Rational):
- continue
- if getattr(S, name).__module__.startswith('sympy.physics'):
- continue
- if name in ['MySingleton', 'MySingleton_sub', 'TestSingleton']:
- # From the tests above
- continue
- if name == 'NegativeInfinity':
- # Accessible by -oo
- continue
- # Use is here to ensure it is the exact same object
- assert any(getattr(S, name) is i for i in d.values()), name
|