test_singleton.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. from sympy.core.basic import Basic
  2. from sympy.core.numbers import Rational
  3. from sympy.core.singleton import S, Singleton
  4. def test_Singleton():
  5. class MySingleton(Basic, metaclass=Singleton):
  6. pass
  7. MySingleton() # force instantiation
  8. assert MySingleton() is not Basic()
  9. assert MySingleton() is MySingleton()
  10. assert S.MySingleton is MySingleton()
  11. class MySingleton_sub(MySingleton):
  12. pass
  13. MySingleton_sub()
  14. assert MySingleton_sub() is not MySingleton()
  15. assert MySingleton_sub() is MySingleton_sub()
  16. def test_singleton_redefinition():
  17. class TestSingleton(Basic, metaclass=Singleton):
  18. pass
  19. assert TestSingleton() is S.TestSingleton
  20. class TestSingleton(Basic, metaclass=Singleton):
  21. pass
  22. assert TestSingleton() is S.TestSingleton
  23. def test_names_in_namespace():
  24. # Every singleton name should be accessible from the 'from sympy import *'
  25. # namespace in addition to the S object. However, it does not need to be
  26. # by the same name (e.g., oo instead of S.Infinity).
  27. # As a general rule, things should only be added to the singleton registry
  28. # if they are used often enough that code can benefit either from the
  29. # performance benefit of being able to use 'is' (this only matters in very
  30. # tight loops), or from the memory savings of having exactly one instance
  31. # (this matters for the numbers singletons, but very little else). The
  32. # singleton registry is already a bit overpopulated, and things cannot be
  33. # removed from it without breaking backwards compatibility. So if you got
  34. # here by adding something new to the singletons, ask yourself if it
  35. # really needs to be singletonized. Note that SymPy classes compare to one
  36. # another just fine, so Class() == Class() will give True even if each
  37. # Class() returns a new instance. Having unique instances is only
  38. # necessary for the above noted performance gains. It should not be needed
  39. # for any behavioral purposes.
  40. # If you determine that something really should be a singleton, it must be
  41. # accessible to sympify() without using 'S' (hence this test). Also, its
  42. # str printer should print a form that does not use S. This is because
  43. # sympify() disables attribute lookups by default for safety purposes.
  44. d = {}
  45. exec('from sympy import *', d)
  46. for name in dir(S) + list(S._classes_to_install):
  47. if name.startswith('_'):
  48. continue
  49. if name == 'register':
  50. continue
  51. if isinstance(getattr(S, name), Rational):
  52. continue
  53. if getattr(S, name).__module__.startswith('sympy.physics'):
  54. continue
  55. if name in ['MySingleton', 'MySingleton_sub', 'TestSingleton']:
  56. # From the tests above
  57. continue
  58. if name == 'NegativeInfinity':
  59. # Accessible by -oo
  60. continue
  61. # Use is here to ensure it is the exact same object
  62. assert any(getattr(S, name) is i for i in d.values()), name