amulet-core 2.0a5__cp311-cp311-macosx_10_9_universal2.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.

Potentially problematic release.


This version of amulet-core might be problematic. Click here for more details.

Files changed (210) hide show
  1. amulet/__init__.cpython-311-darwin.so +0 -0
  2. amulet/__init__.pyi +30 -0
  3. amulet/__pyinstaller/__init__.py +2 -0
  4. amulet/__pyinstaller/hook-amulet.py +4 -0
  5. amulet/_init.py +28 -0
  6. amulet/_version.py +21 -0
  7. amulet/biome.cpp +36 -0
  8. amulet/biome.hpp +43 -0
  9. amulet/biome.pyi +77 -0
  10. amulet/block.cpp +435 -0
  11. amulet/block.hpp +119 -0
  12. amulet/block.pyi +273 -0
  13. amulet/block_entity.cpp +12 -0
  14. amulet/block_entity.hpp +56 -0
  15. amulet/block_entity.pyi +80 -0
  16. amulet/chunk.cpp +16 -0
  17. amulet/chunk.hpp +99 -0
  18. amulet/chunk.pyi +30 -0
  19. amulet/chunk_/components/biome.py +155 -0
  20. amulet/chunk_/components/block_entity.py +117 -0
  21. amulet/chunk_/components/entity.py +64 -0
  22. amulet/chunk_/components/height_2d.py +16 -0
  23. amulet/chunk_components.pyi +95 -0
  24. amulet/collections.pyi +37 -0
  25. amulet/data_types.py +29 -0
  26. amulet/entity.py +180 -0
  27. amulet/errors.py +63 -0
  28. amulet/game/__init__.py +7 -0
  29. amulet/game/_game.py +152 -0
  30. amulet/game/_universal/__init__.py +1 -0
  31. amulet/game/_universal/_biome.py +17 -0
  32. amulet/game/_universal/_block.py +47 -0
  33. amulet/game/_universal/_version.py +68 -0
  34. amulet/game/abc/__init__.py +22 -0
  35. amulet/game/abc/_block_specification.py +150 -0
  36. amulet/game/abc/biome.py +213 -0
  37. amulet/game/abc/block.py +331 -0
  38. amulet/game/abc/game_version_container.py +25 -0
  39. amulet/game/abc/json_interface.py +27 -0
  40. amulet/game/abc/version.py +44 -0
  41. amulet/game/bedrock/__init__.py +1 -0
  42. amulet/game/bedrock/_biome.py +35 -0
  43. amulet/game/bedrock/_block.py +42 -0
  44. amulet/game/bedrock/_version.py +165 -0
  45. amulet/game/java/__init__.py +2 -0
  46. amulet/game/java/_biome.py +35 -0
  47. amulet/game/java/_block.py +60 -0
  48. amulet/game/java/_version.py +176 -0
  49. amulet/game/translate/__init__.py +12 -0
  50. amulet/game/translate/_functions/__init__.py +15 -0
  51. amulet/game/translate/_functions/_code_functions/__init__.py +0 -0
  52. amulet/game/translate/_functions/_code_functions/_text.py +553 -0
  53. amulet/game/translate/_functions/_code_functions/banner_pattern.py +67 -0
  54. amulet/game/translate/_functions/_code_functions/bedrock_chest_connection.py +152 -0
  55. amulet/game/translate/_functions/_code_functions/bedrock_moving_block_pos.py +88 -0
  56. amulet/game/translate/_functions/_code_functions/bedrock_sign.py +152 -0
  57. amulet/game/translate/_functions/_code_functions/bedrock_skull_rotation.py +16 -0
  58. amulet/game/translate/_functions/_code_functions/custom_name.py +146 -0
  59. amulet/game/translate/_functions/_frozen.py +66 -0
  60. amulet/game/translate/_functions/_state.py +54 -0
  61. amulet/game/translate/_functions/_typing.py +98 -0
  62. amulet/game/translate/_functions/abc.py +116 -0
  63. amulet/game/translate/_functions/carry_nbt.py +160 -0
  64. amulet/game/translate/_functions/carry_properties.py +80 -0
  65. amulet/game/translate/_functions/code.py +143 -0
  66. amulet/game/translate/_functions/map_block_name.py +66 -0
  67. amulet/game/translate/_functions/map_nbt.py +111 -0
  68. amulet/game/translate/_functions/map_properties.py +93 -0
  69. amulet/game/translate/_functions/multiblock.py +112 -0
  70. amulet/game/translate/_functions/new_block.py +42 -0
  71. amulet/game/translate/_functions/new_entity.py +43 -0
  72. amulet/game/translate/_functions/new_nbt.py +206 -0
  73. amulet/game/translate/_functions/new_properties.py +64 -0
  74. amulet/game/translate/_functions/sequence.py +51 -0
  75. amulet/game/translate/_functions/walk_input_nbt.py +331 -0
  76. amulet/game/translate/_translator.py +433 -0
  77. amulet/item.py +75 -0
  78. amulet/level/__init__.pyi +27 -0
  79. amulet/level/_load.py +100 -0
  80. amulet/level/abc/__init__.py +12 -0
  81. amulet/level/abc/_chunk_handle.py +335 -0
  82. amulet/level/abc/_dimension.py +86 -0
  83. amulet/level/abc/_history/__init__.py +1 -0
  84. amulet/level/abc/_history/_cache.py +224 -0
  85. amulet/level/abc/_history/_history_manager.py +291 -0
  86. amulet/level/abc/_level/__init__.py +5 -0
  87. amulet/level/abc/_level/_compactable_level.py +10 -0
  88. amulet/level/abc/_level/_creatable_level.py +29 -0
  89. amulet/level/abc/_level/_disk_level.py +17 -0
  90. amulet/level/abc/_level/_level.py +453 -0
  91. amulet/level/abc/_level/_loadable_level.py +42 -0
  92. amulet/level/abc/_player_storage.py +7 -0
  93. amulet/level/abc/_raw_level.py +187 -0
  94. amulet/level/abc/_registry.py +40 -0
  95. amulet/level/bedrock/__init__.py +2 -0
  96. amulet/level/bedrock/_chunk_handle.py +19 -0
  97. amulet/level/bedrock/_dimension.py +22 -0
  98. amulet/level/bedrock/_level.py +187 -0
  99. amulet/level/bedrock/_raw/__init__.py +5 -0
  100. amulet/level/bedrock/_raw/_actor_counter.py +53 -0
  101. amulet/level/bedrock/_raw/_chunk.py +54 -0
  102. amulet/level/bedrock/_raw/_chunk_decode.py +668 -0
  103. amulet/level/bedrock/_raw/_chunk_encode.py +602 -0
  104. amulet/level/bedrock/_raw/_constant.py +9 -0
  105. amulet/level/bedrock/_raw/_dimension.py +343 -0
  106. amulet/level/bedrock/_raw/_level.py +463 -0
  107. amulet/level/bedrock/_raw/_level_dat.py +90 -0
  108. amulet/level/bedrock/_raw/_typing.py +6 -0
  109. amulet/level/bedrock/_raw/leveldb_chunk_versions.py +83 -0
  110. amulet/level/bedrock/chunk/__init__.py +1 -0
  111. amulet/level/bedrock/chunk/_chunk.py +126 -0
  112. amulet/level/bedrock/chunk/components/__init__.py +0 -0
  113. amulet/level/bedrock/chunk/components/chunk_version.py +12 -0
  114. amulet/level/bedrock/chunk/components/finalised_state.py +13 -0
  115. amulet/level/bedrock/chunk/components/raw_chunk.py +15 -0
  116. amulet/level/construction/__init__.py +0 -0
  117. amulet/level/java/__init__.pyi +21 -0
  118. amulet/level/java/_chunk_handle.py +17 -0
  119. amulet/level/java/_chunk_handle.pyi +15 -0
  120. amulet/level/java/_dimension.py +20 -0
  121. amulet/level/java/_dimension.pyi +13 -0
  122. amulet/level/java/_level.py +184 -0
  123. amulet/level/java/_level.pyi +120 -0
  124. amulet/level/java/_raw/__init__.pyi +19 -0
  125. amulet/level/java/_raw/_chunk.pyi +23 -0
  126. amulet/level/java/_raw/_chunk_decode.py +561 -0
  127. amulet/level/java/_raw/_chunk_encode.py +463 -0
  128. amulet/level/java/_raw/_constant.py +9 -0
  129. amulet/level/java/_raw/_constant.pyi +20 -0
  130. amulet/level/java/_raw/_data_pack/__init__.py +2 -0
  131. amulet/level/java/_raw/_data_pack/__init__.pyi +8 -0
  132. amulet/level/java/_raw/_data_pack/data_pack.py +241 -0
  133. amulet/level/java/_raw/_data_pack/data_pack.pyi +197 -0
  134. amulet/level/java/_raw/_data_pack/data_pack_manager.py +77 -0
  135. amulet/level/java/_raw/_data_pack/data_pack_manager.pyi +75 -0
  136. amulet/level/java/_raw/_dimension.py +86 -0
  137. amulet/level/java/_raw/_dimension.pyi +72 -0
  138. amulet/level/java/_raw/_level.py +507 -0
  139. amulet/level/java/_raw/_level.pyi +238 -0
  140. amulet/level/java/_raw/_typing.py +3 -0
  141. amulet/level/java/_raw/_typing.pyi +5 -0
  142. amulet/level/java/anvil/__init__.py +2 -0
  143. amulet/level/java/anvil/__init__.pyi +11 -0
  144. amulet/level/java/anvil/_dimension.py +170 -0
  145. amulet/level/java/anvil/_dimension.pyi +109 -0
  146. amulet/level/java/anvil/_region.py +421 -0
  147. amulet/level/java/anvil/_region.pyi +197 -0
  148. amulet/level/java/anvil/_sector_manager.py +223 -0
  149. amulet/level/java/anvil/_sector_manager.pyi +142 -0
  150. amulet/level/java/chunk.pyi +81 -0
  151. amulet/level/java/chunk_/_chunk.py +260 -0
  152. amulet/level/java/chunk_/components/inhabited_time.py +12 -0
  153. amulet/level/java/chunk_/components/last_update.py +12 -0
  154. amulet/level/java/chunk_/components/legacy_version.py +12 -0
  155. amulet/level/java/chunk_/components/light_populated.py +12 -0
  156. amulet/level/java/chunk_/components/named_height_2d.py +37 -0
  157. amulet/level/java/chunk_/components/status.py +11 -0
  158. amulet/level/java/chunk_/components/terrain_populated.py +12 -0
  159. amulet/level/java/chunk_components.pyi +22 -0
  160. amulet/level/java/long_array.pyi +38 -0
  161. amulet/level/java_forge/__init__.py +0 -0
  162. amulet/level/mcstructure/__init__.py +0 -0
  163. amulet/level/nbt/__init__.py +0 -0
  164. amulet/level/schematic/__init__.py +0 -0
  165. amulet/level/sponge_schematic/__init__.py +0 -0
  166. amulet/level/temporary_level/__init__.py +1 -0
  167. amulet/level/temporary_level/_level.py +16 -0
  168. amulet/palette/__init__.pyi +8 -0
  169. amulet/palette/biome_palette.pyi +45 -0
  170. amulet/palette/block_palette.pyi +45 -0
  171. amulet/player.py +64 -0
  172. amulet/py.typed +0 -0
  173. amulet/selection/__init__.py +2 -0
  174. amulet/selection/abstract_selection.py +342 -0
  175. amulet/selection/box.py +852 -0
  176. amulet/selection/group.py +481 -0
  177. amulet/utils/__init__.pyi +28 -0
  178. amulet/utils/call_spec/__init__.py +24 -0
  179. amulet/utils/call_spec/__init__.pyi +53 -0
  180. amulet/utils/call_spec/_call_spec.py +262 -0
  181. amulet/utils/call_spec/_call_spec.pyi +272 -0
  182. amulet/utils/format_utils.py +41 -0
  183. amulet/utils/generator.py +18 -0
  184. amulet/utils/matrix.py +243 -0
  185. amulet/utils/matrix.pyi +177 -0
  186. amulet/utils/numpy.pyi +11 -0
  187. amulet/utils/numpy_helpers.py +19 -0
  188. amulet/utils/shareable_lock.py +335 -0
  189. amulet/utils/shareable_lock.pyi +190 -0
  190. amulet/utils/signal/__init__.py +10 -0
  191. amulet/utils/signal/__init__.pyi +25 -0
  192. amulet/utils/signal/_signal.py +228 -0
  193. amulet/utils/signal/_signal.pyi +84 -0
  194. amulet/utils/task_manager.py +235 -0
  195. amulet/utils/task_manager.pyi +168 -0
  196. amulet/utils/typed_property.py +111 -0
  197. amulet/utils/typing.py +4 -0
  198. amulet/utils/typing.pyi +6 -0
  199. amulet/utils/weakref.py +70 -0
  200. amulet/utils/weakref.pyi +50 -0
  201. amulet/utils/world_utils.py +102 -0
  202. amulet/utils/world_utils.pyi +109 -0
  203. amulet/version.cpp +136 -0
  204. amulet/version.hpp +142 -0
  205. amulet/version.pyi +94 -0
  206. amulet_core-2.0a5.dist-info/METADATA +103 -0
  207. amulet_core-2.0a5.dist-info/RECORD +210 -0
  208. amulet_core-2.0a5.dist-info/WHEEL +5 -0
  209. amulet_core-2.0a5.dist-info/entry_points.txt +2 -0
  210. amulet_core-2.0a5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,342 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Iterable, Iterator, TYPE_CHECKING, Any
5
+ import numpy
6
+
7
+ from amulet.data_types import (
8
+ ChunkCoordinates,
9
+ SubChunkCoordinates,
10
+ FloatTriplet,
11
+ BlockCoordinates,
12
+ )
13
+
14
+ if TYPE_CHECKING:
15
+ from .box import SelectionBox
16
+ from .group import SelectionGroup
17
+
18
+
19
+ class AbstractBaseSelection(ABC):
20
+ """
21
+ A parent selection class to force a consistent API for selection group and box.
22
+ """
23
+
24
+ __slots__ = ()
25
+
26
+ @abstractmethod
27
+ def __eq__(self, other: Any) -> bool:
28
+ """
29
+ Is the selection equal to the other selection.
30
+
31
+ >>> selection1: AbstractBaseSelection
32
+ >>> selection2: AbstractBaseSelection
33
+ >>> selection1 == selection2
34
+ True
35
+
36
+ :param other: The other selection to test.
37
+ :return: True if the selections are the same, False otherwise.
38
+ """
39
+ raise NotImplementedError
40
+
41
+ @abstractmethod
42
+ def __repr__(self) -> str:
43
+ raise NotImplementedError
44
+
45
+ @abstractmethod
46
+ def __str__(self) -> str:
47
+ raise NotImplementedError
48
+
49
+ @property
50
+ @abstractmethod
51
+ def blocks(self) -> Iterator[BlockCoordinates]:
52
+ """
53
+ The location of every block in the selection.
54
+
55
+ :return: An Iterator of block locations.
56
+ """
57
+ raise NotImplementedError
58
+
59
+ @property
60
+ @abstractmethod
61
+ def bounds(self) -> tuple[BlockCoordinates, BlockCoordinates]:
62
+ """
63
+ The minimum and maximum points in the selection.
64
+ """
65
+ raise NotImplementedError
66
+
67
+ @property
68
+ @abstractmethod
69
+ def bounds_array(self) -> numpy.ndarray:
70
+ """
71
+ The minimum and maximum points in the selection as a numpy array.
72
+ """
73
+ raise NotImplementedError
74
+
75
+ @abstractmethod
76
+ def bounding_box(self) -> SelectionBox:
77
+ """Get a SelectionBox that contains this selection."""
78
+ raise NotImplementedError
79
+
80
+ @abstractmethod
81
+ def selection_group(self) -> SelectionGroup:
82
+ """Get this selection as a SelectionGroup."""
83
+ raise NotImplementedError
84
+
85
+ @abstractmethod
86
+ def chunk_boxes(
87
+ self, sub_chunk_size: int = 16
88
+ ) -> Iterator[tuple[ChunkCoordinates, SelectionBox]]:
89
+ """
90
+ An Iterator of chunk coordinates and boxes that intersect the selection and the chunk.
91
+
92
+ >>> selection1: AbstractBaseSelection
93
+ >>> for (cx, cz), box in selection1.chunk_boxes():
94
+ >>> ...
95
+
96
+ :param sub_chunk_size: The dimension of a sub-chunk. Default 16.
97
+ """
98
+ raise NotImplementedError
99
+
100
+ @abstractmethod
101
+ def chunk_count(self, sub_chunk_size: int = 16) -> int:
102
+ """
103
+ The number of chunks that intersect the selection.
104
+
105
+ :param sub_chunk_size: The dimension of a sub-chunk. Default 16.
106
+ """
107
+ raise NotImplementedError
108
+
109
+ @abstractmethod
110
+ def chunk_locations(self, sub_chunk_size: int = 16) -> Iterable[ChunkCoordinates]:
111
+ """
112
+ An iterable of chunk coordinates that intersect the selection.
113
+
114
+ >>> selection1: AbstractBaseSelection
115
+ >>> for cx, cz in selection1.chunk_locations():
116
+ >>> ...
117
+
118
+ :param sub_chunk_size: The dimension of a sub-chunk. Default 16.
119
+ """
120
+ raise NotImplementedError
121
+
122
+ @abstractmethod
123
+ def contains_block(self, x: int, y: int, z: int) -> bool:
124
+ """
125
+ Is the block contained within the selection.
126
+
127
+ >>> selection1: AbstractBaseSelection
128
+ >>> (1, 2, 3) in selection1
129
+ True
130
+
131
+ :param x: The x coordinate of the block. Defined by the most negative corner.
132
+ :param y: The y coordinate of the block. Defined by the most negative corner.
133
+ :param z: The z coordinate of the block. Defined by the most negative corner.
134
+ :return: True if the block is in the selection.
135
+ """
136
+ raise NotImplementedError
137
+
138
+ @abstractmethod
139
+ def contains_point(self, x: float, y: float, z: float) -> bool:
140
+ """
141
+ Is the point contained within the selection.
142
+
143
+ >>> selection1: AbstractBaseSelection
144
+ >>> (1.5, 2.5, 3.5) in selection1
145
+ True
146
+
147
+ :param x: The x coordinate of the point.
148
+ :param y: The y coordinate of the point.
149
+ :param z: The z coordinate of the point.
150
+ :return: True if the point is in the selection.
151
+ """
152
+ raise NotImplementedError
153
+
154
+ def intersection(self, other: AbstractBaseSelection) -> AbstractBaseSelection:
155
+ """
156
+ Create and return a new a selection containing the volume that this selection and other both contain.
157
+
158
+ If the selections do not intersect the returned selection will have no volume.
159
+
160
+ Use :meth:`intersects` to test if the two selections intersect.
161
+
162
+ :param other: The other selection.
163
+ :return: A new selection containing the intersection.
164
+ """
165
+ out = self._intersection(other)
166
+ if out is NotImplemented:
167
+ out = other._intersection(self)
168
+ if out is NotImplemented:
169
+ raise TypeError(
170
+ f"intersection is not supported between instances of type {self.__class__} and {other.__class__}"
171
+ )
172
+ return out
173
+
174
+ @abstractmethod
175
+ def _intersection(self, other: AbstractBaseSelection) -> AbstractBaseSelection:
176
+ """Get the intersection between self and other.
177
+
178
+ :param other: The other selection
179
+ :return: The selection that intersects. NotImplemented if the operation is not supported.
180
+ """
181
+
182
+ def intersects(self, other: AbstractBaseSelection) -> bool:
183
+ """
184
+ Does this selection intersect ``other``.
185
+
186
+ :param other: The other selection.
187
+ :return: True if the selections intersect, False otherwise.
188
+ """
189
+ out = self._intersects(other)
190
+ if out is NotImplemented:
191
+ out = other._intersects(self)
192
+ if out is NotImplemented:
193
+ raise TypeError(
194
+ f"intersects is not supported between instances of type {self.__class__} and {other.__class__}"
195
+ )
196
+ return out
197
+
198
+ @abstractmethod
199
+ def _intersects(self, other: AbstractBaseSelection) -> bool:
200
+ """Check if other intersects this instance.
201
+
202
+ :param other: The other selection to test
203
+ :return: True if intersects, False if not intersects and NotImplemented if the operation is not supported.
204
+ """
205
+ raise NotImplementedError
206
+
207
+ @property
208
+ @abstractmethod
209
+ def max(self) -> BlockCoordinates:
210
+ """
211
+ The maximum point in the selection.
212
+ """
213
+ raise NotImplementedError
214
+
215
+ @property
216
+ @abstractmethod
217
+ def max_array(self) -> numpy.ndarray:
218
+ """
219
+ The maximum point in the selection as a numpy array.
220
+ """
221
+ raise NotImplementedError
222
+
223
+ @property
224
+ @abstractmethod
225
+ def max_x(self) -> int:
226
+ """
227
+ The maximum x coordinate of the selection.
228
+ """
229
+ raise NotImplementedError
230
+
231
+ @property
232
+ @abstractmethod
233
+ def max_y(self) -> int:
234
+ """
235
+ The maximum y coordinate of the selection.
236
+ """
237
+ raise NotImplementedError
238
+
239
+ @property
240
+ @abstractmethod
241
+ def max_z(self) -> int:
242
+ """
243
+ The maximum z coordinate of the selection.
244
+ """
245
+ raise NotImplementedError
246
+
247
+ @property
248
+ @abstractmethod
249
+ def min(self) -> BlockCoordinates:
250
+ """
251
+ The minimum point in the selection.
252
+ """
253
+ raise NotImplementedError
254
+
255
+ @property
256
+ @abstractmethod
257
+ def min_array(self) -> numpy.ndarray:
258
+ """
259
+ The minimum point in the selection as a numpy array.
260
+ """
261
+ raise NotImplementedError
262
+
263
+ @property
264
+ @abstractmethod
265
+ def min_x(self) -> int:
266
+ """
267
+ The minimum x coordinate of the selection.
268
+ """
269
+ raise NotImplementedError
270
+
271
+ @property
272
+ @abstractmethod
273
+ def min_y(self) -> int:
274
+ """
275
+ The minimum y coordinate of the selection.
276
+ """
277
+ raise NotImplementedError
278
+
279
+ @property
280
+ @abstractmethod
281
+ def min_z(self) -> int:
282
+ """
283
+ The minimum z coordinate of the selection.
284
+ """
285
+ raise NotImplementedError
286
+
287
+ @abstractmethod
288
+ def sub_chunk_boxes(
289
+ self, sub_chunk_size: int = 16
290
+ ) -> Iterator[tuple[SubChunkCoordinates, SelectionBox]]:
291
+ """
292
+ An Iterator of sub-chunk coordinates and boxes that intersect the selection and the sub-chunk.
293
+
294
+ >>> selection1: AbstractBaseSelection
295
+ >>> for (cx, cy, cz), box in selection1.sub_chunk_boxes():
296
+ >>> ...
297
+
298
+ :param sub_chunk_size: The dimension of a sub-chunk. Default 16.
299
+ """
300
+ raise NotImplementedError
301
+
302
+ @abstractmethod
303
+ def sub_chunk_count(self, sub_chunk_size: int = 16) -> int:
304
+ """
305
+ The number of sub-chunks that intersect the selection.
306
+
307
+ :param sub_chunk_size: The dimension of a sub-chunk. Default 16.
308
+ """
309
+ raise NotImplementedError
310
+
311
+ @abstractmethod
312
+ def sub_chunk_locations(
313
+ self, sub_chunk_size: int = 16
314
+ ) -> Iterable[SubChunkCoordinates]:
315
+ """
316
+ An iterable of sub-chunk coordinates that intersect the selection.
317
+
318
+ >>> selection1: AbstractBaseSelection
319
+ >>> for cx, cy, cz in selection1.sub_chunk_locations():
320
+ >>> ...
321
+
322
+ :param sub_chunk_size: The dimension of a sub-chunk. Default 16.
323
+ """
324
+ raise NotImplementedError
325
+
326
+ @abstractmethod
327
+ def subtract(self, other: AbstractBaseSelection) -> AbstractBaseSelection:
328
+ raise NotImplementedError
329
+
330
+ @abstractmethod
331
+ def transform(
332
+ self, scale: FloatTriplet, rotation: FloatTriplet, translation: FloatTriplet
333
+ ) -> AbstractBaseSelection:
334
+ raise NotImplementedError
335
+
336
+ @property
337
+ @abstractmethod
338
+ def volume(self) -> int:
339
+ """
340
+ The number of blocks in the selection.
341
+ """
342
+ raise NotImplementedError