passagemath-objects 10.6.41__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. passagemath_objects/__init__.py +3 -0
  2. passagemath_objects-10.6.41.dist-info/DELVEWHEEL +2 -0
  3. passagemath_objects-10.6.41.dist-info/METADATA +115 -0
  4. passagemath_objects-10.6.41.dist-info/RECORD +281 -0
  5. passagemath_objects-10.6.41.dist-info/WHEEL +5 -0
  6. passagemath_objects-10.6.41.dist-info/top_level.txt +3 -0
  7. passagemath_objects.libs/libgmp-10-79b4110c7ea2b760f16cfef97e8a8a34.dll +0 -0
  8. sage/all__sagemath_objects.py +46 -0
  9. sage/arith/all__sagemath_objects.py +5 -0
  10. sage/arith/long.pxd +411 -0
  11. sage/arith/numerical_approx.cp312-win_amd64.pyd +0 -0
  12. sage/arith/numerical_approx.pxd +35 -0
  13. sage/arith/numerical_approx.pyx +75 -0
  14. sage/arith/power.cp312-win_amd64.pyd +0 -0
  15. sage/arith/power.pxd +31 -0
  16. sage/arith/power.pyx +127 -0
  17. sage/categories/action.cp312-win_amd64.pyd +0 -0
  18. sage/categories/action.pxd +29 -0
  19. sage/categories/action.pyx +641 -0
  20. sage/categories/algebra_functor.py +745 -0
  21. sage/categories/all__sagemath_objects.py +33 -0
  22. sage/categories/basic.py +71 -0
  23. sage/categories/cartesian_product.py +295 -0
  24. sage/categories/category.py +3401 -0
  25. sage/categories/category_cy_helper.cp312-win_amd64.pyd +0 -0
  26. sage/categories/category_cy_helper.pxd +8 -0
  27. sage/categories/category_cy_helper.pyx +322 -0
  28. sage/categories/category_singleton.cp312-win_amd64.pyd +0 -0
  29. sage/categories/category_singleton.pxd +3 -0
  30. sage/categories/category_singleton.pyx +342 -0
  31. sage/categories/category_types.py +637 -0
  32. sage/categories/category_with_axiom.py +2885 -0
  33. sage/categories/covariant_functorial_construction.py +703 -0
  34. sage/categories/facade_sets.py +228 -0
  35. sage/categories/functor.cp312-win_amd64.pyd +0 -0
  36. sage/categories/functor.pxd +7 -0
  37. sage/categories/functor.pyx +691 -0
  38. sage/categories/homset.py +1338 -0
  39. sage/categories/homsets.py +364 -0
  40. sage/categories/isomorphic_objects.py +73 -0
  41. sage/categories/map.cp312-win_amd64.pyd +0 -0
  42. sage/categories/map.pxd +34 -0
  43. sage/categories/map.pyx +2112 -0
  44. sage/categories/morphism.cp312-win_amd64.pyd +0 -0
  45. sage/categories/morphism.pxd +14 -0
  46. sage/categories/morphism.pyx +895 -0
  47. sage/categories/objects.py +167 -0
  48. sage/categories/primer.py +1696 -0
  49. sage/categories/pushout.py +4834 -0
  50. sage/categories/quotients.py +64 -0
  51. sage/categories/realizations.py +200 -0
  52. sage/categories/sets_cat.py +3228 -0
  53. sage/categories/sets_with_partial_maps.py +52 -0
  54. sage/categories/subobjects.py +64 -0
  55. sage/categories/subquotients.py +21 -0
  56. sage/categories/with_realizations.py +311 -0
  57. sage/cpython/__init__.py +28 -0
  58. sage/cpython/_py2_random.py +619 -0
  59. sage/cpython/all.py +3 -0
  60. sage/cpython/atexit.cp312-win_amd64.pyd +0 -0
  61. sage/cpython/atexit.pyx +269 -0
  62. sage/cpython/builtin_types.cp312-win_amd64.pyd +0 -0
  63. sage/cpython/builtin_types.pyx +7 -0
  64. sage/cpython/cython_metaclass.cp312-win_amd64.pyd +0 -0
  65. sage/cpython/cython_metaclass.h +117 -0
  66. sage/cpython/cython_metaclass.pxd +3 -0
  67. sage/cpython/cython_metaclass.pyx +130 -0
  68. sage/cpython/debug.cp312-win_amd64.pyd +0 -0
  69. sage/cpython/debug.pyx +302 -0
  70. sage/cpython/dict_del_by_value.cp312-win_amd64.pyd +0 -0
  71. sage/cpython/dict_del_by_value.pxd +9 -0
  72. sage/cpython/dict_del_by_value.pyx +191 -0
  73. sage/cpython/dict_internal.h +245 -0
  74. sage/cpython/getattr.cp312-win_amd64.pyd +0 -0
  75. sage/cpython/getattr.pxd +9 -0
  76. sage/cpython/getattr.pyx +439 -0
  77. sage/cpython/pycore_long.h +97 -0
  78. sage/cpython/pycore_long.pxd +10 -0
  79. sage/cpython/python_debug.h +44 -0
  80. sage/cpython/python_debug.pxd +47 -0
  81. sage/cpython/pyx_visit.h +13 -0
  82. sage/cpython/string.cp312-win_amd64.pyd +0 -0
  83. sage/cpython/string.pxd +76 -0
  84. sage/cpython/string.pyx +34 -0
  85. sage/cpython/string_impl.h +60 -0
  86. sage/cpython/type.cp312-win_amd64.pyd +0 -0
  87. sage/cpython/type.pxd +2 -0
  88. sage/cpython/type.pyx +40 -0
  89. sage/cpython/wrapperdescr.pxd +67 -0
  90. sage/ext/all__sagemath_objects.py +3 -0
  91. sage/ext/ccobject.h +64 -0
  92. sage/ext/cplusplus.pxd +17 -0
  93. sage/ext/mod_int.h +30 -0
  94. sage/ext/mod_int.pxd +24 -0
  95. sage/ext/stdsage.pxd +39 -0
  96. sage/groups/all__sagemath_objects.py +1 -0
  97. sage/groups/group.cp312-win_amd64.pyd +0 -0
  98. sage/groups/group.pxd +14 -0
  99. sage/groups/group.pyx +322 -0
  100. sage/groups/old.cp312-win_amd64.pyd +0 -0
  101. sage/groups/old.pxd +14 -0
  102. sage/groups/old.pyx +219 -0
  103. sage/libs/all__sagemath_objects.py +3 -0
  104. sage/libs/gmp/__init__.py +1 -0
  105. sage/libs/gmp/all.pxd +6 -0
  106. sage/libs/gmp/binop.pxd +23 -0
  107. sage/libs/gmp/misc.pxd +8 -0
  108. sage/libs/gmp/mpf.pxd +88 -0
  109. sage/libs/gmp/mpn.pxd +57 -0
  110. sage/libs/gmp/mpq.pxd +57 -0
  111. sage/libs/gmp/mpz.pxd +202 -0
  112. sage/libs/gmp/pylong.cp312-win_amd64.pyd +0 -0
  113. sage/libs/gmp/pylong.pxd +12 -0
  114. sage/libs/gmp/pylong.pyx +150 -0
  115. sage/libs/gmp/random.pxd +25 -0
  116. sage/libs/gmp/randomize.pxd +59 -0
  117. sage/libs/gmp/types.pxd +53 -0
  118. sage/libs/gmpxx.pxd +19 -0
  119. sage/misc/abstract_method.py +276 -0
  120. sage/misc/all__sagemath_objects.py +43 -0
  121. sage/misc/bindable_class.py +253 -0
  122. sage/misc/c3_controlled.cp312-win_amd64.pyd +0 -0
  123. sage/misc/c3_controlled.pxd +2 -0
  124. sage/misc/c3_controlled.pyx +1402 -0
  125. sage/misc/cachefunc.cp312-win_amd64.pyd +0 -0
  126. sage/misc/cachefunc.pxd +43 -0
  127. sage/misc/cachefunc.pyx +3781 -0
  128. sage/misc/call.py +188 -0
  129. sage/misc/classcall_metaclass.cp312-win_amd64.pyd +0 -0
  130. sage/misc/classcall_metaclass.pxd +14 -0
  131. sage/misc/classcall_metaclass.pyx +599 -0
  132. sage/misc/constant_function.cp312-win_amd64.pyd +0 -0
  133. sage/misc/constant_function.pyx +130 -0
  134. sage/misc/decorators.py +747 -0
  135. sage/misc/fast_methods.cp312-win_amd64.pyd +0 -0
  136. sage/misc/fast_methods.pxd +20 -0
  137. sage/misc/fast_methods.pyx +351 -0
  138. sage/misc/flatten.py +90 -0
  139. sage/misc/fpickle.cp312-win_amd64.pyd +0 -0
  140. sage/misc/fpickle.pyx +177 -0
  141. sage/misc/function_mangling.cp312-win_amd64.pyd +0 -0
  142. sage/misc/function_mangling.pxd +11 -0
  143. sage/misc/function_mangling.pyx +308 -0
  144. sage/misc/inherit_comparison.cp312-win_amd64.pyd +0 -0
  145. sage/misc/inherit_comparison.pxd +5 -0
  146. sage/misc/inherit_comparison.pyx +105 -0
  147. sage/misc/instancedoc.cp312-win_amd64.pyd +0 -0
  148. sage/misc/instancedoc.pyx +331 -0
  149. sage/misc/lazy_attribute.cp312-win_amd64.pyd +0 -0
  150. sage/misc/lazy_attribute.pyx +607 -0
  151. sage/misc/lazy_format.py +135 -0
  152. sage/misc/lazy_import.cp312-win_amd64.pyd +0 -0
  153. sage/misc/lazy_import.pyx +1299 -0
  154. sage/misc/lazy_import_cache.py +36 -0
  155. sage/misc/lazy_list.cp312-win_amd64.pyd +0 -0
  156. sage/misc/lazy_list.pxd +19 -0
  157. sage/misc/lazy_list.pyx +1187 -0
  158. sage/misc/lazy_string.cp312-win_amd64.pyd +0 -0
  159. sage/misc/lazy_string.pxd +7 -0
  160. sage/misc/lazy_string.pyx +546 -0
  161. sage/misc/misc.py +1066 -0
  162. sage/misc/misc_c.cp312-win_amd64.pyd +0 -0
  163. sage/misc/misc_c.pxd +3 -0
  164. sage/misc/misc_c.pyx +766 -0
  165. sage/misc/namespace_package.py +37 -0
  166. sage/misc/nested_class.cp312-win_amd64.pyd +0 -0
  167. sage/misc/nested_class.pxd +3 -0
  168. sage/misc/nested_class.pyx +394 -0
  169. sage/misc/persist.cp312-win_amd64.pyd +0 -0
  170. sage/misc/persist.pyx +1251 -0
  171. sage/misc/prandom.py +418 -0
  172. sage/misc/randstate.cp312-win_amd64.pyd +0 -0
  173. sage/misc/randstate.pxd +30 -0
  174. sage/misc/randstate.pyx +1059 -0
  175. sage/misc/repr.py +203 -0
  176. sage/misc/reset.cp312-win_amd64.pyd +0 -0
  177. sage/misc/reset.pyx +196 -0
  178. sage/misc/sage_ostools.cp312-win_amd64.pyd +0 -0
  179. sage/misc/sage_ostools.pyx +323 -0
  180. sage/misc/sage_timeit.py +276 -0
  181. sage/misc/sage_timeit_class.cp312-win_amd64.pyd +0 -0
  182. sage/misc/sage_timeit_class.pyx +120 -0
  183. sage/misc/sage_unittest.py +637 -0
  184. sage/misc/sageinspect.py +2768 -0
  185. sage/misc/session.cp312-win_amd64.pyd +0 -0
  186. sage/misc/session.pyx +392 -0
  187. sage/misc/superseded.py +557 -0
  188. sage/misc/test_nested_class.py +228 -0
  189. sage/misc/timing.py +264 -0
  190. sage/misc/unknown.py +222 -0
  191. sage/misc/verbose.py +253 -0
  192. sage/misc/weak_dict.cp312-win_amd64.pyd +0 -0
  193. sage/misc/weak_dict.pxd +15 -0
  194. sage/misc/weak_dict.pyx +1231 -0
  195. sage/modules/all__sagemath_objects.py +1 -0
  196. sage/modules/module.cp312-win_amd64.pyd +0 -0
  197. sage/modules/module.pxd +5 -0
  198. sage/modules/module.pyx +329 -0
  199. sage/rings/all__sagemath_objects.py +3 -0
  200. sage/rings/integer_fake.h +22 -0
  201. sage/rings/integer_fake.pxd +55 -0
  202. sage/sets/all__sagemath_objects.py +3 -0
  203. sage/sets/pythonclass.cp312-win_amd64.pyd +0 -0
  204. sage/sets/pythonclass.pxd +9 -0
  205. sage/sets/pythonclass.pyx +247 -0
  206. sage/structure/__init__.py +13 -0
  207. sage/structure/all.py +30 -0
  208. sage/structure/category_object.cp312-win_amd64.pyd +0 -0
  209. sage/structure/category_object.pxd +28 -0
  210. sage/structure/category_object.pyx +1087 -0
  211. sage/structure/coerce.cp312-win_amd64.pyd +0 -0
  212. sage/structure/coerce.pxd +44 -0
  213. sage/structure/coerce.pyx +2107 -0
  214. sage/structure/coerce_actions.cp312-win_amd64.pyd +0 -0
  215. sage/structure/coerce_actions.pxd +27 -0
  216. sage/structure/coerce_actions.pyx +988 -0
  217. sage/structure/coerce_dict.cp312-win_amd64.pyd +0 -0
  218. sage/structure/coerce_dict.pxd +51 -0
  219. sage/structure/coerce_dict.pyx +1557 -0
  220. sage/structure/coerce_exceptions.py +23 -0
  221. sage/structure/coerce_maps.cp312-win_amd64.pyd +0 -0
  222. sage/structure/coerce_maps.pxd +28 -0
  223. sage/structure/coerce_maps.pyx +718 -0
  224. sage/structure/debug_options.cp312-win_amd64.pyd +0 -0
  225. sage/structure/debug_options.pxd +6 -0
  226. sage/structure/debug_options.pyx +54 -0
  227. sage/structure/dynamic_class.py +541 -0
  228. sage/structure/element.cp312-win_amd64.pyd +0 -0
  229. sage/structure/element.pxd +272 -0
  230. sage/structure/element.pyx +4772 -0
  231. sage/structure/element_wrapper.cp312-win_amd64.pyd +0 -0
  232. sage/structure/element_wrapper.pxd +12 -0
  233. sage/structure/element_wrapper.pyx +582 -0
  234. sage/structure/factorization.py +1422 -0
  235. sage/structure/factorization_integer.py +105 -0
  236. sage/structure/factory.cp312-win_amd64.pyd +0 -0
  237. sage/structure/factory.pyx +786 -0
  238. sage/structure/formal_sum.py +489 -0
  239. sage/structure/gens_py.py +73 -0
  240. sage/structure/global_options.py +1743 -0
  241. sage/structure/indexed_generators.py +863 -0
  242. sage/structure/list_clone.cp312-win_amd64.pyd +0 -0
  243. sage/structure/list_clone.pxd +65 -0
  244. sage/structure/list_clone.pyx +1867 -0
  245. sage/structure/list_clone_demo.cp312-win_amd64.pyd +0 -0
  246. sage/structure/list_clone_demo.pyx +248 -0
  247. sage/structure/list_clone_timings.py +179 -0
  248. sage/structure/list_clone_timings_cy.cp312-win_amd64.pyd +0 -0
  249. sage/structure/list_clone_timings_cy.pyx +86 -0
  250. sage/structure/mutability.cp312-win_amd64.pyd +0 -0
  251. sage/structure/mutability.pxd +21 -0
  252. sage/structure/mutability.pyx +348 -0
  253. sage/structure/nonexact.py +69 -0
  254. sage/structure/parent.cp312-win_amd64.pyd +0 -0
  255. sage/structure/parent.pxd +112 -0
  256. sage/structure/parent.pyx +3093 -0
  257. sage/structure/parent_base.cp312-win_amd64.pyd +0 -0
  258. sage/structure/parent_base.pxd +13 -0
  259. sage/structure/parent_base.pyx +44 -0
  260. sage/structure/parent_gens.cp312-win_amd64.pyd +0 -0
  261. sage/structure/parent_gens.pxd +22 -0
  262. sage/structure/parent_gens.pyx +377 -0
  263. sage/structure/parent_old.cp312-win_amd64.pyd +0 -0
  264. sage/structure/parent_old.pxd +25 -0
  265. sage/structure/parent_old.pyx +294 -0
  266. sage/structure/proof/__init__.py +1 -0
  267. sage/structure/proof/all.py +243 -0
  268. sage/structure/proof/proof.py +300 -0
  269. sage/structure/richcmp.cp312-win_amd64.pyd +0 -0
  270. sage/structure/richcmp.pxd +213 -0
  271. sage/structure/richcmp.pyx +495 -0
  272. sage/structure/sage_object.cp312-win_amd64.pyd +0 -0
  273. sage/structure/sage_object.pxd +3 -0
  274. sage/structure/sage_object.pyx +988 -0
  275. sage/structure/sage_object_test.py +19 -0
  276. sage/structure/sequence.py +937 -0
  277. sage/structure/set_factories.py +1178 -0
  278. sage/structure/set_factories_example.py +527 -0
  279. sage/structure/support_view.py +179 -0
  280. sage/structure/test_factory.py +56 -0
  281. sage/structure/unique_representation.py +1359 -0
@@ -0,0 +1,637 @@
1
+ # sage_setup: distribution = sagemath-objects
2
+ r"""
3
+ Unit testing for Sage objects
4
+ """
5
+
6
+ # ****************************************************************************
7
+ # Copyright (C) 2009 Nicolas M. Thiery <nthiery at users.sf.net>
8
+ #
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ # https://www.gnu.org/licenses/
14
+ # ****************************************************************************
15
+
16
+ import unittest
17
+ import sys
18
+ import traceback
19
+
20
+
21
+ class TestSuite:
22
+ """
23
+ Test suites for Sage objects.
24
+
25
+ EXAMPLES::
26
+
27
+ sage: TestSuite(ZZ).run()
28
+
29
+ No output means that all tests passed. Which tests?
30
+ In practice this calls all the methods ``._test_*`` of this
31
+ object, in alphabetic order::
32
+
33
+ sage: TestSuite(1).run(verbose = True)
34
+ running ._test_category() . . . pass
35
+ running ._test_eq() . . . pass
36
+ running ._test_new() . . . pass
37
+ running ._test_nonzero_equal() . . . pass
38
+ running ._test_not_implemented_methods() . . . pass
39
+ running ._test_pickling() . . . pass
40
+
41
+ Those methods are typically implemented by abstract
42
+ super classes, in particular via categories, in order to
43
+ enforce standard behavior and API, or provide mathematical
44
+ sanity checks. For example if ``self`` is in the category of
45
+ finite semigroups, this checks that the multiplication is
46
+ associative (at least on some elements)::
47
+
48
+ sage: S = FiniteSemigroups().example(alphabet = ('a', 'b'))
49
+ sage: TestSuite(S).run(verbose = True)
50
+ running ._test_an_element() . . . pass
51
+ running ._test_associativity() . . . pass
52
+ running ._test_cardinality() . . . pass
53
+ running ._test_category() . . . pass
54
+ running ._test_construction() . . . pass
55
+ running ._test_elements() . . .
56
+ Running the test suite of self.an_element()
57
+ running ._test_category() . . . pass
58
+ running ._test_eq() . . . pass
59
+ running ._test_new() . . . pass
60
+ running ._test_not_implemented_methods() . . . pass
61
+ running ._test_pickling() . . . pass
62
+ pass
63
+ running ._test_elements_eq_reflexive() . . . pass
64
+ running ._test_elements_eq_symmetric() . . . pass
65
+ running ._test_elements_eq_transitive() . . . pass
66
+ running ._test_elements_neq() . . . pass
67
+ running ._test_enumerated_set_contains() . . . pass
68
+ running ._test_enumerated_set_iter_cardinality() . . . pass
69
+ running ._test_enumerated_set_iter_list() . . . pass
70
+ running ._test_eq() . . . pass
71
+ running ._test_new() . . . pass
72
+ running ._test_not_implemented_methods() . . . pass
73
+ running ._test_pickling() . . . pass
74
+ running ._test_some_elements() . . . pass
75
+
76
+ The different test methods can be called independently::
77
+
78
+ sage: S._test_associativity()
79
+
80
+ Debugging tip: in case of failure of some test, use ``%pdb on`` to
81
+ turn on automatic debugging on error. Run the failing test
82
+ independently: the debugger will stop right where the first
83
+ assertion fails. Then, introspection can be used to analyse what
84
+ exactly the problem is. See also the ``catch = False`` option to
85
+ :meth:`.run`.
86
+
87
+ When meaningful, one can further customize on which elements
88
+ the tests are run. Here, we use it to *prove* that the
89
+ multiplication is indeed associative, by running the test on
90
+ all the elements::
91
+
92
+ sage: S._test_associativity(elements = S)
93
+
94
+ Adding a new test boils down to adding a new method in the class
95
+ of the object or any super class (e.g. in a category). This method
96
+ should use the utility :meth:`._tester` to handle standard options
97
+ and report test failures. See the code of
98
+ :meth:`._test_an_element` for an example. Note: Python's testunit
99
+ convention is to look for methods called ``.test*``; we use instead
100
+ ``._test_*`` so as not to pollute the object's interface.
101
+
102
+ Eventually, every implementation of a :class:`SageObject` should
103
+ run a :class:`TestSuite` on one of its instances in its doctest
104
+ (replacing the current ``loads(dumps(x))`` tests).
105
+
106
+ Finally, running ``TestSuite`` on a standard Python object does
107
+ some basic sanity checks::
108
+
109
+ sage: TestSuite(int(1)).run(verbose = True)
110
+ running ._test_new() . . . pass
111
+ running ._test_pickling() . . . pass
112
+
113
+ .. TODO::
114
+
115
+ - Allow for customized behavior in case of failing assertion
116
+ (warning, error, statistic accounting).
117
+ This involves reimplementing the methods fail / failIf / ...
118
+ of unittest.TestCase in InstanceTester
119
+
120
+ - Don't catch the exceptions if ``TestSuite(..).run()`` is called
121
+ under the debugger, or with ``%pdb`` on (how to detect this? see
122
+ ``get_ipython()``, ``IPython.Magic.shell.call_pdb``, ...)
123
+ In the mean time, see the ``catch=False`` option.
124
+
125
+ - Run the tests according to the inheritance order, from most
126
+ generic to most specific, rather than alphabetically. Then, the
127
+ first failure will be the most relevant, the others being
128
+ usually consequences.
129
+
130
+ - Improve integration with doctests (statistics on failing/passing tests)
131
+
132
+ - Add proper support for nested testsuites.
133
+
134
+ - Integration with unittest:
135
+ Make TestSuite inherit from unittest.TestSuite?
136
+ Make ``.run(...)`` accept a result object
137
+
138
+ - Add some standard option ``proof = True``, asking for the
139
+ test method to choose appropriately the elements so as to
140
+ prove the desired property. The test method may assume that
141
+ a parent implements properly all the super categories. For
142
+ example, the ``_test_commutative`` method of the category
143
+ ``CommutativeSemigroups()`` may just check that the
144
+ provided generators commute, implicitly assuming that
145
+ generators indeed generate the semigroup (as required by
146
+ ``Semigroups()``).
147
+ """
148
+
149
+ def __init__(self, instance):
150
+ """
151
+ TESTS::
152
+
153
+ sage: TestSuite(ZZ)
154
+ Test suite for Integer Ring
155
+ """
156
+ from sage.structure.sage_object import SageObject
157
+ if not isinstance(instance, (SageObject, PythonObjectWithTests)):
158
+ instance = PythonObjectWithTests(instance)
159
+ self._instance = instance
160
+
161
+ def __repr__(self):
162
+ """
163
+ TESTS::
164
+
165
+ sage: TestSuite(ZZ)
166
+ Test suite for Integer Ring
167
+ """
168
+ return "Test suite for %s" % self._instance
169
+
170
+ def run(self, category=None, skip=[], catch=True, raise_on_failure=False,
171
+ **options):
172
+ """
173
+ Run all the tests from this test suite:
174
+
175
+ INPUT:
176
+
177
+ - ``category`` -- a category; reserved for future use
178
+ - ``skip`` -- string or list (or iterable) of strings
179
+ - ``raise_on_failure`` -- boolean (default: ``False``)
180
+ - ``catch`` -- boolean (default: ``True``)
181
+
182
+ All other options are passed down to the individual tests.
183
+
184
+ EXAMPLES::
185
+
186
+ sage: TestSuite(ZZ).run()
187
+
188
+ We now use the ``verbose`` option::
189
+
190
+ sage: TestSuite(1).run(verbose = True)
191
+ running ._test_category() . . . pass
192
+ running ._test_eq() . . . pass
193
+ running ._test_new() . . . pass
194
+ running ._test_nonzero_equal() . . . pass
195
+ running ._test_not_implemented_methods() . . . pass
196
+ running ._test_pickling() . . . pass
197
+
198
+ Some tests may be skipped using the ``skip`` option::
199
+
200
+ sage: TestSuite(1).run(verbose = True, skip ='_test_pickling')
201
+ running ._test_category() . . . pass
202
+ running ._test_eq() . . . pass
203
+ running ._test_new() . . . pass
204
+ running ._test_nonzero_equal() . . . pass
205
+ running ._test_not_implemented_methods() . . . pass
206
+ sage: TestSuite(1).run(verbose = True, skip =["_test_pickling", "_test_category"])
207
+ running ._test_eq() . . . pass
208
+ running ._test_new() . . . pass
209
+ running ._test_nonzero_equal() . . . pass
210
+ running ._test_not_implemented_methods() . . . pass
211
+
212
+ We now show (and test) some standard error reports::
213
+
214
+ sage: class Blah(SageObject):
215
+ ....: def _test_a(self, tester): pass
216
+ ....: def _test_b(self, tester): tester.fail()
217
+ ....: def _test_c(self, tester): pass
218
+ ....: def _test_d(self, tester): tester.fail()
219
+
220
+ sage: TestSuite(Blah()).run()
221
+ Failure in _test_b:
222
+ Traceback (most recent call last):
223
+ ...
224
+ AssertionError: None
225
+ ------------------------------------------------------------
226
+ Failure in _test_d:
227
+ Traceback (most recent call last):
228
+ ...
229
+ AssertionError: None
230
+ ------------------------------------------------------------
231
+ Failure in _test_pickling:
232
+ ...
233
+ ...PicklingError: Can't pickle <class '__main__.Blah'>: ...
234
+ ...
235
+ ------------------------------------------------------------
236
+ The following tests failed: _test_b, _test_d, _test_pickling
237
+
238
+ sage: TestSuite(Blah()).run(verbose = True)
239
+ running ._test_a() . . . pass
240
+ running ._test_b() . . . fail
241
+ Traceback (most recent call last):
242
+ ...
243
+ AssertionError: None
244
+ ------------------------------------------------------------
245
+ running ._test_c() . . . pass
246
+ running ._test_category() . . . pass
247
+ running ._test_d() . . . fail
248
+ Traceback (most recent call last):
249
+ ...
250
+ AssertionError: None
251
+ ------------------------------------------------------------
252
+ running ._test_new() . . . pass
253
+ running ._test_not_implemented_methods() . . . pass
254
+ running ._test_pickling() . . . fail
255
+ ...
256
+ ...PicklingError: Can't pickle <class '__main__.Blah'>: ...
257
+ ...
258
+ ------------------------------------------------------------
259
+ The following tests failed: _test_b, _test_d, _test_pickling
260
+
261
+ ...
262
+
263
+ The ``catch=False`` option prevents ``TestSuite`` from
264
+ catching exceptions::
265
+
266
+ sage: TestSuite(Blah()).run(catch=False)
267
+ Traceback (most recent call last):
268
+ ...
269
+ File ..., in _test_b
270
+ def _test_b(self, tester): tester.fail()
271
+ ...
272
+ AssertionError: None
273
+
274
+ In conjunction with ``%pdb on``, this allows for the debugger
275
+ to jump directly to the first failure location.
276
+ """
277
+ if isinstance(skip, str):
278
+ skip = [skip]
279
+ else:
280
+ skip = tuple(skip)
281
+
282
+ # The class of exceptions that will be caught and reported;
283
+ # other exceptions will get through. () catches nothing.
284
+ catch_exception = Exception if catch else ()
285
+
286
+ tester = instance_tester(self._instance, **options)
287
+ failed = []
288
+ for method_name in dir(self._instance):
289
+ if method_name[0:6] == "_test_" and method_name not in skip:
290
+ # TODO: improve pretty printing
291
+ # could use the doc string of the test method?
292
+ tester.info(tester._prefix + "running .%s() . . ." % method_name, newline=False)
293
+ test_method = getattr(self._instance, method_name)
294
+ try:
295
+ test_method(tester=tester)
296
+ tester.info(" pass")
297
+ except catch_exception as e:
298
+ failed.append(method_name)
299
+ if isinstance(e, TestSuiteFailure):
300
+ # The failure occurred in a nested testsuite
301
+ # which has already reported the details of
302
+ # that failure
303
+ if not tester._verbose:
304
+ print(tester._prefix + "Failure in {}".format(method_name))
305
+ else:
306
+ if tester._verbose:
307
+ tester.info(" fail")
308
+ else:
309
+ print(tester._prefix + "Failure in {}:".format(method_name))
310
+ s = traceback.format_exc()
311
+ print(tester._prefix + s.strip().replace("\n", "\n" + tester._prefix))
312
+ print(tester._prefix + "-" * 60)
313
+ if failed:
314
+ print(tester._prefix + "The following tests failed: {}".format(", ".join(failed)))
315
+ if raise_on_failure:
316
+ raise TestSuiteFailure
317
+
318
+
319
+ class TestSuiteFailure(AssertionError):
320
+ pass
321
+
322
+
323
+ def instance_tester(instance, tester=None, **options):
324
+ """
325
+ Return a gadget attached to ``instance`` providing testing utilities.
326
+
327
+ EXAMPLES::
328
+
329
+ sage: from sage.misc.sage_unittest import instance_tester
330
+ sage: tester = instance_tester(ZZ)
331
+
332
+ sage: tester.assertTrue(1 == 1)
333
+ sage: tester.assertTrue(1 == 0)
334
+ Traceback (most recent call last):
335
+ ...
336
+ AssertionError: False is not true
337
+ sage: tester.assertTrue(1 == 0, "this is expected to fail")
338
+ Traceback (most recent call last):
339
+ ...
340
+ AssertionError: this is expected to fail
341
+
342
+ sage: tester.assertEqual(1, 1)
343
+ sage: tester.assertEqual(1, 0)
344
+ Traceback (most recent call last):
345
+ ...
346
+ AssertionError: 1 != 0
347
+
348
+ The available assertion testing facilities are the same as in
349
+ :class:`unittest.TestCase` [UNITTEST]_, which see (actually, by a slight
350
+ abuse, tester is currently an instance of this class).
351
+
352
+ TESTS::
353
+
354
+ sage: instance_tester(ZZ, tester = tester) is tester
355
+ True
356
+ """
357
+ if tester is None:
358
+ return InstanceTester(instance, **options)
359
+ else:
360
+ assert not options
361
+ assert tester._instance is instance
362
+ return tester
363
+
364
+
365
+ class InstanceTester(unittest.TestCase):
366
+ """
367
+ A gadget attached to an instance providing it with testing utilities.
368
+
369
+ EXAMPLES::
370
+
371
+ sage: from sage.misc.sage_unittest import InstanceTester
372
+ sage: InstanceTester(instance = ZZ, verbose = True, elements = [1,2,3])
373
+ Testing utilities for Integer Ring
374
+
375
+ This is used by ``SageObject._tester``, which see::
376
+
377
+ sage: QQ._tester()
378
+ Testing utilities for Rational Field
379
+ """
380
+
381
+ # On Python 3 this attribute defaults to True, causing the AssertionErrors
382
+ # output by failed test cases to produce longer error messages than the
383
+ # default error messages on Python 2. So for backwards compatibility of
384
+ # existing test cases we disable these "long messages" (which don't gain us
385
+ # all that much anyways)
386
+ longMessage = False
387
+
388
+ def __init__(self, instance, elements=None, verbose=False, prefix='',
389
+ max_runs=4096, max_samples=None, **options):
390
+ """
391
+ A gadget attached to an instance providing it with testing utilities.
392
+
393
+ EXAMPLES::
394
+
395
+ sage: from sage.misc.sage_unittest import InstanceTester
396
+ sage: InstanceTester(instance = ZZ, verbose = True, elements = [1,2,3])
397
+ Testing utilities for Integer Ring
398
+
399
+ This is used by ``SageObject._tester``, for example::
400
+
401
+ sage: QQ._tester()
402
+ Testing utilities for Rational Field
403
+ """
404
+ unittest.TestCase.__init__(self)
405
+ self._instance = instance
406
+ self._verbose = verbose
407
+ self._elements = elements
408
+ self._prefix = prefix
409
+ self._max_runs = max_runs
410
+ self._max_samples = max_samples
411
+
412
+ def runTest(self):
413
+ """
414
+ Trivial implementation of :meth:`unittest.TestCase.runTest` to
415
+ please the super class :class:`TestCase`. That's the price to
416
+ pay for abusively inheriting from it.
417
+
418
+ EXAMPLES::
419
+
420
+ sage: from sage.misc.sage_unittest import InstanceTester
421
+ sage: tester = InstanceTester(ZZ, verbose = True)
422
+ sage: tester.runTest()
423
+ """
424
+ pass
425
+
426
+ def info(self, message, newline=True):
427
+ """
428
+ Display user information.
429
+
430
+ EXAMPLES::
431
+
432
+ sage: from sage.misc.sage_unittest import InstanceTester
433
+ sage: tester = InstanceTester(ZZ, verbose = True)
434
+
435
+ sage: tester.info("hello"); tester.info("world")
436
+ hello
437
+ world
438
+
439
+ sage: tester = InstanceTester(ZZ, verbose = False)
440
+ sage: tester.info("hello"); tester.info("world")
441
+
442
+ sage: tester = InstanceTester(ZZ, verbose = True)
443
+ sage: tester.info("hello", newline = False); tester.info(" world")
444
+ hello world
445
+ """
446
+ if self._verbose:
447
+ if newline:
448
+ sys.stdout.write(message + "\n")
449
+ else:
450
+ sys.stdout.write(message)
451
+ sys.stdout.flush()
452
+
453
+ def __repr__(self):
454
+ """
455
+ EXAMPLES::
456
+
457
+ sage: from sage.misc.sage_unittest import InstanceTester
458
+ sage: InstanceTester(ZZ, verbose = True)
459
+ Testing utilities for Integer Ring
460
+ """
461
+ return "Testing utilities for %s" % self._instance
462
+
463
+ def some_elements(self, S=None, repeat=None):
464
+ """
465
+ Return a list (or iterable) of elements of the instance on which
466
+ the tests should be run.
467
+
468
+ This is only meaningful for container objects like parents.
469
+
470
+ INPUT:
471
+
472
+ - ``S`` -- set of elements to select from; by default this
473
+ will use the elements passed to this tester at creation
474
+ time, or the result of :meth:`.some_elements` if no elements
475
+ were specified
476
+
477
+ - ``repeat`` -- integer (default: ``None``); if given, instead returns
478
+ a list of tuples of length ``repeat`` from ``S``
479
+
480
+ OUTPUT:
481
+
482
+ A list of at most ``self._max_runs`` elements of ``S^r``,
483
+ or a sample of at most ``self._max_samples`` if that is not ``None``.
484
+
485
+ EXAMPLES:
486
+
487
+ By default, this calls :meth:`.some_elements` on the instance::
488
+
489
+ sage: from sage.misc.sage_unittest import InstanceTester
490
+ sage: class MyParent(Parent):
491
+ ....: def some_elements(self):
492
+ ....: return [1,2,3,4,5]
493
+ ...
494
+ sage: tester = InstanceTester(MyParent())
495
+ sage: list(tester.some_elements())
496
+ [1, 2, 3, 4, 5]
497
+
498
+ sage: tester = InstanceTester(MyParent(), max_runs=3)
499
+ sage: list(tester.some_elements())
500
+ [1, 2, 3]
501
+
502
+ sage: tester = InstanceTester(MyParent(), max_runs=7)
503
+ sage: list(tester.some_elements())
504
+ [1, 2, 3, 4, 5]
505
+
506
+ sage: tester = InstanceTester(MyParent(), elements=[1,3,5])
507
+ sage: list(tester.some_elements())
508
+ [1, 3, 5]
509
+
510
+ sage: tester = InstanceTester(MyParent(), elements=[1,3,5], max_runs=2)
511
+ sage: list(tester.some_elements())
512
+ [1, 3]
513
+
514
+ sage: tester = InstanceTester(FiniteEnumeratedSet(['a','b','c','d']), max_runs=3)
515
+ sage: tester.some_elements()
516
+ ['a', 'b', 'c']
517
+
518
+ sage: tester = InstanceTester(FiniteEnumeratedSet([]))
519
+ sage: list(tester.some_elements())
520
+ []
521
+
522
+ sage: tester = InstanceTester(ZZ)
523
+ sage: ZZ.some_elements() # yikes, shamelessly trivial ...
524
+ <generator object ..._some_elements_from_iterator at 0x...>
525
+ sage: list(tester.some_elements())
526
+ [0, 1, -1, 2, -2, ..., 49, -49, 50]
527
+
528
+ sage: tester = InstanceTester(ZZ, elements = ZZ, max_runs=5)
529
+ sage: list(tester.some_elements())
530
+ [0, 1, -1, 2, -2]
531
+
532
+ sage: tester = InstanceTester(ZZ, elements = srange(100), max_runs=5)
533
+ sage: list(tester.some_elements())
534
+ [0, 1, 2, 3, 4]
535
+
536
+ sage: tester = InstanceTester(ZZ, elements = srange(3), max_runs=5)
537
+ sage: list(tester.some_elements())
538
+ [0, 1, 2]
539
+
540
+ The ``repeat`` keyword can give pairs or triples from ``S``::
541
+
542
+ sage: list(tester.some_elements(repeat=2))
543
+ [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1)]
544
+
545
+ You can use ``max_samples`` to sample at random, instead of in order::
546
+
547
+ sage: tester = InstanceTester(ZZ, elements = srange(8), max_samples = 4)
548
+ sage: all(t in srange(8) for t in tester.some_elements())
549
+ True
550
+ sage: all(s in srange(8) and t in srange(8) for s,t in tester.some_elements(repeat=2))
551
+ True
552
+
553
+ Test for :issue:`15919`, :issue:`16244`::
554
+
555
+ sage: Z = IntegerModRing(25) # random.sample, which was used pre #16244, has a threshold at 21!
556
+ sage: Z[1] # since #8389, indexed access is used for ring extensions
557
+ Traceback (most recent call last):
558
+ ...
559
+ ValueError: variable name '1' does not start with a letter
560
+ sage: tester = InstanceTester(Z, elements=Z, max_runs=5)
561
+ sage: list(tester.some_elements())
562
+ [0, 1, 2, 3, 4]
563
+
564
+ sage: C = cartesian_product([Z]*4)
565
+ sage: len(C)
566
+ 390625
567
+ sage: tester = InstanceTester(C, elements = C, max_runs=4)
568
+ sage: list(tester.some_elements())
569
+ [(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)]
570
+ """
571
+ S = S or self._elements or self._instance.some_elements()
572
+ from sage.misc.misc import some_tuples
573
+ return list(some_tuples(S, repeat, self._max_runs, self._max_samples))
574
+
575
+
576
+ class PythonObjectWithTests:
577
+ """
578
+ Utility class for running basis tests on a plain Python object
579
+ (that is not in SageObject). More test methods can be added here.
580
+
581
+ EXAMPLES::
582
+
583
+ sage: TestSuite("bla").run()
584
+ """
585
+ def __init__(self, instance):
586
+ """
587
+ EXAMPLES::
588
+
589
+ sage: from sage.misc.sage_unittest import PythonObjectWithTests
590
+ sage: x = PythonObjectWithTests(int(1)); x
591
+ <sage.misc.sage_unittest.PythonObjectWithTests object at ...>
592
+ sage: TestSuite(x).run()
593
+ """
594
+ self._instance = instance
595
+
596
+ def _test_pickling(self, **options):
597
+ """
598
+ Check that the instance in ``self`` can be pickled and unpickled properly.
599
+
600
+ EXAMPLES::
601
+
602
+ sage: from sage.misc.sage_unittest import PythonObjectWithTests
603
+ sage: PythonObjectWithTests(int(1))._test_pickling()
604
+
605
+ .. SEEALSO::
606
+
607
+ :func:`dumps`, :func:`loads`
608
+ """
609
+ tester = instance_tester(self, **options)
610
+ from sage.misc.persist import loads, dumps
611
+ tester.assertEqual(loads(dumps(self._instance)), self._instance)
612
+
613
+ def _test_new(self, **options):
614
+ """
615
+ Check that ``cls.__new__(cls)`` does not crash Python, with
616
+ ``cls`` either the tested instance (if it's a type) or the type
617
+ of the instance.
618
+
619
+ It is perfectly legal for ``__new__`` to raise ordinary
620
+ exceptions.
621
+
622
+ EXAMPLES::
623
+
624
+ sage: TestSuite(int(1)).run(verbose=True)
625
+ running ._test_new() . . . pass
626
+ running ._test_pickling() . . . pass
627
+ sage: TestSuite(int).run(verbose=True)
628
+ running ._test_new() . . . pass
629
+ running ._test_pickling() . . . pass
630
+ """
631
+ cls = self._instance
632
+ if not isinstance(cls, type):
633
+ cls = type(cls)
634
+ try:
635
+ cls.__new__(cls)
636
+ except Exception:
637
+ pass