vispy 0.15.0__cp312-cp312-macosx_10_13_x86_64.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 vispy might be problematic. Click here for more details.

Files changed (521) hide show
  1. vispy/__init__.py +33 -0
  2. vispy/app/__init__.py +15 -0
  3. vispy/app/_default_app.py +76 -0
  4. vispy/app/_detect_eventloop.py +148 -0
  5. vispy/app/application.py +263 -0
  6. vispy/app/backends/__init__.py +52 -0
  7. vispy/app/backends/_egl.py +264 -0
  8. vispy/app/backends/_glfw.py +513 -0
  9. vispy/app/backends/_jupyter_rfb.py +278 -0
  10. vispy/app/backends/_offscreen_util.py +121 -0
  11. vispy/app/backends/_osmesa.py +235 -0
  12. vispy/app/backends/_pyglet.py +451 -0
  13. vispy/app/backends/_pyqt4.py +36 -0
  14. vispy/app/backends/_pyqt5.py +36 -0
  15. vispy/app/backends/_pyqt6.py +40 -0
  16. vispy/app/backends/_pyside.py +37 -0
  17. vispy/app/backends/_pyside2.py +52 -0
  18. vispy/app/backends/_pyside6.py +53 -0
  19. vispy/app/backends/_qt.py +1003 -0
  20. vispy/app/backends/_sdl2.py +444 -0
  21. vispy/app/backends/_template.py +244 -0
  22. vispy/app/backends/_test.py +8 -0
  23. vispy/app/backends/_tk.py +800 -0
  24. vispy/app/backends/_wx.py +476 -0
  25. vispy/app/backends/tests/__init__.py +0 -0
  26. vispy/app/backends/tests/test_offscreen_util.py +52 -0
  27. vispy/app/backends/tests/test_rfb.py +77 -0
  28. vispy/app/base.py +294 -0
  29. vispy/app/canvas.py +828 -0
  30. vispy/app/qt.py +92 -0
  31. vispy/app/tests/__init__.py +0 -0
  32. vispy/app/tests/qt-designer.ui +58 -0
  33. vispy/app/tests/test_app.py +442 -0
  34. vispy/app/tests/test_backends.py +164 -0
  35. vispy/app/tests/test_canvas.py +122 -0
  36. vispy/app/tests/test_context.py +92 -0
  37. vispy/app/tests/test_qt.py +47 -0
  38. vispy/app/tests/test_simultaneous.py +134 -0
  39. vispy/app/timer.py +174 -0
  40. vispy/color/__init__.py +17 -0
  41. vispy/color/_color_dict.py +193 -0
  42. vispy/color/color_array.py +447 -0
  43. vispy/color/color_space.py +181 -0
  44. vispy/color/colormap.py +1213 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +378 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1522 -0
  50. vispy/ext/cubehelix.py +138 -0
  51. vispy/ext/egl.py +375 -0
  52. vispy/ext/fontconfig.py +118 -0
  53. vispy/ext/gdi32plus.py +206 -0
  54. vispy/ext/osmesa.py +105 -0
  55. vispy/geometry/__init__.py +23 -0
  56. vispy/geometry/_triangulation_debugger.py +171 -0
  57. vispy/geometry/calculations.py +162 -0
  58. vispy/geometry/curves.py +399 -0
  59. vispy/geometry/generation.py +643 -0
  60. vispy/geometry/isocurve.py +175 -0
  61. vispy/geometry/isosurface.py +465 -0
  62. vispy/geometry/meshdata.py +700 -0
  63. vispy/geometry/normals.py +78 -0
  64. vispy/geometry/parametric.py +56 -0
  65. vispy/geometry/polygon.py +137 -0
  66. vispy/geometry/rect.py +210 -0
  67. vispy/geometry/tests/__init__.py +0 -0
  68. vispy/geometry/tests/test_calculations.py +23 -0
  69. vispy/geometry/tests/test_generation.py +56 -0
  70. vispy/geometry/tests/test_meshdata.py +106 -0
  71. vispy/geometry/tests/test_triangulation.py +594 -0
  72. vispy/geometry/torusknot.py +142 -0
  73. vispy/geometry/triangulation.py +876 -0
  74. vispy/gloo/__init__.py +56 -0
  75. vispy/gloo/buffer.py +505 -0
  76. vispy/gloo/context.py +272 -0
  77. vispy/gloo/framebuffer.py +257 -0
  78. vispy/gloo/gl/__init__.py +234 -0
  79. vispy/gloo/gl/_constants.py +332 -0
  80. vispy/gloo/gl/_es2.py +986 -0
  81. vispy/gloo/gl/_gl2.py +1365 -0
  82. vispy/gloo/gl/_proxy.py +499 -0
  83. vispy/gloo/gl/_pyopengl2.py +362 -0
  84. vispy/gloo/gl/dummy.py +24 -0
  85. vispy/gloo/gl/es2.py +62 -0
  86. vispy/gloo/gl/gl2.py +98 -0
  87. vispy/gloo/gl/glplus.py +168 -0
  88. vispy/gloo/gl/pyopengl2.py +97 -0
  89. vispy/gloo/gl/tests/__init__.py +0 -0
  90. vispy/gloo/gl/tests/test_basics.py +282 -0
  91. vispy/gloo/gl/tests/test_functionality.py +568 -0
  92. vispy/gloo/gl/tests/test_names.py +246 -0
  93. vispy/gloo/gl/tests/test_use.py +71 -0
  94. vispy/gloo/glir.py +1824 -0
  95. vispy/gloo/globject.py +101 -0
  96. vispy/gloo/preprocessor.py +67 -0
  97. vispy/gloo/program.py +543 -0
  98. vispy/gloo/tests/__init__.py +0 -0
  99. vispy/gloo/tests/test_buffer.py +558 -0
  100. vispy/gloo/tests/test_context.py +119 -0
  101. vispy/gloo/tests/test_framebuffer.py +195 -0
  102. vispy/gloo/tests/test_glir.py +307 -0
  103. vispy/gloo/tests/test_globject.py +35 -0
  104. vispy/gloo/tests/test_program.py +302 -0
  105. vispy/gloo/tests/test_texture.py +732 -0
  106. vispy/gloo/tests/test_use_gloo.py +187 -0
  107. vispy/gloo/tests/test_util.py +60 -0
  108. vispy/gloo/tests/test_wrappers.py +261 -0
  109. vispy/gloo/texture.py +1046 -0
  110. vispy/gloo/util.py +129 -0
  111. vispy/gloo/wrappers.py +762 -0
  112. vispy/glsl/__init__.py +42 -0
  113. vispy/glsl/antialias/antialias.glsl +7 -0
  114. vispy/glsl/antialias/cap-butt.glsl +31 -0
  115. vispy/glsl/antialias/cap-round.glsl +29 -0
  116. vispy/glsl/antialias/cap-square.glsl +30 -0
  117. vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
  118. vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
  119. vispy/glsl/antialias/cap.glsl +67 -0
  120. vispy/glsl/antialias/caps.glsl +67 -0
  121. vispy/glsl/antialias/filled.glsl +50 -0
  122. vispy/glsl/antialias/outline.glsl +40 -0
  123. vispy/glsl/antialias/stroke.glsl +43 -0
  124. vispy/glsl/arrowheads/angle.glsl +99 -0
  125. vispy/glsl/arrowheads/arrowheads.frag +60 -0
  126. vispy/glsl/arrowheads/arrowheads.glsl +12 -0
  127. vispy/glsl/arrowheads/arrowheads.vert +83 -0
  128. vispy/glsl/arrowheads/curved.glsl +48 -0
  129. vispy/glsl/arrowheads/inhibitor.glsl +26 -0
  130. vispy/glsl/arrowheads/stealth.glsl +46 -0
  131. vispy/glsl/arrowheads/triangle.glsl +97 -0
  132. vispy/glsl/arrowheads/util.glsl +13 -0
  133. vispy/glsl/arrows/angle-30.glsl +12 -0
  134. vispy/glsl/arrows/angle-60.glsl +12 -0
  135. vispy/glsl/arrows/angle-90.glsl +12 -0
  136. vispy/glsl/arrows/arrow.frag +39 -0
  137. vispy/glsl/arrows/arrow.vert +49 -0
  138. vispy/glsl/arrows/arrows.glsl +17 -0
  139. vispy/glsl/arrows/common.glsl +187 -0
  140. vispy/glsl/arrows/curved.glsl +63 -0
  141. vispy/glsl/arrows/stealth.glsl +50 -0
  142. vispy/glsl/arrows/triangle-30.glsl +12 -0
  143. vispy/glsl/arrows/triangle-60.glsl +12 -0
  144. vispy/glsl/arrows/triangle-90.glsl +12 -0
  145. vispy/glsl/arrows/util.glsl +98 -0
  146. vispy/glsl/build_spatial_filters.py +660 -0
  147. vispy/glsl/collections/agg-fast-path.frag +20 -0
  148. vispy/glsl/collections/agg-fast-path.vert +78 -0
  149. vispy/glsl/collections/agg-glyph.frag +60 -0
  150. vispy/glsl/collections/agg-glyph.vert +33 -0
  151. vispy/glsl/collections/agg-marker.frag +35 -0
  152. vispy/glsl/collections/agg-marker.vert +48 -0
  153. vispy/glsl/collections/agg-path.frag +55 -0
  154. vispy/glsl/collections/agg-path.vert +166 -0
  155. vispy/glsl/collections/agg-point.frag +21 -0
  156. vispy/glsl/collections/agg-point.vert +35 -0
  157. vispy/glsl/collections/agg-segment.frag +32 -0
  158. vispy/glsl/collections/agg-segment.vert +75 -0
  159. vispy/glsl/collections/marker.frag +38 -0
  160. vispy/glsl/collections/marker.vert +48 -0
  161. vispy/glsl/collections/raw-path.frag +15 -0
  162. vispy/glsl/collections/raw-path.vert +24 -0
  163. vispy/glsl/collections/raw-point.frag +14 -0
  164. vispy/glsl/collections/raw-point.vert +31 -0
  165. vispy/glsl/collections/raw-segment.frag +18 -0
  166. vispy/glsl/collections/raw-segment.vert +26 -0
  167. vispy/glsl/collections/raw-triangle.frag +13 -0
  168. vispy/glsl/collections/raw-triangle.vert +26 -0
  169. vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
  170. vispy/glsl/collections/sdf-glyph.frag +80 -0
  171. vispy/glsl/collections/sdf-glyph.vert +59 -0
  172. vispy/glsl/collections/tick-labels.vert +71 -0
  173. vispy/glsl/colormaps/autumn.glsl +20 -0
  174. vispy/glsl/colormaps/blues.glsl +20 -0
  175. vispy/glsl/colormaps/color-space.glsl +17 -0
  176. vispy/glsl/colormaps/colormaps.glsl +24 -0
  177. vispy/glsl/colormaps/cool.glsl +20 -0
  178. vispy/glsl/colormaps/fire.glsl +21 -0
  179. vispy/glsl/colormaps/gray.glsl +20 -0
  180. vispy/glsl/colormaps/greens.glsl +20 -0
  181. vispy/glsl/colormaps/hot.glsl +22 -0
  182. vispy/glsl/colormaps/ice.glsl +20 -0
  183. vispy/glsl/colormaps/icefire.glsl +23 -0
  184. vispy/glsl/colormaps/parse.py +40 -0
  185. vispy/glsl/colormaps/reds.glsl +20 -0
  186. vispy/glsl/colormaps/spring.glsl +20 -0
  187. vispy/glsl/colormaps/summer.glsl +20 -0
  188. vispy/glsl/colormaps/user.glsl +22 -0
  189. vispy/glsl/colormaps/util.glsl +41 -0
  190. vispy/glsl/colormaps/wheel.glsl +21 -0
  191. vispy/glsl/colormaps/winter.glsl +20 -0
  192. vispy/glsl/lines/agg.frag +320 -0
  193. vispy/glsl/lines/agg.vert +241 -0
  194. vispy/glsl/markers/arrow.glsl +12 -0
  195. vispy/glsl/markers/asterisk.glsl +16 -0
  196. vispy/glsl/markers/chevron.glsl +14 -0
  197. vispy/glsl/markers/clover.glsl +20 -0
  198. vispy/glsl/markers/club.glsl +31 -0
  199. vispy/glsl/markers/cross.glsl +17 -0
  200. vispy/glsl/markers/diamond.glsl +12 -0
  201. vispy/glsl/markers/disc.glsl +9 -0
  202. vispy/glsl/markers/ellipse.glsl +67 -0
  203. vispy/glsl/markers/hbar.glsl +9 -0
  204. vispy/glsl/markers/heart.glsl +15 -0
  205. vispy/glsl/markers/infinity.glsl +15 -0
  206. vispy/glsl/markers/marker-sdf.frag +74 -0
  207. vispy/glsl/markers/marker-sdf.vert +41 -0
  208. vispy/glsl/markers/marker.frag +36 -0
  209. vispy/glsl/markers/marker.vert +46 -0
  210. vispy/glsl/markers/markers.glsl +24 -0
  211. vispy/glsl/markers/pin.glsl +18 -0
  212. vispy/glsl/markers/ring.glsl +11 -0
  213. vispy/glsl/markers/spade.glsl +28 -0
  214. vispy/glsl/markers/square.glsl +10 -0
  215. vispy/glsl/markers/tag.glsl +11 -0
  216. vispy/glsl/markers/triangle.glsl +14 -0
  217. vispy/glsl/markers/vbar.glsl +9 -0
  218. vispy/glsl/math/circle-through-2-points.glsl +30 -0
  219. vispy/glsl/math/constants.glsl +48 -0
  220. vispy/glsl/math/double.glsl +114 -0
  221. vispy/glsl/math/functions.glsl +20 -0
  222. vispy/glsl/math/point-to-line-distance.glsl +31 -0
  223. vispy/glsl/math/point-to-line-projection.glsl +29 -0
  224. vispy/glsl/math/signed-line-distance.glsl +27 -0
  225. vispy/glsl/math/signed-segment-distance.glsl +30 -0
  226. vispy/glsl/misc/regular-grid.frag +244 -0
  227. vispy/glsl/misc/spatial-filters.frag +1407 -0
  228. vispy/glsl/misc/viewport-NDC.glsl +20 -0
  229. vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
  230. vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
  231. vispy/glsl/transforms/hammer.glsl +44 -0
  232. vispy/glsl/transforms/identity.glsl +6 -0
  233. vispy/glsl/transforms/identity_forward.glsl +23 -0
  234. vispy/glsl/transforms/identity_inverse.glsl +23 -0
  235. vispy/glsl/transforms/linear-scale.glsl +127 -0
  236. vispy/glsl/transforms/log-scale.glsl +126 -0
  237. vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
  238. vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
  239. vispy/glsl/transforms/panzoom.glsl +10 -0
  240. vispy/glsl/transforms/polar.glsl +41 -0
  241. vispy/glsl/transforms/position.glsl +44 -0
  242. vispy/glsl/transforms/power-scale.glsl +139 -0
  243. vispy/glsl/transforms/projection.glsl +7 -0
  244. vispy/glsl/transforms/pvm.glsl +13 -0
  245. vispy/glsl/transforms/rotate.glsl +45 -0
  246. vispy/glsl/transforms/trackball.glsl +15 -0
  247. vispy/glsl/transforms/translate.glsl +35 -0
  248. vispy/glsl/transforms/transverse_mercator.glsl +38 -0
  249. vispy/glsl/transforms/viewport-clipping.glsl +14 -0
  250. vispy/glsl/transforms/viewport-transform.glsl +16 -0
  251. vispy/glsl/transforms/viewport.glsl +50 -0
  252. vispy/glsl/transforms/x.glsl +24 -0
  253. vispy/glsl/transforms/y.glsl +19 -0
  254. vispy/glsl/transforms/z.glsl +14 -0
  255. vispy/io/__init__.py +20 -0
  256. vispy/io/_data/spatial-filters.npy +0 -0
  257. vispy/io/datasets.py +94 -0
  258. vispy/io/image.py +231 -0
  259. vispy/io/mesh.py +122 -0
  260. vispy/io/stl.py +167 -0
  261. vispy/io/tests/__init__.py +0 -0
  262. vispy/io/tests/test_image.py +47 -0
  263. vispy/io/tests/test_io.py +121 -0
  264. vispy/io/wavefront.py +350 -0
  265. vispy/plot/__init__.py +36 -0
  266. vispy/plot/fig.py +58 -0
  267. vispy/plot/plotwidget.py +522 -0
  268. vispy/plot/tests/__init__.py +0 -0
  269. vispy/plot/tests/test_plot.py +46 -0
  270. vispy/scene/__init__.py +43 -0
  271. vispy/scene/cameras/__init__.py +27 -0
  272. vispy/scene/cameras/_base.py +38 -0
  273. vispy/scene/cameras/arcball.py +105 -0
  274. vispy/scene/cameras/base_camera.py +551 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +311 -0
  278. vispy/scene/cameras/perspective.py +338 -0
  279. vispy/scene/cameras/tests/__init__.py +0 -0
  280. vispy/scene/cameras/tests/test_cameras.py +27 -0
  281. vispy/scene/cameras/tests/test_link.py +53 -0
  282. vispy/scene/cameras/tests/test_perspective.py +122 -0
  283. vispy/scene/cameras/turntable.py +183 -0
  284. vispy/scene/canvas.py +639 -0
  285. vispy/scene/events.py +85 -0
  286. vispy/scene/node.py +644 -0
  287. vispy/scene/subscene.py +20 -0
  288. vispy/scene/tests/__init__.py +0 -0
  289. vispy/scene/tests/test_canvas.py +119 -0
  290. vispy/scene/tests/test_node.py +142 -0
  291. vispy/scene/tests/test_visuals.py +141 -0
  292. vispy/scene/visuals.py +276 -0
  293. vispy/scene/widgets/__init__.py +18 -0
  294. vispy/scene/widgets/anchor.py +25 -0
  295. vispy/scene/widgets/axis.py +88 -0
  296. vispy/scene/widgets/colorbar.py +176 -0
  297. vispy/scene/widgets/console.py +351 -0
  298. vispy/scene/widgets/grid.py +509 -0
  299. vispy/scene/widgets/label.py +50 -0
  300. vispy/scene/widgets/tests/__init__.py +0 -0
  301. vispy/scene/widgets/tests/test_colorbar.py +47 -0
  302. vispy/scene/widgets/viewbox.py +199 -0
  303. vispy/scene/widgets/widget.py +478 -0
  304. vispy/testing/__init__.py +51 -0
  305. vispy/testing/_runners.py +448 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +494 -0
  308. vispy/testing/rendered_array_tester.py +85 -0
  309. vispy/testing/tests/__init__.py +0 -0
  310. vispy/testing/tests/test_testing.py +20 -0
  311. vispy/util/__init__.py +32 -0
  312. vispy/util/bunch.py +15 -0
  313. vispy/util/check_environment.py +57 -0
  314. vispy/util/config.py +490 -0
  315. vispy/util/dpi/__init__.py +19 -0
  316. vispy/util/dpi/_linux.py +69 -0
  317. vispy/util/dpi/_quartz.py +26 -0
  318. vispy/util/dpi/_win32.py +34 -0
  319. vispy/util/dpi/tests/__init__.py +0 -0
  320. vispy/util/dpi/tests/test_dpi.py +16 -0
  321. vispy/util/eq.py +41 -0
  322. vispy/util/event.py +774 -0
  323. vispy/util/fetching.py +276 -0
  324. vispy/util/filter.py +44 -0
  325. vispy/util/fonts/__init__.py +14 -0
  326. vispy/util/fonts/_freetype.py +73 -0
  327. vispy/util/fonts/_quartz.py +192 -0
  328. vispy/util/fonts/_triage.py +36 -0
  329. vispy/util/fonts/_vispy_fonts.py +20 -0
  330. vispy/util/fonts/_win32.py +105 -0
  331. vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
  332. vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
  333. vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
  334. vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
  335. vispy/util/fonts/tests/__init__.py +0 -0
  336. vispy/util/fonts/tests/test_font.py +45 -0
  337. vispy/util/fourier.py +69 -0
  338. vispy/util/frozen.py +25 -0
  339. vispy/util/gallery_scraper.py +268 -0
  340. vispy/util/keys.py +91 -0
  341. vispy/util/logs.py +358 -0
  342. vispy/util/osmesa_gl.py +17 -0
  343. vispy/util/profiler.py +135 -0
  344. vispy/util/ptime.py +16 -0
  345. vispy/util/quaternion.py +229 -0
  346. vispy/util/svg/__init__.py +18 -0
  347. vispy/util/svg/base.py +20 -0
  348. vispy/util/svg/color.py +219 -0
  349. vispy/util/svg/element.py +51 -0
  350. vispy/util/svg/geometry.py +478 -0
  351. vispy/util/svg/group.py +66 -0
  352. vispy/util/svg/length.py +81 -0
  353. vispy/util/svg/number.py +25 -0
  354. vispy/util/svg/path.py +332 -0
  355. vispy/util/svg/shapes.py +57 -0
  356. vispy/util/svg/style.py +59 -0
  357. vispy/util/svg/svg.py +40 -0
  358. vispy/util/svg/transform.py +223 -0
  359. vispy/util/svg/transformable.py +28 -0
  360. vispy/util/svg/viewport.py +73 -0
  361. vispy/util/tests/__init__.py +0 -0
  362. vispy/util/tests/test_config.py +58 -0
  363. vispy/util/tests/test_docstring_parameters.py +123 -0
  364. vispy/util/tests/test_emitter_group.py +262 -0
  365. vispy/util/tests/test_event_emitter.py +743 -0
  366. vispy/util/tests/test_fourier.py +35 -0
  367. vispy/util/tests/test_gallery_scraper.py +112 -0
  368. vispy/util/tests/test_import.py +127 -0
  369. vispy/util/tests/test_key.py +22 -0
  370. vispy/util/tests/test_logging.py +45 -0
  371. vispy/util/tests/test_run.py +14 -0
  372. vispy/util/tests/test_transforms.py +42 -0
  373. vispy/util/tests/test_vispy.py +48 -0
  374. vispy/util/transforms.py +201 -0
  375. vispy/util/wrappers.py +155 -0
  376. vispy/version.py +21 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +487 -0
  379. vispy/visuals/axis.py +678 -0
  380. vispy/visuals/border.py +208 -0
  381. vispy/visuals/box.py +79 -0
  382. vispy/visuals/collections/__init__.py +30 -0
  383. vispy/visuals/collections/agg_fast_path_collection.py +219 -0
  384. vispy/visuals/collections/agg_path_collection.py +197 -0
  385. vispy/visuals/collections/agg_point_collection.py +52 -0
  386. vispy/visuals/collections/agg_segment_collection.py +142 -0
  387. vispy/visuals/collections/array_list.py +401 -0
  388. vispy/visuals/collections/base_collection.py +482 -0
  389. vispy/visuals/collections/collection.py +253 -0
  390. vispy/visuals/collections/path_collection.py +23 -0
  391. vispy/visuals/collections/point_collection.py +19 -0
  392. vispy/visuals/collections/polygon_collection.py +25 -0
  393. vispy/visuals/collections/raw_path_collection.py +119 -0
  394. vispy/visuals/collections/raw_point_collection.py +113 -0
  395. vispy/visuals/collections/raw_polygon_collection.py +77 -0
  396. vispy/visuals/collections/raw_segment_collection.py +112 -0
  397. vispy/visuals/collections/raw_triangle_collection.py +78 -0
  398. vispy/visuals/collections/segment_collection.py +19 -0
  399. vispy/visuals/collections/triangle_collection.py +16 -0
  400. vispy/visuals/collections/util.py +168 -0
  401. vispy/visuals/colorbar.py +699 -0
  402. vispy/visuals/cube.py +41 -0
  403. vispy/visuals/ellipse.py +162 -0
  404. vispy/visuals/filters/__init__.py +10 -0
  405. vispy/visuals/filters/base_filter.py +242 -0
  406. vispy/visuals/filters/clipper.py +60 -0
  407. vispy/visuals/filters/clipping_planes.py +122 -0
  408. vispy/visuals/filters/color.py +181 -0
  409. vispy/visuals/filters/markers.py +28 -0
  410. vispy/visuals/filters/mesh.py +801 -0
  411. vispy/visuals/filters/picking.py +60 -0
  412. vispy/visuals/filters/tests/__init__.py +3 -0
  413. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  414. vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
  415. vispy/visuals/glsl/__init__.py +1 -0
  416. vispy/visuals/glsl/antialiasing.py +133 -0
  417. vispy/visuals/glsl/color.py +63 -0
  418. vispy/visuals/graphs/__init__.py +1 -0
  419. vispy/visuals/graphs/graph.py +240 -0
  420. vispy/visuals/graphs/layouts/__init__.py +55 -0
  421. vispy/visuals/graphs/layouts/circular.py +49 -0
  422. vispy/visuals/graphs/layouts/force_directed.py +211 -0
  423. vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
  424. vispy/visuals/graphs/layouts/random.py +52 -0
  425. vispy/visuals/graphs/tests/__init__.py +1 -0
  426. vispy/visuals/graphs/tests/test_layouts.py +139 -0
  427. vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
  428. vispy/visuals/graphs/util.py +120 -0
  429. vispy/visuals/gridlines.py +161 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +701 -0
  433. vispy/visuals/image_complex.py +130 -0
  434. vispy/visuals/infinite_line.py +199 -0
  435. vispy/visuals/instanced_mesh.py +152 -0
  436. vispy/visuals/isocurve.py +213 -0
  437. vispy/visuals/isoline.py +241 -0
  438. vispy/visuals/isosurface.py +113 -0
  439. vispy/visuals/line/__init__.py +6 -0
  440. vispy/visuals/line/arrow.py +289 -0
  441. vispy/visuals/line/dash_atlas.py +90 -0
  442. vispy/visuals/line/line.py +545 -0
  443. vispy/visuals/line_plot.py +135 -0
  444. vispy/visuals/linear_region.py +199 -0
  445. vispy/visuals/markers.py +819 -0
  446. vispy/visuals/mesh.py +373 -0
  447. vispy/visuals/mesh_normals.py +159 -0
  448. vispy/visuals/plane.py +54 -0
  449. vispy/visuals/polygon.py +145 -0
  450. vispy/visuals/rectangle.py +196 -0
  451. vispy/visuals/regular_polygon.py +56 -0
  452. vispy/visuals/scrolling_lines.py +197 -0
  453. vispy/visuals/shaders/__init__.py +17 -0
  454. vispy/visuals/shaders/compiler.py +206 -0
  455. vispy/visuals/shaders/expression.py +99 -0
  456. vispy/visuals/shaders/function.py +788 -0
  457. vispy/visuals/shaders/multiprogram.py +145 -0
  458. vispy/visuals/shaders/parsing.py +140 -0
  459. vispy/visuals/shaders/program.py +161 -0
  460. vispy/visuals/shaders/shader_object.py +162 -0
  461. vispy/visuals/shaders/tests/__init__.py +0 -0
  462. vispy/visuals/shaders/tests/test_function.py +486 -0
  463. vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
  464. vispy/visuals/shaders/tests/test_parsing.py +57 -0
  465. vispy/visuals/shaders/variable.py +272 -0
  466. vispy/visuals/spectrogram.py +169 -0
  467. vispy/visuals/sphere.py +80 -0
  468. vispy/visuals/surface_plot.py +192 -0
  469. vispy/visuals/tests/__init__.py +0 -0
  470. vispy/visuals/tests/test_arrows.py +109 -0
  471. vispy/visuals/tests/test_axis.py +120 -0
  472. vispy/visuals/tests/test_collections.py +15 -0
  473. vispy/visuals/tests/test_colorbar.py +179 -0
  474. vispy/visuals/tests/test_colormap.py +97 -0
  475. vispy/visuals/tests/test_ellipse.py +122 -0
  476. vispy/visuals/tests/test_gridlines.py +30 -0
  477. vispy/visuals/tests/test_histogram.py +24 -0
  478. vispy/visuals/tests/test_image.py +392 -0
  479. vispy/visuals/tests/test_image_complex.py +36 -0
  480. vispy/visuals/tests/test_infinite_line.py +53 -0
  481. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  482. vispy/visuals/tests/test_isosurface.py +22 -0
  483. vispy/visuals/tests/test_linear_region.py +152 -0
  484. vispy/visuals/tests/test_markers.py +54 -0
  485. vispy/visuals/tests/test_mesh.py +261 -0
  486. vispy/visuals/tests/test_mesh_normals.py +218 -0
  487. vispy/visuals/tests/test_polygon.py +112 -0
  488. vispy/visuals/tests/test_rectangle.py +163 -0
  489. vispy/visuals/tests/test_regular_polygon.py +111 -0
  490. vispy/visuals/tests/test_scalable_textures.py +196 -0
  491. vispy/visuals/tests/test_sdf.py +73 -0
  492. vispy/visuals/tests/test_spectrogram.py +42 -0
  493. vispy/visuals/tests/test_surface_plot.py +57 -0
  494. vispy/visuals/tests/test_text.py +95 -0
  495. vispy/visuals/tests/test_volume.py +542 -0
  496. vispy/visuals/tests/test_windbarb.py +33 -0
  497. vispy/visuals/text/__init__.py +7 -0
  498. vispy/visuals/text/_sdf_cpu.cpython-312-darwin.so +0 -0
  499. vispy/visuals/text/_sdf_cpu.pyx +112 -0
  500. vispy/visuals/text/_sdf_gpu.py +316 -0
  501. vispy/visuals/text/text.py +675 -0
  502. vispy/visuals/transforms/__init__.py +34 -0
  503. vispy/visuals/transforms/_util.py +191 -0
  504. vispy/visuals/transforms/base_transform.py +233 -0
  505. vispy/visuals/transforms/chain.py +300 -0
  506. vispy/visuals/transforms/interactive.py +98 -0
  507. vispy/visuals/transforms/linear.py +564 -0
  508. vispy/visuals/transforms/nonlinear.py +398 -0
  509. vispy/visuals/transforms/tests/__init__.py +0 -0
  510. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  511. vispy/visuals/transforms/transform_system.py +339 -0
  512. vispy/visuals/tube.py +173 -0
  513. vispy/visuals/visual.py +923 -0
  514. vispy/visuals/volume.py +1366 -0
  515. vispy/visuals/windbarb.py +291 -0
  516. vispy/visuals/xyz_axis.py +34 -0
  517. vispy-0.15.0.dist-info/METADATA +243 -0
  518. vispy-0.15.0.dist-info/RECORD +521 -0
  519. vispy-0.15.0.dist-info/WHEEL +6 -0
  520. vispy-0.15.0.dist-info/licenses/LICENSE.txt +36 -0
  521. vispy-0.15.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,743 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+ import unittest
5
+ import copy
6
+ import functools
7
+
8
+ from vispy.util.event import Event, EventEmitter
9
+ from vispy.testing import run_tests_if_main, assert_raises, assert_equal
10
+
11
+
12
+ class BasicEvent(Event):
13
+ pass
14
+
15
+
16
+ class TypedEvent(Event):
17
+
18
+ def __init__(self, **kwargs):
19
+ kwargs['type'] = 'typed_event'
20
+ Event.__init__(self, **kwargs)
21
+
22
+
23
+ class TestEmitters(unittest.TestCase):
24
+
25
+ def test_emitter(self):
26
+ """Emitter constructed with no arguments"""
27
+ em = EventEmitter()
28
+
29
+ # type must be specified when emitting since Event requires type
30
+ # argument and the emitter was constructed without it.
31
+ try:
32
+ em()
33
+ assert False, "Emitting event with no type should have failed."
34
+ except TypeError:
35
+ pass
36
+
37
+ # See that emitted event has all of the properties we expect
38
+ ev = self.try_emitter(em, type='test_event')
39
+ self.assert_result(
40
+ event=ev,
41
+ event_class=Event,
42
+ source=None,
43
+ type='test_event',
44
+ sources=[None])
45
+
46
+ def test_emitter_source(self):
47
+ """Emitter constructed with source argument"""
48
+ em = EventEmitter(source=self)
49
+ ev = self.try_emitter(em, type='test_event')
50
+ self.assert_result(
51
+ event=ev,
52
+ event_class=Event,
53
+ source=self,
54
+ type='test_event',
55
+ sources=[self])
56
+
57
+ # overriding source should fail:
58
+ try:
59
+ ev = em(type='test_event', source=None)
60
+ assert False, "Should not be able to specify source when emitting"
61
+ except AttributeError:
62
+ pass
63
+
64
+ def test_emitter_type(self):
65
+ """Emitter constructed with type argument"""
66
+ em = EventEmitter(type='asdf')
67
+ ev = self.try_emitter(em)
68
+ self.assert_result(
69
+ event=ev,
70
+ event_class=Event,
71
+ source=None,
72
+ type='asdf',
73
+ sources=[None])
74
+
75
+ # overriding type is ok:
76
+ ev = self.try_emitter(em, type='qwer')
77
+ self.assert_result(
78
+ event=ev,
79
+ event_class=Event,
80
+ source=None,
81
+ type='qwer',
82
+ sources=[None])
83
+
84
+ def test_emitter_type_event_class(self):
85
+ """Emitter constructed with event_class argument"""
86
+ em = EventEmitter(event_class=BasicEvent)
87
+ ev = self.try_emitter(em, type='test_event')
88
+ self.assert_result(
89
+ event=ev,
90
+ event_class=BasicEvent,
91
+ source=None,
92
+ type='test_event',
93
+ sources=[None])
94
+
95
+ # specifying non-event class should fail (eventually):
96
+ class X:
97
+
98
+ def __init__(self, *args, **kwargs):
99
+ self.blocked = False
100
+
101
+ def _push_source(self, s):
102
+ pass
103
+
104
+ def _pop_source(self):
105
+ pass
106
+
107
+ try:
108
+ em = EventEmitter(event_class=X)
109
+ ev = self.try_emitter(em, type='test_event')
110
+ self.assert_result() # checks event type
111
+ assert False, \
112
+ "Should not be able to construct emitter with non-Event class"
113
+ except Exception:
114
+ pass
115
+
116
+ def test_event_kwargs(self):
117
+ """Extra Event kwargs"""
118
+ em = EventEmitter(type='test_event')
119
+ em.default_args['key1'] = 'test1'
120
+ em.connect(self.record_event)
121
+ self.result = None
122
+ em(key2='test2')
123
+ self.assert_result(key1='test1', key2='test2')
124
+
125
+ def test_prebuilt_event(self):
126
+ """Emit pre-built event"""
127
+ em = EventEmitter(type='test_event')
128
+ em.default_args['key1'] = 'test1'
129
+ em.connect(self.record_event)
130
+
131
+ self.result = None
132
+ ev = Event(type='my_type')
133
+ em(ev)
134
+ self.assert_result(event=ev, type='my_type')
135
+ assert not hasattr(self.result[0], 'key1')
136
+
137
+ def test_emitter_subclass(self):
138
+ """The EventEmitter subclassing"""
139
+ class MyEmitter(EventEmitter):
140
+
141
+ def _prepare_event(self, *args, **kwargs):
142
+ ev = super(MyEmitter, self)._prepare_event(*args, **kwargs)
143
+ ev.test_tag = 1
144
+ return ev
145
+ em = MyEmitter(type='test_event')
146
+ em.connect(self.record_event)
147
+ self.result = None
148
+ em()
149
+ self.assert_result(test_tag=1)
150
+
151
+ def test_typed_event(self):
152
+ """Emit Event class with pre-specified type"""
153
+ em = EventEmitter(event_class=TypedEvent)
154
+ ev = self.try_emitter(em) # no need to specify type here
155
+ self.assert_result(
156
+ event=ev,
157
+ event_class=TypedEvent,
158
+ source=None,
159
+ type='typed_event',
160
+ sources=[None])
161
+
162
+ def test_disconnect(self):
163
+ """Emitter disconnection"""
164
+ em = EventEmitter(type='test_event')
165
+
166
+ def cb1(ev):
167
+ self.result = 1
168
+
169
+ def cb2(ev):
170
+ self.result = 2
171
+
172
+ em.connect((self, 'record_event'))
173
+ em.connect(cb1)
174
+ em.connect(cb2)
175
+ self.result = None
176
+ em.disconnect(cb2)
177
+ em.disconnect(cb2) # should pass silently
178
+ ev = em()
179
+ self.assert_result(event=ev)
180
+
181
+ self.result = None
182
+ em.disconnect((self, 'record_event'))
183
+ ev = em()
184
+ assert self.result == 1
185
+
186
+ self.result = None
187
+ em.connect(cb1)
188
+ em.connect(cb2)
189
+ em.connect((self, 'record_event'))
190
+ em.disconnect()
191
+ em()
192
+ assert self.result is None
193
+
194
+ def test_reconnect(self):
195
+ """Ignore callback reconnect"""
196
+ em = EventEmitter(type='test_event')
197
+
198
+ def cb(ev):
199
+ self.result += 1
200
+
201
+ em.connect(cb)
202
+ em.connect(cb) # second connection should do nothing.
203
+ self.result = 0
204
+ em()
205
+ assert self.result == 1
206
+
207
+ def test_decorator_connection(self):
208
+ """Connection by decorator"""
209
+ em = EventEmitter(type='test_event')
210
+
211
+ @em.connect
212
+ def cb(ev):
213
+ self.result = 1
214
+
215
+ self.result = None
216
+ em()
217
+ assert self.result == 1
218
+
219
+ def test_chained_emitters(self):
220
+ """Chained emitters"""
221
+ em1 = EventEmitter(source=None, type='test_event1')
222
+ em2 = EventEmitter(source=self, type='test_event2')
223
+ em1.connect(em2)
224
+ em1.connect(self.record_event)
225
+ self.result = None
226
+ ev = em1()
227
+ self.assert_result(
228
+ event=ev,
229
+ event_class=Event,
230
+ source=None,
231
+ type='test_event1',
232
+ sources=[None])
233
+
234
+ # sources look different from second emitter, but type is the same.
235
+ em1.disconnect(self.record_event)
236
+ em2.connect(self.record_event)
237
+ self.result = None
238
+ ev = em1()
239
+ self.assert_result(
240
+ event=ev,
241
+ event_class=Event,
242
+ source=self,
243
+ type='test_event1',
244
+ sources=[
245
+ None,
246
+ self])
247
+
248
+ def test_emitter_error_handling(self):
249
+ """Emitter error handling"""
250
+ em = EventEmitter(type='test_event')
251
+ em.print_callback_errors = 'never'
252
+
253
+ def cb(ev):
254
+ raise Exception('test')
255
+
256
+ # first callback fails; second callback still runs.
257
+ em.connect(self.record_event)
258
+ em.connect(cb)
259
+ self.result = None
260
+ ev = em()
261
+ self.assert_result(event=ev)
262
+
263
+ # this time we should get an exception
264
+ self.result = None
265
+ em.ignore_callback_errors = False
266
+ try:
267
+ em()
268
+ assert False, "Emission should have raised exception"
269
+ except Exception as err:
270
+ if str(err) != 'test':
271
+ raise
272
+
273
+ def test_emission_order(self):
274
+ """Event emission order"""
275
+ em = EventEmitter(type='test_event')
276
+
277
+ def cb1(ev):
278
+ self.result = 1
279
+
280
+ def cb2(ev):
281
+ self.result = 2
282
+
283
+ em.connect(cb1)
284
+ em.connect(cb2)
285
+ self.result = None
286
+ em()
287
+ assert self.result == 1, "Events emitted in wrong order"
288
+
289
+ em.disconnect()
290
+ em.connect(cb2)
291
+ em.connect(cb1)
292
+ self.result = None
293
+ em()
294
+ assert self.result == 2, "Events emitted in wrong order"
295
+
296
+ def test_multiple_callbacks(self):
297
+ """Multiple emitter callbacks"""
298
+ em = EventEmitter(type='test_event')
299
+ em.connect(functools.partial(self.record_event, key=1))
300
+ em.connect(functools.partial(self.record_event, key=2))
301
+ em.connect(functools.partial(self.record_event, key=3))
302
+ ev = em()
303
+ self.assert_result(key=1, event=ev, sources=[None])
304
+ self.assert_result(key=2, event=ev, sources=[None])
305
+ self.assert_result(key=3, event=ev, sources=[None])
306
+
307
+ def test_symbolic_callback(self):
308
+ """Symbolic callbacks"""
309
+ em = EventEmitter(type='test_event')
310
+ em.connect((self, 'record_event'))
311
+ ev = em()
312
+ self.assert_result(event=ev)
313
+
314
+ # now check overriding the connected method
315
+ def cb(ev):
316
+ self.result = 1
317
+
318
+ self.result = None
319
+ orig_method = self.record_event
320
+ try:
321
+ self.record_event = cb
322
+ em()
323
+ assert self.result == 1
324
+ finally:
325
+ self.record_event = orig_method
326
+
327
+ def test_source_stack_integrity(self):
328
+ """Emitter checks source stack"""
329
+ em = EventEmitter(type='test_event')
330
+
331
+ def cb(ev):
332
+ ev._sources.append('x')
333
+ em.connect(cb)
334
+
335
+ try:
336
+ em()
337
+ except RuntimeError as err:
338
+ if str(err) != 'Event source-stack mismatch.':
339
+ raise
340
+
341
+ em.disconnect()
342
+
343
+ def cb(ev):
344
+ ev._sources = []
345
+ em.connect(cb)
346
+
347
+ try:
348
+ em()
349
+ except IndexError:
350
+ pass
351
+
352
+ def test_emitter_loop(self):
353
+ """Catch emitter loops"""
354
+ em1 = EventEmitter(type='test_event1')
355
+ em2 = EventEmitter(type='test_event2')
356
+ em1.ignore_callback_errors = False
357
+ em2.ignore_callback_errors = False
358
+
359
+ # cross-connect emitters; when we emit, an exception should be raised
360
+ # indicating an event loop.
361
+ em1.connect(em2)
362
+ em2.connect(em1)
363
+ try:
364
+ em1()
365
+ except RuntimeError as err:
366
+ if str(err) != 'EventEmitter loop detected!':
367
+ raise err
368
+
369
+ def test_emitter_block(self):
370
+ """EventEmitter.blocker"""
371
+ em = EventEmitter(type='test_event')
372
+ em.connect(self.record_event)
373
+ self.result = None
374
+
375
+ with em.blocker():
376
+ em()
377
+ assert self.result is None
378
+
379
+ ev = em()
380
+ self.assert_result(event=ev)
381
+
382
+ def test_event_handling(self):
383
+ """Event.handled"""
384
+ em = EventEmitter(type='test_event')
385
+
386
+ def cb1(ev):
387
+ ev.handled = True
388
+
389
+ def cb2(ev):
390
+ assert ev.handled
391
+ self.result = 1
392
+ em.connect(cb2)
393
+ em.connect(cb1)
394
+ self.result = None
395
+ em()
396
+ assert self.result == 1
397
+
398
+ def test_event_block(self):
399
+ """Event.blocked"""
400
+ em = EventEmitter(type='test_event')
401
+
402
+ def cb1(ev):
403
+ ev.handled = True
404
+ self.result = 1
405
+
406
+ def cb2(ev):
407
+ ev.blocked = True
408
+ self.result = 2
409
+
410
+ em.connect(self.record_event)
411
+ em.connect(cb1)
412
+ self.result = None
413
+ em()
414
+ self.assert_result()
415
+
416
+ em.connect(cb2)
417
+ self.result = None
418
+ em()
419
+ assert self.result == 2
420
+
421
+ def try_emitter(self, em, **kwargs):
422
+ em.connect(self.record_event)
423
+ self.result = None
424
+ return em(**kwargs)
425
+
426
+ def record_event(self, ev, key=None):
427
+ # get a copy of all event attributes because these may change
428
+ # as the event is passed around; we want to know exactly what the event
429
+ # looked like when it reached this callback.
430
+ names = [name for name in dir(ev) if name[0] != '_']
431
+ attrs = {}
432
+ for name in names:
433
+ val = getattr(ev, name)
434
+ if name == 'source':
435
+ attrs[name] = val
436
+ elif name == 'sources':
437
+ attrs[name] = val[:]
438
+ else:
439
+ try:
440
+ attrs[name] = copy.deepcopy(val)
441
+ except Exception:
442
+ try:
443
+ attrs[name] = copy.copy(val)
444
+ except Exception:
445
+ attrs[name] = val
446
+ if key is None:
447
+ self.result = ev, attrs
448
+ else:
449
+ if not hasattr(self, 'result') or self.result is None:
450
+ self.result = {}
451
+ self.result[key] = ev, attrs
452
+
453
+ def assert_result(self, key=None, **kwargs):
454
+ assert (hasattr(self, 'result') and self.result is not None), \
455
+ "No event recorded"
456
+
457
+ if key is None:
458
+ event, event_attrs = self.result
459
+ else:
460
+ event, event_attrs = self.result[key]
461
+
462
+ assert isinstance(event, Event), "Emitted object is not Event instance"
463
+
464
+ for name, val in kwargs.items():
465
+ if name == 'event':
466
+ assert event is val, "Event objects do not match"
467
+
468
+ elif name == 'event_class':
469
+ assert isinstance(event, val), \
470
+ "Emitted object is not instance of %s" % val.__name__
471
+
472
+ else:
473
+ attr = event_attrs[name]
474
+ assert (attr == val), "Event.%s != %s (%s)" % (
475
+ name, str(val), str(attr))
476
+
477
+
478
+ def test_event_connect_order():
479
+ """Test event connection order"""
480
+ def a():
481
+ return
482
+
483
+ def b():
484
+ return
485
+
486
+ def c():
487
+ return
488
+
489
+ def d():
490
+ return
491
+
492
+ def e():
493
+ return
494
+
495
+ def f():
496
+ return
497
+
498
+ em = EventEmitter(type='test_event')
499
+ assert_raises(ValueError, em.connect, c, before=['c', 'foo'])
500
+ assert_raises(ValueError, em.connect, c, position='foo')
501
+ assert_raises(TypeError, em.connect, c, ref=dict())
502
+ em.connect(c, ref=True)
503
+ assert_equal((c,), tuple(em.callbacks))
504
+ em.connect(c)
505
+ assert_equal((c,), tuple(em.callbacks))
506
+ em.connect(d, ref=True, position='last')
507
+ assert_equal((c, d), tuple(em.callbacks))
508
+ em.connect(b, ref=True) # position='first'
509
+ assert_equal((b, c, d), tuple(em.callbacks))
510
+ assert_raises(RuntimeError, em.connect, a, before='c', after='d') # can't
511
+ em.connect(a, ref=True, before=['c', 'd']) # first possible pos == 0
512
+ assert_equal((a, b, c, d), tuple(em.callbacks))
513
+ em.connect(f, ref=True, after=['c', 'd'])
514
+ assert_equal((a, b, c, d, f), tuple(em.callbacks))
515
+ em.connect(e, ref=True, after='d', before='f')
516
+ assert_equal(('a', 'b', 'c', 'd', 'e', 'f'), tuple(em.callback_refs))
517
+ em.disconnect(e)
518
+ em.connect(e, ref=True, after='a', before='f', position='last')
519
+ assert_equal(('a', 'b', 'c', 'd', 'e', 'f'), tuple(em.callback_refs))
520
+ em.disconnect(e)
521
+ em.connect(e, ref='e', after='d', before='f', position='last')
522
+ assert_equal(('a', 'b', 'c', 'd', 'e', 'f'), tuple(em.callback_refs))
523
+ em.disconnect(e)
524
+ em.connect(e, after='d', before='f', position='first') # no name
525
+ assert_equal(('a', 'b', 'c', 'd', None, 'f'), tuple(em.callback_refs))
526
+ em.disconnect(e)
527
+ assert_raises(ValueError, em.connect, e, ref='d') # duplicate name
528
+ em.connect(e, ref=True, after=[], before='f', position='last')
529
+ assert_equal(('a', 'b', 'c', 'd', 'e', 'f'), tuple(em.callback_refs))
530
+ assert_equal((a, b, c, d, e, f), tuple(em.callbacks))
531
+
532
+ old_e = e
533
+
534
+ def e():
535
+ return
536
+
537
+ assert_raises(ValueError, em.connect, e, ref=True) # duplicate name
538
+ em.connect(e)
539
+ assert_equal((None, 'a', 'b', 'c', 'd', 'e', 'f'),
540
+ tuple(em.callback_refs))
541
+ assert_equal((e, a, b, c, d, old_e, f), tuple(em.callbacks))
542
+
543
+
544
+ def test_emitter_block():
545
+ state = [False, False]
546
+
547
+ def a(ev):
548
+ state[0] = True
549
+
550
+ def b(ev):
551
+ state[1] = True
552
+
553
+ e = EventEmitter(source=None, type='event')
554
+ e.connect(a)
555
+ e.connect(b)
556
+
557
+ def assert_state(a, b):
558
+ assert state == [a, b]
559
+ state[0] = False
560
+ state[1] = False
561
+
562
+ e()
563
+ assert_state(True, True)
564
+
565
+ # test global blocking
566
+ e.block()
567
+ e()
568
+ assert_state(False, False)
569
+ e.block()
570
+ e()
571
+ assert_state(False, False)
572
+
573
+ # test global unlock, multiple depth
574
+ e.unblock()
575
+ e()
576
+ assert_state(False, False)
577
+ e.unblock()
578
+ e()
579
+ assert_state(True, True)
580
+
581
+ # test unblock failure
582
+ try:
583
+ e.unblock()
584
+ raise Exception("Expected RuntimeError")
585
+ except RuntimeError:
586
+ pass
587
+
588
+ # test single block
589
+ e.block(a)
590
+ e()
591
+ assert_state(False, True)
592
+
593
+ e.block(b)
594
+ e()
595
+ assert_state(False, False)
596
+
597
+ e.block(b)
598
+ e()
599
+ assert_state(False, False)
600
+
601
+ # test single unblock
602
+ e.unblock(a)
603
+ e()
604
+ assert_state(True, False)
605
+
606
+ e.unblock(b)
607
+ e()
608
+ assert_state(True, False)
609
+
610
+ e.unblock(b)
611
+ e()
612
+ assert_state(True, True)
613
+
614
+ # Test single unblock failure
615
+ try:
616
+ e.unblock(a)
617
+ raise Exception("Expected RuntimeError")
618
+ except RuntimeError:
619
+ pass
620
+
621
+ # test global blocker
622
+ with e.blocker():
623
+ e()
624
+ assert_state(False, False)
625
+
626
+ # test nested blocker
627
+ with e.blocker():
628
+ e()
629
+ assert_state(False, False)
630
+
631
+ e()
632
+ assert_state(False, False)
633
+
634
+ e()
635
+ assert_state(True, True)
636
+
637
+ # test single blocker
638
+ with e.blocker(a):
639
+ e()
640
+ assert_state(False, True)
641
+
642
+ # test nested gloabel blocker
643
+ with e.blocker():
644
+ e()
645
+ assert_state(False, False)
646
+
647
+ e()
648
+ assert_state(False, True)
649
+
650
+ # test nested single blocker
651
+ with e.blocker(a):
652
+ e()
653
+ assert_state(False, True)
654
+
655
+ with e.blocker(b):
656
+ e()
657
+ assert_state(False, False)
658
+
659
+ e()
660
+ assert_state(False, True)
661
+
662
+ e()
663
+ assert_state(True, True)
664
+
665
+
666
+ def test_emitter_reentrance_allowed_when_blocked1():
667
+ # Minimal re-entrance example
668
+
669
+ e = EventEmitter(source=None, type='test')
670
+ count = 0
671
+
672
+ @e.connect
673
+ def foo(x):
674
+ nonlocal count
675
+ count += 1
676
+ with e.blocker():
677
+ e()
678
+
679
+ e()
680
+ assert count == 1
681
+
682
+
683
+ def test_emitter_reentrance_allowed_when_blocked2():
684
+ # More realistic re-entrance example
685
+ # The real world case for this might be a longer chain of events
686
+ # where event1's callback knows that what it's doing will trigger
687
+ # the same event so it blocks it:
688
+ # event1 -> foo -> event2 -> bar -> event1 -> (ignored bc blocked).
689
+
690
+ e1 = EventEmitter(source=None, type='test1')
691
+ e2 = EventEmitter(source=None, type='test2')
692
+ count = 0
693
+
694
+ @e1.connect
695
+ def foo(x):
696
+ nonlocal count
697
+ count += 1
698
+ with e1.blocker():
699
+ e2()
700
+
701
+ @e2.connect
702
+ def bar(x):
703
+ nonlocal count
704
+ count += 10
705
+ e1()
706
+
707
+ e1()
708
+ assert count == 11
709
+
710
+
711
+ def test_emitter_reentrance_allowed_when_blocked3():
712
+ # Like the previous, but blocking callbacks instead of the event itself.
713
+ # Allows more fine-grained control. To some extent anyway - all callbacks
714
+ # of the event must be blocked to prevent raising the emitter loop error.
715
+
716
+ e1 = EventEmitter(source=None, type='test1')
717
+ e2 = EventEmitter(source=None, type='test2')
718
+ count = 0
719
+
720
+ @e1.connect
721
+ def foo(x):
722
+ nonlocal count
723
+ count += 1
724
+ with e1.blocker(foo):
725
+ e2()
726
+
727
+ @e2.connect
728
+ def bar(x):
729
+ nonlocal count
730
+ count += 10
731
+ e1()
732
+
733
+ @e2.connect
734
+ def eggs(x):
735
+ nonlocal count
736
+ count += 100
737
+ e1()
738
+
739
+ e1()
740
+ assert count == 111
741
+
742
+
743
+ run_tests_if_main()