ndtypes 0.2.0dev5 → 0.2.0dev6

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +12 -0
  3. data/Rakefile +8 -0
  4. data/ext/ruby_ndtypes/GPATH +0 -0
  5. data/ext/ruby_ndtypes/GRTAGS +0 -0
  6. data/ext/ruby_ndtypes/GTAGS +0 -0
  7. data/ext/ruby_ndtypes/extconf.rb +1 -1
  8. data/ext/ruby_ndtypes/include/ndtypes.h +231 -122
  9. data/ext/ruby_ndtypes/include/ruby_ndtypes.h +1 -1
  10. data/ext/ruby_ndtypes/lib/libndtypes.a +0 -0
  11. data/ext/ruby_ndtypes/lib/libndtypes.so.0.2.0dev3 +0 -0
  12. data/ext/ruby_ndtypes/ndtypes/Makefile +87 -0
  13. data/ext/ruby_ndtypes/ndtypes/config.h +68 -0
  14. data/ext/ruby_ndtypes/ndtypes/config.log +477 -0
  15. data/ext/ruby_ndtypes/ndtypes/config.status +1027 -0
  16. data/ext/ruby_ndtypes/ndtypes/doc/_static/style.css +7 -0
  17. data/ext/ruby_ndtypes/ndtypes/doc/_templates/layout.html +2 -0
  18. data/ext/ruby_ndtypes/ndtypes/doc/conf.py +40 -4
  19. data/ext/ruby_ndtypes/ndtypes/doc/images/xndlogo.png +0 -0
  20. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/types.rst +1 -1
  21. data/ext/ruby_ndtypes/ndtypes/doc/requirements.txt +2 -0
  22. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile +287 -0
  23. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.in +20 -4
  24. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.vc +22 -3
  25. data/ext/ruby_ndtypes/ndtypes/libndtypes/alloc.c +1 -1
  26. data/ext/ruby_ndtypes/ndtypes/libndtypes/alloc.o +0 -0
  27. data/ext/ruby_ndtypes/ndtypes/libndtypes/attr.o +0 -0
  28. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/Makefile +73 -0
  29. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.c +246 -229
  30. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.h +15 -11
  31. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.o +0 -0
  32. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.y +38 -28
  33. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.c +91 -91
  34. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.h +1 -1
  35. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.l +4 -3
  36. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.o +0 -0
  37. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/export.c +8 -7
  38. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/export.o +0 -0
  39. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/import.c +2 -2
  40. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/import.o +0 -0
  41. data/ext/ruby_ndtypes/ndtypes/libndtypes/context.o +0 -0
  42. data/ext/ruby_ndtypes/ndtypes/libndtypes/copy.c +263 -182
  43. data/ext/ruby_ndtypes/ndtypes/libndtypes/copy.o +0 -0
  44. data/ext/ruby_ndtypes/ndtypes/libndtypes/encodings.o +0 -0
  45. data/ext/ruby_ndtypes/ndtypes/libndtypes/equal.c +67 -7
  46. data/ext/ruby_ndtypes/ndtypes/libndtypes/equal.o +0 -0
  47. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.c +1112 -1000
  48. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.h +69 -58
  49. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.o +0 -0
  50. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.y +150 -99
  51. data/ext/ruby_ndtypes/ndtypes/libndtypes/io.c +185 -15
  52. data/ext/ruby_ndtypes/ndtypes/libndtypes/io.o +0 -0
  53. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.c +301 -276
  54. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.h +1 -1
  55. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.l +9 -4
  56. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.o +0 -0
  57. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.a +0 -0
  58. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so +1 -0
  59. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so.0 +1 -0
  60. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so.0.2.0dev3 +0 -0
  61. data/ext/ruby_ndtypes/ndtypes/libndtypes/match.c +729 -228
  62. data/ext/ruby_ndtypes/ndtypes/libndtypes/match.o +0 -0
  63. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.c +768 -403
  64. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.h +1002 -0
  65. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.h.in +231 -122
  66. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.o +0 -0
  67. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.c +176 -84
  68. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.h +26 -14
  69. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.o +0 -0
  70. data/ext/ruby_ndtypes/ndtypes/libndtypes/parser.c +57 -35
  71. data/ext/ruby_ndtypes/ndtypes/libndtypes/parser.o +0 -0
  72. data/ext/ruby_ndtypes/ndtypes/libndtypes/primitive.c +420 -0
  73. data/ext/ruby_ndtypes/ndtypes/libndtypes/primitive.o +0 -0
  74. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.c +8 -8
  75. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.h +1 -1
  76. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.o +0 -0
  77. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/Makefile +48 -0
  78. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/deserialize.c +200 -116
  79. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/deserialize.o +0 -0
  80. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/serialize.c +46 -4
  81. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/serialize.o +0 -0
  82. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.c +58 -27
  83. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.h +1 -1
  84. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.o +0 -0
  85. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.c +3 -5
  86. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.h +12 -4
  87. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.o +0 -0
  88. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile +55 -0
  89. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.in +8 -8
  90. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.vc +5 -5
  91. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/runtest.c +274 -172
  92. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test.h +24 -4
  93. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_array.c +2 -2
  94. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_buffer.c +14 -14
  95. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_match.c +32 -30
  96. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse.c +37 -0
  97. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_error.c +36 -0
  98. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_roundtrip.c +16 -0
  99. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_record.c +5 -5
  100. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_typecheck.c +706 -253
  101. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_unify.c +132 -0
  102. data/ext/ruby_ndtypes/ndtypes/libndtypes/unify.c +703 -0
  103. data/ext/ruby_ndtypes/ndtypes/libndtypes/unify.o +0 -0
  104. data/ext/ruby_ndtypes/ndtypes/libndtypes/util.c +335 -127
  105. data/ext/ruby_ndtypes/ndtypes/libndtypes/util.o +0 -0
  106. data/ext/ruby_ndtypes/ndtypes/libndtypes/values.c +2 -2
  107. data/ext/ruby_ndtypes/ndtypes/libndtypes/values.o +0 -0
  108. data/ext/ruby_ndtypes/ndtypes/python/ndt_randtype.py +88 -71
  109. data/ext/ruby_ndtypes/ndtypes/python/ndt_support.py +0 -1
  110. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/__init__.py +10 -13
  111. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/_ndtypes.c +395 -314
  112. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.a +0 -0
  113. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so +1 -0
  114. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so.0 +1 -0
  115. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so.0.2.0dev3 +0 -0
  116. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/ndtypes.h +1002 -0
  117. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/pyndtypes.h +15 -33
  118. data/ext/ruby_ndtypes/ndtypes/python/test_ndtypes.py +340 -132
  119. data/ext/ruby_ndtypes/ndtypes/setup.py +11 -2
  120. data/ext/ruby_ndtypes/ruby_ndtypes.c +364 -241
  121. data/ext/ruby_ndtypes/ruby_ndtypes.h +1 -1
  122. data/ext/ruby_ndtypes/ruby_ndtypes_internal.h +0 -1
  123. data/lib/ndtypes.rb +11 -0
  124. data/lib/ndtypes/version.rb +2 -2
  125. data/lib/ruby_ndtypes.so +0 -0
  126. data/ndtypes.gemspec +3 -0
  127. data/spec/ndtypes_spec.rb +6 -0
  128. metadata +98 -4
  129. data/ext/ruby_ndtypes/gc_guard.c +0 -36
  130. data/ext/ruby_ndtypes/gc_guard.h +0 -12
@@ -51,13 +51,11 @@ extern "C" {
51
51
 
52
52
  typedef struct {
53
53
  PyObject_HEAD
54
- PyObject *rbuf; /* resource buffer */
55
- ndt_t *ndt; /* type */
54
+ Py_hash_t hash;
55
+ const ndt_t *ndt;
56
56
  } NdtObject;
57
57
 
58
58
  #define NDT(v) (((NdtObject *)v)->ndt)
59
- #define RBUF(v) (((NdtObject *)v)->rbuf)
60
- #define RBUF_NDT_META(v) (((ResourceBufferObject *)(((NdtObject *)v)->rbuf))->m)
61
59
 
62
60
 
63
61
  /****************************************************************************/
@@ -72,42 +70,32 @@ typedef struct {
72
70
  #define Ndt_Check_RETURN int
73
71
  #define Ndt_Check_ARGS (const PyObject *)
74
72
 
75
- #define CONST_NDT_INDEX 2
76
- #define CONST_NDT_RETURN const ndt_t *
77
- #define CONST_NDT_ARGS (const PyObject *)
78
-
79
- #define Ndt_SetError_INDEX 3
73
+ #define Ndt_SetError_INDEX 2
80
74
  #define Ndt_SetError_RETURN PyObject *
81
75
  #define Ndt_SetError_ARGS (ndt_context_t *)
82
76
 
83
- #define Ndt_CopySubtree_INDEX 4
84
- #define Ndt_CopySubtree_RETURN PyObject *
85
- #define Ndt_CopySubtree_ARGS (const PyObject *, const ndt_t *)
86
-
87
- #define Ndt_MoveSubtree_INDEX 5
88
- #define Ndt_MoveSubtree_RETURN PyObject *
89
- #define Ndt_MoveSubtree_ARGS (const PyObject *, ndt_t *)
90
-
91
- #define Ndt_FromType_INDEX 6
77
+ #define Ndt_FromType_INDEX 3
92
78
  #define Ndt_FromType_RETURN PyObject *
93
- #define Ndt_FromType_ARGS (ndt_t *)
79
+ #define Ndt_FromType_ARGS (const ndt_t *)
94
80
 
95
- #define Ndt_FromObject_INDEX 7
81
+ #define Ndt_FromObject_INDEX 4
96
82
  #define Ndt_FromObject_RETURN PyObject *
97
83
  #define Ndt_FromObject_ARGS (PyObject *)
98
84
 
99
- #define NDTYPES_MAX_API 8
85
+ #define Ndt_FromOffsetsAndDtype_INDEX 5
86
+ #define Ndt_FromOffsetsAndDtype_RETURN PyObject *
87
+ #define Ndt_FromOffsetsAndDtype_ARGS (PyObject *offsets, bool *opt, const ndt_t *dtype)
88
+
89
+ #define NDTYPES_MAX_API 6
100
90
 
101
91
 
102
92
  #ifdef NDTYPES_MODULE
103
93
  static Ndt_CheckExact_RETURN Ndt_CheckExact Ndt_CheckExact_ARGS;
104
94
  static Ndt_Check_RETURN Ndt_Check Ndt_Check_ARGS;
105
- static CONST_NDT_RETURN CONST_NDT CONST_NDT_ARGS;
106
95
  static Ndt_SetError_RETURN Ndt_SetError Ndt_SetError_ARGS;
107
- static Ndt_CopySubtree_RETURN Ndt_CopySubtree Ndt_CopySubtree_ARGS;
108
- static Ndt_MoveSubtree_RETURN Ndt_MoveSubtree Ndt_MoveSubtree_ARGS;
109
96
  static Ndt_FromType_RETURN Ndt_FromType Ndt_FromType_ARGS;
110
97
  static Ndt_FromObject_RETURN Ndt_FromObject Ndt_FromObject_ARGS;
98
+ static Ndt_FromOffsetsAndDtype_RETURN Ndt_FromOffsetsAndDtype Ndt_FromOffsetsAndDtype_ARGS;
111
99
  #else
112
100
  static void **_ndtypes_api;
113
101
 
@@ -117,24 +105,18 @@ static void **_ndtypes_api;
117
105
  #define Ndt_Check \
118
106
  (*(Ndt_Check_RETURN (*)Ndt_Check_ARGS) _ndtypes_api[Ndt_Check_INDEX])
119
107
 
120
- #define CONST_NDT \
121
- (*(CONST_NDT_RETURN (*)CONST_NDT_ARGS) _ndtypes_api[CONST_NDT_INDEX])
122
-
123
108
  #define Ndt_SetError \
124
109
  (*(Ndt_SetError_RETURN (*)Ndt_SetError_ARGS) _ndtypes_api[Ndt_SetError_INDEX])
125
110
 
126
- #define Ndt_CopySubtree \
127
- (*(Ndt_CopySubtree_RETURN (*)Ndt_CopySubtree_ARGS) _ndtypes_api[Ndt_CopySubtree_INDEX])
128
-
129
- #define Ndt_MoveSubtree \
130
- (*(Ndt_MoveSubtree_RETURN (*)Ndt_MoveSubtree_ARGS) _ndtypes_api[Ndt_MoveSubtree_INDEX])
131
-
132
111
  #define Ndt_FromType \
133
112
  (*(Ndt_FromType_RETURN (*)Ndt_FromType_ARGS) _ndtypes_api[Ndt_FromType_INDEX])
134
113
 
135
114
  #define Ndt_FromObject \
136
115
  (*(Ndt_FromObject_RETURN (*)Ndt_FromObject_ARGS) _ndtypes_api[Ndt_FromObject_INDEX])
137
116
 
117
+ #define Ndt_FromOffsetsAndDtype \
118
+ (*(Ndt_FromOffsetsAndDtype_RETURN (*)Ndt_FromOffsetsAndDtype_ARGS) _ndtypes_api[Ndt_FromOffsetsAndDtype_INDEX])
119
+
138
120
  static int
139
121
  import_ndtypes(void)
140
122
  {
@@ -81,6 +81,7 @@ class TestModule(unittest.TestCase):
81
81
 
82
82
  self.assertFalse(t.is_f_contiguous())
83
83
  self.assertFalse(t.is_c_contiguous())
84
+ self.assertFalse(t.is_var_contiguous())
84
85
 
85
86
  def test_module_common_fields(self):
86
87
  t = ndt("SomeNamespace:: 2 * 3 * float64")
@@ -113,6 +114,7 @@ class TestFunction(unittest.TestCase):
113
114
 
114
115
  self.assertFalse(t.is_c_contiguous())
115
116
  self.assertFalse(t.is_f_contiguous())
117
+ self.assertFalse(t.is_var_contiguous())
116
118
 
117
119
  def test_function_common_fields(self):
118
120
  t = ndt("(10 * float64, string) -> float64")
@@ -145,6 +147,7 @@ class TestVoid(unittest.TestCase):
145
147
 
146
148
  self.assertFalse(t.is_c_contiguous())
147
149
  self.assertFalse(t.is_f_contiguous())
150
+ self.assertFalse(t.is_var_contiguous())
148
151
 
149
152
  def test_void_exceptions(self):
150
153
  # Void can only be used as a function return type.
@@ -167,6 +170,7 @@ class TestAny(unittest.TestCase):
167
170
 
168
171
  self.assertFalse(t.is_c_contiguous())
169
172
  self.assertFalse(t.is_f_contiguous())
173
+ self.assertFalse(t.is_var_contiguous())
170
174
 
171
175
  def test_any_common_fields(self):
172
176
  t = ndt("Any")
@@ -198,14 +202,17 @@ class TestFixedDim(unittest.TestCase):
198
202
 
199
203
  self.assertTrue(t.is_c_contiguous())
200
204
  self.assertFalse(t.is_f_contiguous())
205
+ self.assertFalse(t.is_var_contiguous())
201
206
 
202
207
  t = ndt("20 * complex128")
203
208
  self.assertTrue(t.is_c_contiguous())
204
209
  self.assertTrue(t.is_f_contiguous())
210
+ self.assertFalse(t.is_var_contiguous())
205
211
 
206
212
  t = ndt("1 * 10 * complex128")
207
213
  self.assertTrue(t.is_c_contiguous())
208
214
  self.assertTrue(t.is_f_contiguous())
215
+ self.assertFalse(t.is_var_contiguous())
209
216
 
210
217
  def test_fixed_dim_common_fields(self):
211
218
  dt = "{a: complex64, b: string}"
@@ -291,6 +298,32 @@ class TestFixedDim(unittest.TestCase):
291
298
  self.assertEqual(t.datasize, c_datasize(t))
292
299
  self.assertTrue(verify_datasize(t))
293
300
 
301
+ def test_fixed_dim_at(self):
302
+
303
+ for dims in ("2 * 3 * ", "0 * 1 * "):
304
+ t = ndt(dims + "int8")
305
+
306
+ u = t.at(0)
307
+ self.assertEqual(u, ndt(dims + "int8"))
308
+
309
+ u = t.at(1)
310
+ self.assertEqual(u, ndt(dims[4:] + "int8"))
311
+
312
+ u = t.at(2)
313
+ self.assertEqual(u, ndt("int8"))
314
+
315
+ u = t.at(0, dtype="int64")
316
+ self.assertEqual(u, ndt(dims + "int64"))
317
+
318
+ u = t.at(1, dtype="int64")
319
+ self.assertEqual(u, ndt(dims[4:] + "int64"))
320
+
321
+ u = t.at(2, dtype="int64")
322
+ self.assertEqual(u, ndt("int64"))
323
+
324
+ self.assertRaises(ValueError, t.at, -1)
325
+ self.assertRaises(ValueError, t.at, -3)
326
+
294
327
 
295
328
  class TestFortran(unittest.TestCase):
296
329
 
@@ -308,14 +341,17 @@ class TestFortran(unittest.TestCase):
308
341
 
309
342
  self.assertFalse(t.is_c_contiguous())
310
343
  self.assertTrue(t.is_f_contiguous())
344
+ self.assertFalse(t.is_var_contiguous())
311
345
 
312
346
  t = ndt("!20 * complex128")
313
347
  self.assertTrue(t.is_c_contiguous())
314
348
  self.assertTrue(t.is_f_contiguous())
349
+ self.assertFalse(t.is_var_contiguous())
315
350
 
316
351
  t = ndt("!1 * 10 * uint8")
317
352
  self.assertTrue(t.is_c_contiguous())
318
353
  self.assertTrue(t.is_f_contiguous())
354
+ self.assertFalse(t.is_var_contiguous())
319
355
 
320
356
  def test_fortran_common_fields(self):
321
357
  dt = "{a: complex64, b: string}"
@@ -398,6 +434,32 @@ class TestFortran(unittest.TestCase):
398
434
  s = "!fixed(shape=2, step=-20) * uint8"
399
435
  self.assertRaises(TypeError, ndt, s)
400
436
 
437
+ def test_fortran_at(self):
438
+
439
+ for dims in ("2 * 3 * ", "0 * 1 * "):
440
+ t = ndt("!" + dims + "int8")
441
+
442
+ u = t.at(0)
443
+ self.assertEqual(u, ndt(dims + "int8"))
444
+
445
+ u = t.at(1)
446
+ self.assertEqual(u, ndt(dims[4:] + "int8"))
447
+
448
+ u = t.at(2)
449
+ self.assertEqual(u, ndt("int8"))
450
+
451
+ u = t.at(0, dtype="int64")
452
+ self.assertEqual(u, ndt(dims + "int64"))
453
+
454
+ u = t.at(1, dtype="int64")
455
+ self.assertEqual(u, ndt(dims[4:] + "int64"))
456
+
457
+ u = t.at(2, dtype="int64")
458
+ self.assertEqual(u, ndt("int64"))
459
+
460
+ self.assertRaises(ValueError, t.at, -1)
461
+ self.assertRaises(ValueError, t.at, -3)
462
+
401
463
 
402
464
  class TestVarDim(unittest.TestCase):
403
465
 
@@ -416,6 +478,7 @@ class TestVarDim(unittest.TestCase):
416
478
 
417
479
  self.assertFalse(t.is_c_contiguous())
418
480
  self.assertFalse(t.is_f_contiguous())
481
+ self.assertTrue(t.is_var_contiguous())
419
482
 
420
483
  def test_var_dim_common_fields(self):
421
484
  dt = "{a: complex64, b: string}"
@@ -445,12 +508,6 @@ class TestVarDim(unittest.TestCase):
445
508
  # Too many dimensions.
446
509
  self.assertRaises(TypeError, ndt, "var * " * (MAX_DIM + 1) + "float64")
447
510
 
448
- # Nested var is disallowed.
449
- self.assertRaises(TypeError, ndt, "2 * {a: var * complex128}")
450
- self.assertRaises(TypeError, ndt, "var * {a: var * complex128}")
451
- self.assertRaises(TypeError, ndt, "var * ref(var * string)")
452
- self.assertRaises(TypeError, ndt, "var * SomeConstr(var * string)")
453
-
454
511
  def test_var_dim_external_offsets(self):
455
512
  # Invalid offsets.
456
513
  self.assertRaises(TypeError, ndt, "int8", [""])
@@ -478,9 +535,6 @@ class TestVarDim(unittest.TestCase):
478
535
  self.assertRaises(ValueError, ndt, "N * int8", [[0, 2], [0, 10, 20]])
479
536
  self.assertRaises(ValueError, ndt, "var * int8", [[0, 2], [0, 10, 20]])
480
537
 
481
- # Mixing external and internal offsets.
482
- self.assertRaises(TypeError, ndt, "var(offsets=[0,2,10]) * int8", [[0, 1], [0, 2]])
483
-
484
538
 
485
539
  class TestSymbolicDim(unittest.TestCase):
486
540
 
@@ -499,6 +553,7 @@ class TestSymbolicDim(unittest.TestCase):
499
553
 
500
554
  self.assertFalse(t.is_c_contiguous())
501
555
  self.assertFalse(t.is_f_contiguous())
556
+ self.assertFalse(t.is_var_contiguous())
502
557
 
503
558
  def test_symbolic_dim_common_fields(self):
504
559
  dt = "{a: complex64, b: string}"
@@ -506,12 +561,12 @@ class TestSymbolicDim(unittest.TestCase):
506
561
  check_serialize(self, t)
507
562
  dtype = ndt(dt)
508
563
 
509
- self.assertRaises(TypeError, t, 'ndim')
510
- self.assertRaises(TypeError, t, 'itemsize')
511
- self.assertRaises(TypeError, t, 'align')
564
+ self.assertRaises(TypeError, getattr, t, 'ndim')
565
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
566
+ self.assertRaises(TypeError, getattr, t, 'align')
512
567
 
513
- self.assertRaises(TypeError, t, 'shape')
514
- self.assertRaises(TypeError, t, 'strides')
568
+ self.assertRaises(TypeError, getattr, t, 'shape')
569
+ self.assertRaises(TypeError, getattr, t, 'strides')
515
570
 
516
571
 
517
572
  class TestEllipsisDim(unittest.TestCase):
@@ -531,6 +586,7 @@ class TestEllipsisDim(unittest.TestCase):
531
586
 
532
587
  self.assertFalse(t.is_c_contiguous())
533
588
  self.assertFalse(t.is_f_contiguous())
589
+ self.assertFalse(t.is_var_contiguous())
534
590
 
535
591
  def test_ellipsis_dim_common_fields(self):
536
592
  dt = "{a: complex64, b: string}"
@@ -538,12 +594,51 @@ class TestEllipsisDim(unittest.TestCase):
538
594
  check_serialize(self, t)
539
595
  dtype = ndt(dt)
540
596
 
541
- self.assertRaises(TypeError, t, 'ndim')
542
- self.assertRaises(TypeError, t, 'itemsize')
543
- self.assertRaises(TypeError, t, 'align')
597
+ self.assertRaises(TypeError, getattr, t, 'ndim')
598
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
599
+ self.assertRaises(TypeError, getattr, t, 'align')
544
600
 
545
- self.assertRaises(TypeError, t, 'shape')
546
- self.assertRaises(TypeError, t, 'strides')
601
+ self.assertRaises(TypeError, getattr, t, 'shape')
602
+ self.assertRaises(TypeError, getattr, t, 'strides')
603
+
604
+ class TestArray(unittest.TestCase):
605
+
606
+ def test_array_predicates(self):
607
+ t = ndt("array of complex128")
608
+ check_serialize(self, t)
609
+
610
+ self.assertFalse(t.isabstract())
611
+ self.assertFalse(t.iscomplex())
612
+ self.assertTrue(t.isconcrete())
613
+ self.assertFalse(t.isfloat())
614
+ self.assertFalse(t.isoptional())
615
+ self.assertFalse(t.isscalar())
616
+ self.assertFalse(t.issigned())
617
+ self.assertFalse(t.isunsigned())
618
+
619
+ self.assertFalse(t.is_c_contiguous())
620
+ self.assertFalse(t.is_f_contiguous())
621
+
622
+ def test_array_dim_common_fields(self):
623
+ dt = "{a: complex64, b: float64}"
624
+ t = ndt("array of %s" % dt)
625
+ check_serialize(self, t)
626
+ dtype = ndt(dt)
627
+
628
+ # The flexible array counts as a dtype.
629
+ self.assertEqual(t.ndim, 1)
630
+
631
+ self.assertRaises(TypeError, getattr, t, 'shape')
632
+ self.assertRaises(TypeError, getattr, t, 'strides')
633
+
634
+ if not HAVE_32_BIT_LINUX:
635
+ self.assertEqual(t.itemsize, dtype.itemsize)
636
+ self.assertEqual(t.align, dtype.align)
637
+
638
+ def test_array_invariants(self):
639
+ # Mixing array with fixed/var dimensions is disallowed.
640
+ self.assertRaises(TypeError, ndt, "array of 2 * int64")
641
+ self.assertRaises(TypeError, ndt, "array of var * int64")
547
642
 
548
643
 
549
644
  class TestTuple(unittest.TestCase):
@@ -564,6 +659,7 @@ class TestTuple(unittest.TestCase):
564
659
 
565
660
  self.assertTrue(t.is_c_contiguous())
566
661
  self.assertTrue(t.is_f_contiguous())
662
+ self.assertTrue(t.is_var_contiguous())
567
663
 
568
664
  for s in ["(Any)", "(int64, N * M * uint8)", "(string, Float)"]:
569
665
  t = ndt(s)
@@ -580,6 +676,7 @@ class TestTuple(unittest.TestCase):
580
676
 
581
677
  self.assertFalse(t.is_c_contiguous())
582
678
  self.assertFalse(t.is_f_contiguous())
679
+ self.assertFalse(t.is_var_contiguous())
583
680
 
584
681
  def test_tuple_common_fields(self):
585
682
  f = "{a: complex64, b: string}"
@@ -592,8 +689,8 @@ class TestTuple(unittest.TestCase):
592
689
  self.assertEqual(t.itemsize, 2 * field.itemsize)
593
690
  self.assertEqual(t.align, field.align)
594
691
 
595
- self.assertRaises(TypeError, t, 'shape')
596
- self.assertRaises(TypeError, t, 'strides')
692
+ self.assertEqual(t.shape, ())
693
+ self.assertEqual(t.strides, ())
597
694
 
598
695
 
599
696
  class TestRecord(unittest.TestCase):
@@ -614,6 +711,7 @@ class TestRecord(unittest.TestCase):
614
711
 
615
712
  self.assertTrue(t.is_c_contiguous())
616
713
  self.assertTrue(t.is_f_contiguous())
714
+ self.assertTrue(t.is_var_contiguous())
617
715
 
618
716
  for s in ["{a: Any, b: Complex}", "{x: N * M * T}"]:
619
717
  t = ndt(s)
@@ -630,6 +728,7 @@ class TestRecord(unittest.TestCase):
630
728
 
631
729
  self.assertFalse(t.is_c_contiguous())
632
730
  self.assertFalse(t.is_f_contiguous())
731
+ self.assertFalse(t.is_var_contiguous())
633
732
 
634
733
  def test_record_common_fields(self):
635
734
  f = "{a: complex64, b: string}"
@@ -642,8 +741,63 @@ class TestRecord(unittest.TestCase):
642
741
  self.assertEqual(t.itemsize, 3 * field.itemsize)
643
742
  self.assertEqual(t.align, field.align)
644
743
 
645
- self.assertRaises(TypeError, t, 'shape')
646
- self.assertRaises(TypeError, t, 'strides')
744
+ self.assertEqual(t.shape, ())
745
+ self.assertEqual(t.strides, ())
746
+
747
+
748
+ class TestUnion(unittest.TestCase):
749
+
750
+ def test_union_predicates(self):
751
+ for s in ["[A of int64 | B of bytes]", "[X of string | Y of uint8]"]:
752
+ t = ndt(s)
753
+ check_serialize(self, t)
754
+
755
+ self.assertFalse(t.isabstract())
756
+ self.assertFalse(t.iscomplex())
757
+ self.assertTrue(t.isconcrete())
758
+ self.assertFalse(t.isfloat())
759
+ self.assertFalse(t.isoptional())
760
+ self.assertFalse(t.isscalar())
761
+ self.assertFalse(t.issigned())
762
+ self.assertFalse(t.isunsigned())
763
+
764
+ self.assertTrue(t.is_c_contiguous())
765
+ self.assertTrue(t.is_f_contiguous())
766
+ self.assertTrue(t.is_var_contiguous())
767
+
768
+ for s in ["[A of Any | B of Complex]", "[X of N * M * T]"]:
769
+ t = ndt(s)
770
+ check_serialize(self, t)
771
+
772
+ self.assertTrue(t.isabstract())
773
+ self.assertFalse(t.iscomplex())
774
+ self.assertFalse(t.isconcrete())
775
+ self.assertFalse(t.isfloat())
776
+ self.assertFalse(t.isoptional())
777
+ self.assertFalse(t.isscalar())
778
+ self.assertFalse(t.issigned())
779
+ self.assertFalse(t.isunsigned())
780
+
781
+ self.assertFalse(t.is_c_contiguous())
782
+ self.assertFalse(t.is_f_contiguous())
783
+ self.assertFalse(t.is_var_contiguous())
784
+
785
+ def test_union_common_fields(self):
786
+ f = "[A of uint64 | B of uint8]"
787
+ g = "[C of (uint64, uint64) | D of string]"
788
+ t = ndt("[X of %s | Y of %s]" % (f, g))
789
+ u = ndt("(uint64, uint64)")
790
+
791
+ check_serialize(self, t)
792
+
793
+ a = ndt(g)
794
+
795
+ self.assertEqual(t.ndim, 0)
796
+ self.assertEqual(t.itemsize, u.itemsize + 2)
797
+ self.assertEqual(t.align, 1)
798
+
799
+ self.assertEqual(t.shape, ())
800
+ self.assertEqual(t.strides, ())
647
801
 
648
802
 
649
803
  class TestRef(unittest.TestCase):
@@ -664,6 +818,7 @@ class TestRef(unittest.TestCase):
664
818
 
665
819
  self.assertTrue(t.is_c_contiguous())
666
820
  self.assertTrue(t.is_f_contiguous())
821
+ self.assertTrue(t.is_var_contiguous())
667
822
 
668
823
  for s in ["&Any", "&(int64, N * M * uint8)"]:
669
824
  t = ndt(s)
@@ -680,6 +835,7 @@ class TestRef(unittest.TestCase):
680
835
 
681
836
  self.assertFalse(t.is_c_contiguous())
682
837
  self.assertFalse(t.is_f_contiguous())
838
+ self.assertFalse(t.is_var_contiguous())
683
839
 
684
840
  def test_ref_common_fields(self):
685
841
  a = "{a: complex64, b: string}"
@@ -691,8 +847,8 @@ class TestRef(unittest.TestCase):
691
847
  self.assertEqual(t.itemsize, SIZEOF_PTR)
692
848
  self.assertEqual(t.align, SIZEOF_PTR)
693
849
 
694
- self.assertRaises(TypeError, t, 'shape')
695
- self.assertRaises(TypeError, t, 'strides')
850
+ self.assertEqual(t.shape, ())
851
+ self.assertEqual(t.strides, ())
696
852
 
697
853
 
698
854
  class TestConstr(unittest.TestCase):
@@ -713,6 +869,7 @@ class TestConstr(unittest.TestCase):
713
869
 
714
870
  self.assertTrue(t.is_c_contiguous())
715
871
  self.assertTrue(t.is_f_contiguous())
872
+ self.assertTrue(t.is_var_contiguous())
716
873
 
717
874
  def test_constr_common_fields(self):
718
875
  a = "{a: complex64, b: string}"
@@ -725,8 +882,8 @@ class TestConstr(unittest.TestCase):
725
882
  self.assertEqual(t.itemsize, arg.itemsize)
726
883
  self.assertEqual(t.align, arg.align)
727
884
 
728
- self.assertRaises(TypeError, t, 'shape')
729
- self.assertRaises(TypeError, t, 'strides')
885
+ self.assertEqual(t.shape, ())
886
+ self.assertEqual(t.strides, ())
730
887
 
731
888
 
732
889
  class TestNominal(unittest.TestCase):
@@ -757,6 +914,7 @@ class TestNominal(unittest.TestCase):
757
914
 
758
915
  self.assertTrue(t.is_c_contiguous())
759
916
  self.assertTrue(t.is_f_contiguous())
917
+ self.assertTrue(t.is_var_contiguous())
760
918
 
761
919
  def test_nominal_common_fields(self):
762
920
  t = ndt("some_t")
@@ -769,8 +927,8 @@ class TestNominal(unittest.TestCase):
769
927
  self.assertEqual(t.itemsize, 2 * 10 * dtype.itemsize)
770
928
  self.assertEqual(t.align, dtype.align)
771
929
 
772
- self.assertRaises(TypeError, t, 'shape')
773
- self.assertRaises(TypeError, t, 'strides')
930
+ self.assertEqual(t.shape, ())
931
+ self.assertEqual(t.strides, ())
774
932
 
775
933
  def test_nominal_exceptions(self):
776
934
  # not in the typedef table
@@ -797,17 +955,18 @@ class TestScalarKind(unittest.TestCase):
797
955
 
798
956
  self.assertFalse(t.is_c_contiguous())
799
957
  self.assertFalse(t.is_f_contiguous())
958
+ self.assertFalse(t.is_var_contiguous())
800
959
 
801
960
  def test_scalar_kind_common_fields(self):
802
961
  t = ndt("Scalar")
803
962
  check_serialize(self, t)
804
963
 
805
- self.assertRaises(TypeError, t, 'ndim')
806
- self.assertRaises(TypeError, t, 'itemsize')
807
- self.assertRaises(TypeError, t, 'align')
964
+ self.assertRaises(TypeError, getattr, t, 'ndim')
965
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
966
+ self.assertRaises(TypeError, getattr, t, 'align')
808
967
 
809
- self.assertRaises(TypeError, t, 'shape')
810
- self.assertRaises(TypeError, t, 'strides')
968
+ self.assertRaises(TypeError, getattr, t, 'shape')
969
+ self.assertRaises(TypeError, getattr, t, 'strides')
811
970
 
812
971
 
813
972
  class TestCategorical(unittest.TestCase):
@@ -832,6 +991,7 @@ class TestCategorical(unittest.TestCase):
832
991
 
833
992
  self.assertTrue(t.is_c_contiguous())
834
993
  self.assertTrue(t.is_f_contiguous())
994
+ self.assertTrue(t.is_var_contiguous())
835
995
 
836
996
  def test_categorical_common_fields(self):
837
997
  t = ndt("categorical(NA, 'something', 'must', 'be', 'done')")
@@ -842,8 +1002,8 @@ class TestCategorical(unittest.TestCase):
842
1002
  self.assertEqual(t.itemsize, 8)
843
1003
  self.assertEqual(t.align, 8)
844
1004
 
845
- self.assertRaises(TypeError, t, 'shape')
846
- self.assertRaises(TypeError, t, 'strides')
1005
+ self.assertEqual(t.shape, ())
1006
+ self.assertEqual(t.strides, ())
847
1007
 
848
1008
 
849
1009
  class TestFixedStringKind(unittest.TestCase):
@@ -863,16 +1023,17 @@ class TestFixedStringKind(unittest.TestCase):
863
1023
 
864
1024
  self.assertFalse(t.is_c_contiguous())
865
1025
  self.assertFalse(t.is_f_contiguous())
1026
+ self.assertFalse(t.is_var_contiguous())
866
1027
 
867
1028
  def test_fixed_string_kind_common_fields(self):
868
1029
  t = ndt("FixedString")
869
1030
 
870
- self.assertRaises(TypeError, t, 'ndim')
871
- self.assertRaises(TypeError, t, 'itemsize')
872
- self.assertRaises(TypeError, t, 'align')
1031
+ self.assertRaises(TypeError, getattr, t, 'ndim')
1032
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
1033
+ self.assertRaises(TypeError, getattr, t, 'align')
873
1034
 
874
- self.assertRaises(TypeError, t, 'shape')
875
- self.assertRaises(TypeError, t, 'strides')
1035
+ self.assertRaises(TypeError, getattr, t, 'shape')
1036
+ self.assertRaises(TypeError, getattr, t, 'strides')
876
1037
 
877
1038
 
878
1039
  class TestFixedString(unittest.TestCase):
@@ -892,6 +1053,7 @@ class TestFixedString(unittest.TestCase):
892
1053
 
893
1054
  self.assertTrue(t.is_c_contiguous())
894
1055
  self.assertTrue(t.is_f_contiguous())
1056
+ self.assertTrue(t.is_var_contiguous())
895
1057
 
896
1058
  def test_fixed_string_common_fields(self):
897
1059
  for encoding, codepoint_size in [
@@ -908,8 +1070,8 @@ class TestFixedString(unittest.TestCase):
908
1070
  self.assertEqual(t.itemsize, 20 * codepoint_size)
909
1071
  self.assertEqual(t.align, codepoint_size)
910
1072
 
911
- self.assertRaises(TypeError, t, 'shape')
912
- self.assertRaises(TypeError, t, 'strides')
1073
+ self.assertEqual(t.shape, ())
1074
+ self.assertEqual(t.strides, ())
913
1075
 
914
1076
 
915
1077
  class TestFixedBytesKind(unittest.TestCase):
@@ -929,16 +1091,17 @@ class TestFixedBytesKind(unittest.TestCase):
929
1091
 
930
1092
  self.assertFalse(t.is_c_contiguous())
931
1093
  self.assertFalse(t.is_f_contiguous())
1094
+ self.assertFalse(t.is_var_contiguous())
932
1095
 
933
1096
  def test_fixed_string_kind_common_fields(self):
934
1097
  t = ndt("FixedBytes")
935
1098
 
936
- self.assertRaises(TypeError, t, 'ndim')
937
- self.assertRaises(TypeError, t, 'itemsize')
938
- self.assertRaises(TypeError, t, 'align')
1099
+ self.assertRaises(TypeError, getattr, t, 'ndim')
1100
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
1101
+ self.assertRaises(TypeError, getattr, t, 'align')
939
1102
 
940
- self.assertRaises(TypeError, t, 'shape')
941
- self.assertRaises(TypeError, t, 'strides')
1103
+ self.assertRaises(TypeError, getattr, t, 'shape')
1104
+ self.assertRaises(TypeError, getattr, t, 'strides')
942
1105
 
943
1106
 
944
1107
  class TestFixedBytes(unittest.TestCase):
@@ -958,6 +1121,7 @@ class TestFixedBytes(unittest.TestCase):
958
1121
 
959
1122
  self.assertTrue(t.is_c_contiguous())
960
1123
  self.assertTrue(t.is_f_contiguous())
1124
+ self.assertTrue(t.is_var_contiguous())
961
1125
 
962
1126
  def test_fixed_bytes_common_fields(self):
963
1127
  for align in [1,2,4,8,16,32,64]:
@@ -970,8 +1134,8 @@ class TestFixedBytes(unittest.TestCase):
970
1134
  self.assertEqual(t.itemsize, 1024)
971
1135
  self.assertEqual(t.align, align)
972
1136
 
973
- self.assertRaises(TypeError, t, 'shape')
974
- self.assertRaises(TypeError, t, 'strides')
1137
+ self.assertEqual(t.shape, ())
1138
+ self.assertEqual(t.strides, ())
975
1139
 
976
1140
  def test_fixed_bytes_exceptions(self):
977
1141
  # Data size must be a multiple of align.
@@ -995,6 +1159,7 @@ class TestString(unittest.TestCase):
995
1159
 
996
1160
  self.assertTrue(t.is_c_contiguous())
997
1161
  self.assertTrue(t.is_f_contiguous())
1162
+ self.assertTrue(t.is_var_contiguous())
998
1163
 
999
1164
  def test_string_common_fields(self):
1000
1165
  t = ndt("string")
@@ -1003,8 +1168,8 @@ class TestString(unittest.TestCase):
1003
1168
  self.assertEqual(t.itemsize, SIZEOF_PTR)
1004
1169
  self.assertEqual(t.align, SIZEOF_PTR)
1005
1170
 
1006
- self.assertRaises(TypeError, t, 'shape')
1007
- self.assertRaises(TypeError, t, 'strides')
1171
+ self.assertEqual(t.shape, ())
1172
+ self.assertEqual(t.strides, ())
1008
1173
 
1009
1174
 
1010
1175
  class TestBytes(unittest.TestCase):
@@ -1024,6 +1189,7 @@ class TestBytes(unittest.TestCase):
1024
1189
 
1025
1190
  self.assertTrue(t.is_c_contiguous())
1026
1191
  self.assertTrue(t.is_f_contiguous())
1192
+ self.assertTrue(t.is_var_contiguous())
1027
1193
 
1028
1194
  def test_bytes_common_fields(self):
1029
1195
  t = ndt("bytes")
@@ -1033,8 +1199,8 @@ class TestBytes(unittest.TestCase):
1033
1199
  self.assertEqual(t.itemsize, 16)
1034
1200
  self.assertEqual(t.align, 8)
1035
1201
 
1036
- self.assertRaises(TypeError, t, 'shape')
1037
- self.assertRaises(TypeError, t, 'strides')
1202
+ self.assertEqual(t.shape, ())
1203
+ self.assertEqual(t.strides, ())
1038
1204
 
1039
1205
 
1040
1206
  class TestChar(unittest.TestCase):
@@ -1054,6 +1220,7 @@ class TestChar(unittest.TestCase):
1054
1220
 
1055
1221
  self.assertTrue(t.is_c_contiguous())
1056
1222
  self.assertTrue(t.is_f_contiguous())
1223
+ self.assertTrue(t.is_var_contiguous())
1057
1224
 
1058
1225
  def test_char_common_fields(self):
1059
1226
  t = ndt("char('utf32')")
@@ -1063,8 +1230,8 @@ class TestChar(unittest.TestCase):
1063
1230
  self.assertEqual(t.itemsize, 4)
1064
1231
  self.assertEqual(t.align, 4)
1065
1232
 
1066
- self.assertRaises(TypeError, t, 'shape')
1067
- self.assertRaises(TypeError, t, 'strides')
1233
+ self.assertEqual(t.shape, ())
1234
+ self.assertEqual(t.strides, ())
1068
1235
 
1069
1236
 
1070
1237
  class TestBool(unittest.TestCase):
@@ -1084,6 +1251,7 @@ class TestBool(unittest.TestCase):
1084
1251
 
1085
1252
  self.assertTrue(t.is_c_contiguous())
1086
1253
  self.assertTrue(t.is_f_contiguous())
1254
+ self.assertTrue(t.is_var_contiguous())
1087
1255
 
1088
1256
  def test_bool_common_fields(self):
1089
1257
  t = ndt("bool")
@@ -1092,8 +1260,8 @@ class TestBool(unittest.TestCase):
1092
1260
  self.assertEqual(t.itemsize, 1)
1093
1261
  self.assertEqual(t.align, 1)
1094
1262
 
1095
- self.assertRaises(TypeError, t, 'shape')
1096
- self.assertRaises(TypeError, t, 'strides')
1263
+ self.assertEqual(t.shape, ())
1264
+ self.assertEqual(t.strides, ())
1097
1265
 
1098
1266
 
1099
1267
  class TestSignedKind(unittest.TestCase):
@@ -1113,16 +1281,17 @@ class TestSignedKind(unittest.TestCase):
1113
1281
 
1114
1282
  self.assertFalse(t.is_c_contiguous())
1115
1283
  self.assertFalse(t.is_f_contiguous())
1284
+ self.assertFalse(t.is_var_contiguous())
1116
1285
 
1117
1286
  def test_signed_kind_common_fields(self):
1118
1287
  t = ndt("Signed")
1119
1288
 
1120
- self.assertRaises(TypeError, t, 'ndim')
1121
- self.assertRaises(TypeError, t, 'itemsize')
1122
- self.assertRaises(TypeError, t, 'align')
1289
+ self.assertRaises(TypeError, getattr, t, 'ndim')
1290
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
1291
+ self.assertRaises(TypeError, getattr, t, 'align')
1123
1292
 
1124
- self.assertRaises(TypeError, t, 'shape')
1125
- self.assertRaises(TypeError, t, 'strides')
1293
+ self.assertRaises(TypeError, getattr, t, 'shape')
1294
+ self.assertRaises(TypeError, getattr, t, 'strides')
1126
1295
 
1127
1296
 
1128
1297
  class TestSigned(unittest.TestCase):
@@ -1145,6 +1314,7 @@ class TestSigned(unittest.TestCase):
1145
1314
 
1146
1315
  self.assertTrue(t.is_c_contiguous())
1147
1316
  self.assertTrue(t.is_f_contiguous())
1317
+ self.assertTrue(t.is_var_contiguous())
1148
1318
 
1149
1319
  def test_signed_common_fields(self):
1150
1320
  for s, itemsize in [
@@ -1160,8 +1330,8 @@ class TestSigned(unittest.TestCase):
1160
1330
  self.assertEqual(t.itemsize, itemsize)
1161
1331
  self.assertEqual(t.align, itemsize)
1162
1332
 
1163
- self.assertRaises(TypeError, t, 'shape')
1164
- self.assertRaises(TypeError, t, 'shape')
1333
+ self.assertEqual(t.shape, ())
1334
+ self.assertEqual(t.strides, ())
1165
1335
 
1166
1336
 
1167
1337
  class TestUnsignedKind(unittest.TestCase):
@@ -1181,16 +1351,17 @@ class TestUnsignedKind(unittest.TestCase):
1181
1351
 
1182
1352
  self.assertFalse(t.is_c_contiguous())
1183
1353
  self.assertFalse(t.is_f_contiguous())
1354
+ self.assertFalse(t.is_var_contiguous())
1184
1355
 
1185
1356
  def test_unsigned_kind_common_fields(self):
1186
1357
  t = ndt("Unsigned")
1187
1358
 
1188
- self.assertRaises(TypeError, t, 'ndim')
1189
- self.assertRaises(TypeError, t, 'itemsize')
1190
- self.assertRaises(TypeError, t, 'align')
1359
+ self.assertRaises(TypeError, getattr, t, 'ndim')
1360
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
1361
+ self.assertRaises(TypeError, getattr, t, 'align')
1191
1362
 
1192
- self.assertRaises(TypeError, t, 'shape')
1193
- self.assertRaises(TypeError, t, 'strides')
1363
+ self.assertRaises(TypeError, getattr, t, 'shape')
1364
+ self.assertRaises(TypeError, getattr, t, 'strides')
1194
1365
 
1195
1366
 
1196
1367
  class TestUnsigned(unittest.TestCase):
@@ -1213,6 +1384,7 @@ class TestUnsigned(unittest.TestCase):
1213
1384
 
1214
1385
  self.assertTrue(t.is_c_contiguous())
1215
1386
  self.assertTrue(t.is_f_contiguous())
1387
+ self.assertTrue(t.is_var_contiguous())
1216
1388
 
1217
1389
  def test_unsigned_common_fields(self):
1218
1390
  for s, itemsize in [
@@ -1228,8 +1400,8 @@ class TestUnsigned(unittest.TestCase):
1228
1400
  self.assertEqual(t.itemsize, itemsize)
1229
1401
  self.assertEqual(t.align, itemsize)
1230
1402
 
1231
- self.assertRaises(TypeError, t, 'shape')
1232
- self.assertRaises(TypeError, t, 'shape')
1403
+ self.assertEqual(t.shape, ())
1404
+ self.assertEqual(t.strides, ())
1233
1405
 
1234
1406
 
1235
1407
  class TestFloatKind(unittest.TestCase):
@@ -1249,25 +1421,24 @@ class TestFloatKind(unittest.TestCase):
1249
1421
 
1250
1422
  self.assertFalse(t.is_c_contiguous())
1251
1423
  self.assertFalse(t.is_f_contiguous())
1424
+ self.assertFalse(t.is_var_contiguous())
1252
1425
 
1253
1426
  def test_float_kind_common_fields(self):
1254
1427
  t = ndt("Float")
1255
1428
  check_serialize(self, t)
1256
1429
 
1257
- self.assertRaises(TypeError, t, 'ndim')
1258
- self.assertRaises(TypeError, t, 'itemsize')
1259
- self.assertRaises(TypeError, t, 'align')
1430
+ self.assertRaises(TypeError, getattr, t, 'ndim')
1431
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
1432
+ self.assertRaises(TypeError, getattr, t, 'align')
1260
1433
 
1261
- self.assertRaises(TypeError, t, 'shape')
1262
- self.assertRaises(TypeError, t, 'strides')
1434
+ self.assertRaises(TypeError, getattr, t, 'shape')
1435
+ self.assertRaises(TypeError, getattr, t, 'strides')
1263
1436
 
1264
1437
 
1265
1438
  class TestFloat(unittest.TestCase):
1266
1439
 
1267
1440
  def test_float_predicates(self):
1268
- _float = ['float32', 'float64']
1269
- if HAVE_PYTHON_36:
1270
- _float.insert(0, 'float16')
1441
+ _float = ['bfloat16', 'float16', 'float32', 'float64']
1271
1442
 
1272
1443
  for s in _float:
1273
1444
  t = ndt(s)
@@ -1284,11 +1455,10 @@ class TestFloat(unittest.TestCase):
1284
1455
 
1285
1456
  self.assertTrue(t.is_c_contiguous())
1286
1457
  self.assertTrue(t.is_f_contiguous())
1458
+ self.assertTrue(t.is_var_contiguous())
1287
1459
 
1288
1460
  def test_float_common_fields(self):
1289
- _float = [('float32', 4), ('float64', 8)]
1290
- if HAVE_PYTHON_36:
1291
- _float.insert(0, ('float16', 2))
1461
+ _float = [('bfloat16', 2), ('float16', 2), ('float32', 4), ('float64', 8)]
1292
1462
 
1293
1463
  for s, itemsize in _float:
1294
1464
  t = ndt(s)
@@ -1298,8 +1468,8 @@ class TestFloat(unittest.TestCase):
1298
1468
  self.assertEqual(t.itemsize, itemsize)
1299
1469
  self.assertEqual(t.align, itemsize)
1300
1470
 
1301
- self.assertRaises(TypeError, t, 'shape')
1302
- self.assertRaises(TypeError, t, 'shape')
1471
+ self.assertEqual(t.shape, ())
1472
+ self.assertEqual(t.strides, ())
1303
1473
 
1304
1474
 
1305
1475
  class TestComplexKind(unittest.TestCase):
@@ -1319,24 +1489,23 @@ class TestComplexKind(unittest.TestCase):
1319
1489
 
1320
1490
  self.assertFalse(t.is_c_contiguous())
1321
1491
  self.assertFalse(t.is_f_contiguous())
1492
+ self.assertFalse(t.is_var_contiguous())
1322
1493
 
1323
1494
  def test_complex_kind_common_fields(self):
1324
1495
  t = ndt("Complex")
1325
1496
 
1326
- self.assertRaises(TypeError, t, 'ndim')
1327
- self.assertRaises(TypeError, t, 'itemsize')
1328
- self.assertRaises(TypeError, t, 'align')
1497
+ self.assertRaises(TypeError, getattr, t, 'ndim')
1498
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
1499
+ self.assertRaises(TypeError, getattr, t, 'align')
1329
1500
 
1330
- self.assertRaises(TypeError, t, 'shape')
1331
- self.assertRaises(TypeError, t, 'strides')
1501
+ self.assertRaises(TypeError, getattr, t, 'shape')
1502
+ self.assertRaises(TypeError, getattr, t, 'strides')
1332
1503
 
1333
1504
 
1334
1505
  class TestComplex(unittest.TestCase):
1335
1506
 
1336
1507
  def test_complex_predicates(self):
1337
- _complex = ['complex64', 'complex128']
1338
- if HAVE_PYTHON_36:
1339
- _complex.insert(0, 'complex32')
1508
+ _complex = ['bcomplex32', 'complex32', 'complex64', 'complex128']
1340
1509
 
1341
1510
  for s in _complex:
1342
1511
  t = ndt(s)
@@ -1353,11 +1522,10 @@ class TestComplex(unittest.TestCase):
1353
1522
 
1354
1523
  self.assertTrue(t.is_c_contiguous())
1355
1524
  self.assertTrue(t.is_f_contiguous())
1525
+ self.assertTrue(t.is_var_contiguous())
1356
1526
 
1357
1527
  def test_complex_common_fields(self):
1358
- _complex = [('complex64', 8), ('complex128', 16)]
1359
- if HAVE_PYTHON_36:
1360
- _complex.insert(0, ('complex32', 4))
1528
+ _complex = [('bcomplex32', 4), ('complex32', 4), ('complex64', 8), ('complex128', 16)]
1361
1529
 
1362
1530
  for s, itemsize in _complex:
1363
1531
  t = ndt(s)
@@ -1367,8 +1535,8 @@ class TestComplex(unittest.TestCase):
1367
1535
  self.assertEqual(t.itemsize, itemsize)
1368
1536
  self.assertEqual(t.align, itemsize // 2)
1369
1537
 
1370
- self.assertRaises(TypeError, t, 'shape')
1371
- self.assertRaises(TypeError, t, 'shape')
1538
+ self.assertEqual(t.shape, ())
1539
+ self.assertEqual(t.strides, ())
1372
1540
 
1373
1541
 
1374
1542
  class TestTypevar(unittest.TestCase):
@@ -1388,16 +1556,17 @@ class TestTypevar(unittest.TestCase):
1388
1556
 
1389
1557
  self.assertFalse(t.is_c_contiguous())
1390
1558
  self.assertFalse(t.is_f_contiguous())
1559
+ self.assertFalse(t.is_var_contiguous())
1391
1560
 
1392
1561
  def test_typevar_common_fields(self):
1393
1562
  t = ndt("T")
1394
1563
 
1395
- self.assertRaises(TypeError, t, 'ndim')
1396
- self.assertRaises(TypeError, t, 'itemsize')
1397
- self.assertRaises(TypeError, t, 'align')
1564
+ self.assertRaises(TypeError, getattr, t, 'ndim')
1565
+ self.assertRaises(TypeError, getattr, t, 'itemsize')
1566
+ self.assertRaises(TypeError, getattr, t, 'align')
1398
1567
 
1399
- self.assertRaises(TypeError, t, 'shape')
1400
- self.assertRaises(TypeError, t, 'strides')
1568
+ self.assertRaises(TypeError, getattr, t, 'shape')
1569
+ self.assertRaises(TypeError, getattr, t, 'strides')
1401
1570
 
1402
1571
 
1403
1572
  class TestCopy(unittest.TestCase):
@@ -1450,7 +1619,7 @@ class TestBufferProtocol(unittest.TestCase):
1450
1619
  ("(2,19)T{<b:a:xxxQ:b:}", 12, 4),
1451
1620
  ("(31,221)T{<b:a:xxxxxxxQ:b:}", 16, 8),
1452
1621
  ("(2,3,10)T{<b:a:xxxxxxxxxxxxxxxQ:b:xxxxxxxx}", 32, 16),
1453
- ("(2,10)T{=L:a:(2,3)D:b:}", 100, 1)]
1622
+ ("(2,10)T{=L:a:(2,3)Zd:b:}", 100, 1)]
1454
1623
 
1455
1624
  test_error_cases = [
1456
1625
  # empty shape (scalars are not arrays in datashape)
@@ -1524,13 +1693,10 @@ class TestBufferProtocol(unittest.TestCase):
1524
1693
  'c', 'b', 'B',
1525
1694
  'h', 'i', 'l', 'q',
1526
1695
  'H', 'I', 'L', 'Q',
1527
- 'f', 'd']
1696
+ 'e', 'f', 'd']
1528
1697
 
1529
1698
  native = ['n', 'N']
1530
1699
 
1531
- if HAVE_PYTHON_36:
1532
- standard += ['e']
1533
-
1534
1700
  for fmt in standard:
1535
1701
  for modifier in ['', '@', '=', '<', '>', '!']:
1536
1702
  f = modifier + fmt
@@ -1553,17 +1719,16 @@ class TestBufferProtocol(unittest.TestCase):
1553
1719
  self.assertRaises(ValueError, ndt.from_format, f)
1554
1720
  self.assertRaises(struct.error, struct.Struct, f)
1555
1721
 
1556
- if HAVE_PYTHON_36:
1557
- # complex32
1558
- fmt = 'E'
1559
- for modifier in ['', '@', '=', '<', '>', '!']:
1560
- f = modifier + fmt
1561
- t = ndt.from_format(f)
1562
- if not HAVE_32_BIT_LINUX:
1563
- self.assertEqual(t.itemsize, 4)
1722
+ # complex32
1723
+ fmt = 'Ze'
1724
+ for modifier in ['', '@', '=', '<', '>', '!']:
1725
+ f = modifier + fmt
1726
+ t = ndt.from_format(f)
1727
+ if not HAVE_32_BIT_LINUX:
1728
+ self.assertEqual(t.itemsize, 4)
1564
1729
 
1565
1730
  # complex64
1566
- fmt = 'F'
1731
+ fmt = 'Zf'
1567
1732
  for modifier in ['', '@', '=', '<', '>', '!']:
1568
1733
  f = modifier + fmt
1569
1734
  t = ndt.from_format(f)
@@ -1571,7 +1736,7 @@ class TestBufferProtocol(unittest.TestCase):
1571
1736
  self.assertEqual(t.itemsize, 8)
1572
1737
 
1573
1738
  # complex128
1574
- fmt = 'D'
1739
+ fmt = 'Zd'
1575
1740
  for modifier in ['', '@', '=', '<', '>', '!']:
1576
1741
  f = modifier + fmt
1577
1742
  t = ndt.from_format(f)
@@ -1703,6 +1868,38 @@ class TestMatch(unittest.TestCase):
1703
1868
  self.assertFalse(p.match(c))
1704
1869
 
1705
1870
 
1871
+ class TestUnify(unittest.TestCase):
1872
+
1873
+ def test_unify(self):
1874
+
1875
+ t = ndt("2 * 3 * float32")
1876
+ u = ndt("2 * 3 * float32")
1877
+ w = t.unify(u)
1878
+ self.assertEqual(w, ndt("2 * 3 * float32"))
1879
+
1880
+ t = ndt("2 * 3 * float32")
1881
+ u = ndt("2 * 3 * ?float64")
1882
+ w = t.unify(u)
1883
+ self.assertEqual(w, ndt("2 * 3 * ?float64"))
1884
+
1885
+ t = ndt("2 * 3 * (?Any, int64)")
1886
+ u = ndt("2 * 3 * (float64, Any)")
1887
+ w = t.unify(u)
1888
+ self.assertEqual(w, ndt("2 * 3 * (?float64, int64)"))
1889
+
1890
+ t = ndt("var(offsets=[0,2]) * var(offsets=[0,3,10]) * (int64, complex128)")
1891
+ u = ndt("var(offsets=[0,2]) * var(offsets=[0,3,10]) * ?(int8, complex64)")
1892
+ w = t.unify(u)
1893
+ del t
1894
+ del u
1895
+ gc.collect()
1896
+ self.assertEqual(w, ndt("var(offsets=[0,2]) * var(offsets=[0,3,10]) * ?(int64, complex128)"))
1897
+
1898
+ x = copy(w)
1899
+ del(w)
1900
+ self.assertEqual(x, ndt("var(offsets=[0,2]) * var(offsets=[0,3,10]) * ?(int64, complex128)"))
1901
+
1902
+
1706
1903
  class TestApply(unittest.TestCase):
1707
1904
 
1708
1905
  def test_apply(self):
@@ -1714,13 +1911,14 @@ class TestApply(unittest.TestCase):
1714
1911
 
1715
1912
 
1716
1913
  # Argument types:
1717
- in_types = [ndt("20 * 2 * 3 * int64"), ndt("20 * 3 * 4 * int64")]
1914
+ types = [ndt("20 * 2 * 3 * int64"), ndt("20 * 3 * 4 * int64")]
1718
1915
 
1719
- spec = sig.apply(in_types)
1720
- self.assertEqual(spec.sig, sig)
1721
- self.assertEqual(spec.in_types, in_types)
1722
- self.assertSequenceEqual(spec.out_types, [ndt("20 * 2 * 4 * float64")])
1916
+ spec = sig.apply(*types)
1723
1917
  self.assertEqual(spec.outer_dims, 1)
1918
+ self.assertEqual(spec.nin, 2)
1919
+ self.assertEqual(spec.nout, 1)
1920
+ self.assertEqual(spec.nargs, 3)
1921
+ self.assertEqual(spec.types, types + [ndt("20 * 2 * 4 * float64")])
1724
1922
 
1725
1923
  def test_apply_error(self):
1726
1924
 
@@ -1731,8 +1929,8 @@ class TestApply(unittest.TestCase):
1731
1929
  ["20 * 2 * 100 * int64", "20 * 3 * 4 * int64"]]
1732
1930
 
1733
1931
  for l in lst:
1734
- in_types = [ndt(x) for x in l]
1735
- self.assertRaises(TypeError, sig.apply, in_types)
1932
+ types = [ndt(x) for x in l]
1933
+ self.assertRaises(TypeError, sig.apply, types)
1736
1934
 
1737
1935
 
1738
1936
  def from_shape_strides(shape, strides):
@@ -1745,12 +1943,19 @@ class TestBroadcast(unittest.TestCase):
1745
1943
 
1746
1944
  def test_broadcast(self):
1747
1945
 
1748
- for c in BROADCAST_TEST_CASES:
1749
- spec = c.sig.apply(c.in_types)
1946
+ for d in BROADCAST_TEST_CASES:
1947
+ sig, args, kwargs, expected = d.values()
1948
+ spec = sig.apply(*args, out=kwargs)
1949
+
1950
+ msg = str(sig)
1750
1951
 
1751
- self.assertEqual(len(spec), len(c))
1752
- for v, u in zip(spec, c):
1753
- self.assertEqual(v, u)
1952
+ self.assertEqual(len(spec), len(expected), msg=msg)
1953
+ self.assertEqual(spec.flags, expected.flags, msg=msg)
1954
+ self.assertEqual(spec.outer_dims, expected.outer_dims, msg=msg)
1955
+ self.assertEqual(spec.nin, expected.nin, msg=msg)
1956
+ self.assertEqual(spec.nout, expected.nout, msg=msg)
1957
+ self.assertEqual(spec.nargs, expected.nargs, msg=msg)
1958
+ self.assertEqual(spec.types, expected.types, msg=msg)
1754
1959
 
1755
1960
  def test_against_numpy(self):
1756
1961
 
@@ -1788,8 +1993,8 @@ class TestBroadcast(unittest.TestCase):
1788
1993
 
1789
1994
  t = from_shape_strides(xshape, xstrides)
1790
1995
  u = from_shape_strides(yshape, ystrides)
1791
- spec = sig.apply([t, u])
1792
- tt, uu = spec.in_broadcast
1996
+ spec = sig.apply(t, u)
1997
+ tt, uu = spec.types[:2]
1793
1998
 
1794
1999
  self.assertEqual(tt.shape, xx.shape)
1795
2000
  self.assertEqual(uu.shape, yy.shape)
@@ -1916,8 +2121,10 @@ ALL_TESTS = [
1916
2121
  TestVarDim,
1917
2122
  TestSymbolicDim,
1918
2123
  TestEllipsisDim,
2124
+ TestArray,
1919
2125
  TestTuple,
1920
2126
  TestRecord,
2127
+ TestUnion,
1921
2128
  TestRef,
1922
2129
  TestConstr,
1923
2130
  TestNominal,
@@ -1945,6 +2152,7 @@ ALL_TESTS = [
1945
2152
  TestConstruction,
1946
2153
  TestError,
1947
2154
  TestMatch,
2155
+ TestUnify,
1948
2156
  TestApply,
1949
2157
  TestBroadcast,
1950
2158
  TestTypedef,