datajoint 0.14.3__tar.gz → 0.14.5__tar.gz

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 datajoint might be problematic. Click here for more details.

Files changed (257) hide show
  1. {datajoint-0.14.3 → datajoint-0.14.5}/PKG-INFO +138 -28
  2. datajoint-0.14.5/README.md +143 -0
  3. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/__init__.py +14 -15
  4. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/admin.py +4 -2
  5. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/attribute_adapter.py +1 -0
  6. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/autopopulate.py +124 -26
  7. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/blob.py +8 -7
  8. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/cli.py +1 -0
  9. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/condition.py +10 -8
  10. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/connection.py +17 -10
  11. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/declare.py +6 -4
  12. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/dependencies.py +3 -1
  13. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/diagram.py +7 -7
  14. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/expression.py +11 -10
  15. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/external.py +11 -9
  16. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/fetch.py +7 -5
  17. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/heading.py +11 -10
  18. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/jobs.py +4 -3
  19. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/plugin.py +5 -3
  20. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/preview.py +1 -1
  21. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/s3.py +5 -3
  22. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/schemas.py +14 -13
  23. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/settings.py +18 -12
  24. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/table.py +29 -26
  25. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/user_tables.py +3 -2
  26. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/utils.py +4 -1
  27. datajoint-0.14.5/datajoint/version.py +6 -0
  28. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint.egg-info/PKG-INFO +138 -28
  29. datajoint-0.14.5/datajoint.egg-info/SOURCES.txt +80 -0
  30. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint.egg-info/requires.txt +11 -2
  31. datajoint-0.14.5/pyproject.toml +105 -0
  32. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_adapted_attributes.py +6 -3
  33. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_admin.py +3 -1
  34. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_aggr_regressions.py +6 -3
  35. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_alter.py +5 -2
  36. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_attach.py +4 -2
  37. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_autopopulate.py +4 -2
  38. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_blob.py +8 -5
  39. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_blob_matlab.py +2 -1
  40. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_bypass_serialization.py +3 -2
  41. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_cascading_delete.py +3 -1
  42. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_cli.py +2 -0
  43. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_connection.py +3 -2
  44. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_declare.py +5 -3
  45. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_dependencies.py +3 -1
  46. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_erd.py +2 -1
  47. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_external.py +7 -4
  48. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_external_class.py +2 -0
  49. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_fetch.py +12 -9
  50. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_fetch_same.py +2 -1
  51. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_filepath.py +8 -5
  52. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_foreign_keys.py +1 -0
  53. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_jobs.py +6 -3
  54. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_json.py +5 -3
  55. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_nan.py +2 -1
  56. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_plugin.py +4 -2
  57. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_privileges.py +3 -0
  58. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_reconnection.py +1 -0
  59. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_relation.py +7 -4
  60. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_relation_u.py +3 -1
  61. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_relational_operand.py +7 -5
  62. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_s3.py +5 -3
  63. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_schema.py +5 -2
  64. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_schema_keywords.py +1 -0
  65. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_settings.py +4 -2
  66. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_tls.py +2 -1
  67. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_university.py +6 -3
  68. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_update1.py +5 -3
  69. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_utils.py +3 -6
  70. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_uuid.py +6 -3
  71. datajoint-0.14.3/.codespellrc +0 -5
  72. datajoint-0.14.3/.coveragerc +0 -6
  73. datajoint-0.14.3/.devcontainer/Dockerfile +0 -13
  74. datajoint-0.14.3/.devcontainer/devcontainer.json +0 -50
  75. datajoint-0.14.3/.devcontainer/docker-compose.yml +0 -32
  76. datajoint-0.14.3/.dockerignore +0 -6
  77. datajoint-0.14.3/.github/ISSUE_TEMPLATE/bug_report.md +0 -37
  78. datajoint-0.14.3/.github/ISSUE_TEMPLATE/feature_request.md +0 -46
  79. datajoint-0.14.3/.github/workflows/development.yaml +0 -239
  80. datajoint-0.14.3/.github/workflows/docs.yaml +0 -19
  81. datajoint-0.14.3/.gitignore +0 -35
  82. datajoint-0.14.3/.vscode/launch.json +0 -16
  83. datajoint-0.14.3/.vscode/settings.json +0 -21
  84. datajoint-0.14.3/CHANGELOG.md +0 -338
  85. datajoint-0.14.3/Dockerfile +0 -24
  86. datajoint-0.14.3/README.md +0 -50
  87. datajoint-0.14.3/datajoint/version.py +0 -3
  88. datajoint-0.14.3/datajoint.egg-info/SOURCES.txt +0 -251
  89. datajoint-0.14.3/datajoint.pub +0 -6
  90. datajoint-0.14.3/docker-compose.yaml +0 -79
  91. datajoint-0.14.3/docs/.docker/Dockerfile +0 -15
  92. datajoint-0.14.3/docs/.docker/apk_requirements.txt +0 -1
  93. datajoint-0.14.3/docs/.docker/pip_requirements.txt +0 -11
  94. datajoint-0.14.3/docs/.markdownlint.yaml +0 -20
  95. datajoint-0.14.3/docs/README.md +0 -16
  96. datajoint-0.14.3/docs/docker-compose.yaml +0 -38
  97. datajoint-0.14.3/docs/mkdocs.yaml +0 -194
  98. datajoint-0.14.3/docs/src/.overrides/.icons/main/company-logo.svg +0 -11
  99. datajoint-0.14.3/docs/src/.overrides/assets/images/company-logo-blue.png +0 -0
  100. datajoint-0.14.3/docs/src/.overrides/assets/stylesheets/extra.css +0 -105
  101. datajoint-0.14.3/docs/src/.overrides/partials/nav.html +0 -33
  102. datajoint-0.14.3/docs/src/api/make_pages.py +0 -18
  103. datajoint-0.14.3/docs/src/changelog.md +0 -338
  104. datajoint-0.14.3/docs/src/citation.md +0 -7
  105. datajoint-0.14.3/docs/src/client/credentials.md +0 -46
  106. datajoint-0.14.3/docs/src/client/install.md +0 -209
  107. datajoint-0.14.3/docs/src/client/settings.md +0 -11
  108. datajoint-0.14.3/docs/src/client/stores.md +0 -1
  109. datajoint-0.14.3/docs/src/compute/distributed.md +0 -166
  110. datajoint-0.14.3/docs/src/compute/key-source.md +0 -51
  111. datajoint-0.14.3/docs/src/compute/make.md +0 -25
  112. datajoint-0.14.3/docs/src/compute/populate.md +0 -127
  113. datajoint-0.14.3/docs/src/concepts/data-model.md +0 -117
  114. datajoint-0.14.3/docs/src/concepts/data-pipelines.md +0 -166
  115. datajoint-0.14.3/docs/src/concepts/principles.md +0 -136
  116. datajoint-0.14.3/docs/src/concepts/teamwork.md +0 -100
  117. datajoint-0.14.3/docs/src/concepts/terminology.md +0 -127
  118. datajoint-0.14.3/docs/src/design/alter.md +0 -1
  119. datajoint-0.14.3/docs/src/design/diagrams.md +0 -110
  120. datajoint-0.14.3/docs/src/design/drop.md +0 -23
  121. datajoint-0.14.3/docs/src/design/integrity.md +0 -218
  122. datajoint-0.14.3/docs/src/design/normalization.md +0 -117
  123. datajoint-0.14.3/docs/src/design/recall.md +0 -207
  124. datajoint-0.14.3/docs/src/design/schema.md +0 -49
  125. datajoint-0.14.3/docs/src/design/tables/attach.md +0 -67
  126. datajoint-0.14.3/docs/src/design/tables/attributes.md +0 -88
  127. datajoint-0.14.3/docs/src/design/tables/blobs.md +0 -1
  128. datajoint-0.14.3/docs/src/design/tables/customtype.md +0 -1
  129. datajoint-0.14.3/docs/src/design/tables/declare.md +0 -242
  130. datajoint-0.14.3/docs/src/design/tables/dependencies.md +0 -241
  131. datajoint-0.14.3/docs/src/design/tables/filepath.md +0 -96
  132. datajoint-0.14.3/docs/src/design/tables/indexes.md +0 -1
  133. datajoint-0.14.3/docs/src/design/tables/lookup.md +0 -31
  134. datajoint-0.14.3/docs/src/design/tables/manual.md +0 -47
  135. datajoint-0.14.3/docs/src/design/tables/master-part.md +0 -112
  136. datajoint-0.14.3/docs/src/design/tables/primary.md +0 -178
  137. datajoint-0.14.3/docs/src/design/tables/tiers.md +0 -68
  138. datajoint-0.14.3/docs/src/develop.md +0 -126
  139. datajoint-0.14.3/docs/src/faq.md +0 -191
  140. datajoint-0.14.3/docs/src/images/StudentTable.png +0 -0
  141. datajoint-0.14.3/docs/src/images/added-example-ERD.svg +0 -207
  142. datajoint-0.14.3/docs/src/images/data-engineering.png +0 -0
  143. datajoint-0.14.3/docs/src/images/data-science-after.png +0 -0
  144. datajoint-0.14.3/docs/src/images/data-science-before.png +0 -0
  145. datajoint-0.14.3/docs/src/images/diff-example1.png +0 -0
  146. datajoint-0.14.3/docs/src/images/diff-example2.png +0 -0
  147. datajoint-0.14.3/docs/src/images/diff-example3.png +0 -0
  148. datajoint-0.14.3/docs/src/images/dimitri-ERD.svg +0 -117
  149. datajoint-0.14.3/docs/src/images/doc_1-1.png +0 -0
  150. datajoint-0.14.3/docs/src/images/doc_1-many.png +0 -0
  151. datajoint-0.14.3/docs/src/images/doc_many-1.png +0 -0
  152. datajoint-0.14.3/docs/src/images/doc_many-many.png +0 -0
  153. datajoint-0.14.3/docs/src/images/how-it-works.png +0 -0
  154. datajoint-0.14.3/docs/src/images/install-cmd-prompt.png +0 -0
  155. datajoint-0.14.3/docs/src/images/install-datajoint-1.png +0 -0
  156. datajoint-0.14.3/docs/src/images/install-datajoint-2.png +0 -0
  157. datajoint-0.14.3/docs/src/images/install-git-1.png +0 -0
  158. datajoint-0.14.3/docs/src/images/install-graphviz-1.png +0 -0
  159. datajoint-0.14.3/docs/src/images/install-graphviz-2a.png +0 -0
  160. datajoint-0.14.3/docs/src/images/install-graphviz-2b.png +0 -0
  161. datajoint-0.14.3/docs/src/images/install-jupyter-1.png +0 -0
  162. datajoint-0.14.3/docs/src/images/install-jupyter-2.png +0 -0
  163. datajoint-0.14.3/docs/src/images/install-matplotlib.png +0 -0
  164. datajoint-0.14.3/docs/src/images/install-pydotplus.png +0 -0
  165. datajoint-0.14.3/docs/src/images/install-python-advanced-1.png +0 -0
  166. datajoint-0.14.3/docs/src/images/install-python-advanced-2.png +0 -0
  167. datajoint-0.14.3/docs/src/images/install-python-simple.png +0 -0
  168. datajoint-0.14.3/docs/src/images/install-run-jupyter-1.png +0 -0
  169. datajoint-0.14.3/docs/src/images/install-run-jupyter-2.png +0 -0
  170. datajoint-0.14.3/docs/src/images/install-verify-graphviz.png +0 -0
  171. datajoint-0.14.3/docs/src/images/install-verify-jupyter.png +0 -0
  172. datajoint-0.14.3/docs/src/images/install-verify-python.png +0 -0
  173. datajoint-0.14.3/docs/src/images/join-example1.png +0 -0
  174. datajoint-0.14.3/docs/src/images/join-example2.png +0 -0
  175. datajoint-0.14.3/docs/src/images/join-example3.png +0 -0
  176. datajoint-0.14.3/docs/src/images/key_source_combination.png +0 -0
  177. datajoint-0.14.3/docs/src/images/map-dataflow.png +0 -0
  178. datajoint-0.14.3/docs/src/images/matched_tuples1.png +0 -0
  179. datajoint-0.14.3/docs/src/images/matched_tuples2.png +0 -0
  180. datajoint-0.14.3/docs/src/images/matched_tuples3.png +0 -0
  181. datajoint-0.14.3/docs/src/images/mp-diagram.png +0 -0
  182. datajoint-0.14.3/docs/src/images/op-restrict.png +0 -0
  183. datajoint-0.14.3/docs/src/images/outer-example1.png +0 -0
  184. datajoint-0.14.3/docs/src/images/pipeline-database.png +0 -0
  185. datajoint-0.14.3/docs/src/images/pipeline.png +0 -0
  186. datajoint-0.14.3/docs/src/images/python_collection.png +0 -0
  187. datajoint-0.14.3/docs/src/images/queries_example_diagram.png +0 -0
  188. datajoint-0.14.3/docs/src/images/query_object_preview.png +0 -0
  189. datajoint-0.14.3/docs/src/images/restrict-example1.png +0 -0
  190. datajoint-0.14.3/docs/src/images/restrict-example2.png +0 -0
  191. datajoint-0.14.3/docs/src/images/restrict-example3.png +0 -0
  192. datajoint-0.14.3/docs/src/images/shapes_pipeline.svg +0 -36
  193. datajoint-0.14.3/docs/src/images/spawned-classes-ERD.svg +0 -155
  194. datajoint-0.14.3/docs/src/images/union-example1.png +0 -0
  195. datajoint-0.14.3/docs/src/images/union-example2.png +0 -0
  196. datajoint-0.14.3/docs/src/images/virtual-module-ERD.svg +0 -155
  197. datajoint-0.14.3/docs/src/index.md +0 -44
  198. datajoint-0.14.3/docs/src/internal/transpilation.md +0 -170
  199. datajoint-0.14.3/docs/src/manipulation/delete.md +0 -31
  200. datajoint-0.14.3/docs/src/manipulation/index.md +0 -9
  201. datajoint-0.14.3/docs/src/manipulation/insert.md +0 -94
  202. datajoint-0.14.3/docs/src/manipulation/transactions.md +0 -36
  203. datajoint-0.14.3/docs/src/manipulation/update.md +0 -48
  204. datajoint-0.14.3/docs/src/publish-data.md +0 -34
  205. datajoint-0.14.3/docs/src/query/aggregation.md +0 -29
  206. datajoint-0.14.3/docs/src/query/example-schema.md +0 -112
  207. datajoint-0.14.3/docs/src/query/fetch.md +0 -126
  208. datajoint-0.14.3/docs/src/query/iteration.md +0 -36
  209. datajoint-0.14.3/docs/src/query/join.md +0 -37
  210. datajoint-0.14.3/docs/src/query/operators.md +0 -395
  211. datajoint-0.14.3/docs/src/query/principles.md +0 -81
  212. datajoint-0.14.3/docs/src/query/project.md +0 -68
  213. datajoint-0.14.3/docs/src/query/query-caching.md +0 -42
  214. datajoint-0.14.3/docs/src/query/restrict.md +0 -193
  215. datajoint-0.14.3/docs/src/query/union.md +0 -48
  216. datajoint-0.14.3/docs/src/query/universals.md +0 -46
  217. datajoint-0.14.3/docs/src/quick-start.md +0 -460
  218. datajoint-0.14.3/docs/src/sysadmin/bulk-storage.md +0 -106
  219. datajoint-0.14.3/docs/src/sysadmin/database-admin.md +0 -364
  220. datajoint-0.14.3/docs/src/sysadmin/external-store.md +0 -293
  221. datajoint-0.14.3/docs/src/tutorials/json.ipynb +0 -1085
  222. datajoint-0.14.3/images/pipeline.drawio +0 -1
  223. datajoint-0.14.3/images/pipeline.png +0 -0
  224. datajoint-0.14.3/pyproject.toml +0 -71
  225. datajoint-0.14.3/tests/__init__.py +0 -0
  226. datajoint-0.14.3/tests/conftest.py +0 -535
  227. datajoint-0.14.3/tests/data/Course.csv +0 -46
  228. datajoint-0.14.3/tests/data/CurrentTerm.csv +0 -2
  229. datajoint-0.14.3/tests/data/Department.csv +0 -9
  230. datajoint-0.14.3/tests/data/Enroll.csv +0 -3365
  231. datajoint-0.14.3/tests/data/Grade.csv +0 -3028
  232. datajoint-0.14.3/tests/data/Section.csv +0 -757
  233. datajoint-0.14.3/tests/data/Student.csv +0 -301
  234. datajoint-0.14.3/tests/data/StudentMajor.csv +0 -227
  235. datajoint-0.14.3/tests/data/Term.csv +0 -19
  236. datajoint-0.14.3/tests/schema.py +0 -469
  237. datajoint-0.14.3/tests/schema_adapted.py +0 -62
  238. datajoint-0.14.3/tests/schema_advanced.py +0 -140
  239. datajoint-0.14.3/tests/schema_aggr_regress.py +0 -51
  240. datajoint-0.14.3/tests/schema_alter.py +0 -56
  241. datajoint-0.14.3/tests/schema_external.py +0 -88
  242. datajoint-0.14.3/tests/schema_privileges.py +0 -34
  243. datajoint-0.14.3/tests/schema_simple.py +0 -320
  244. datajoint-0.14.3/tests/schema_university.py +0 -112
  245. datajoint-0.14.3/tests/schema_uuid.py +0 -49
  246. {datajoint-0.14.3 → datajoint-0.14.5}/LICENSE.txt +0 -0
  247. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/errors.py +0 -0
  248. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/hash.py +1 -1
  249. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint/logging.py +0 -0
  250. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint.egg-info/dependency_links.txt +0 -0
  251. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint.egg-info/entry_points.txt +0 -0
  252. {datajoint-0.14.3 → datajoint-0.14.5}/datajoint.egg-info/top_level.txt +0 -0
  253. {datajoint-0.14.3 → datajoint-0.14.5}/setup.cfg +0 -0
  254. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_groupby.py +0 -0
  255. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_hash.py +0 -0
  256. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_log.py +0 -0
  257. {datajoint-0.14.3 → datajoint-0.14.5}/tests/test_virtual_module.py +0 -0
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: datajoint
3
- Version: 0.14.3
4
- Summary: A relational data pipeline framework.
3
+ Version: 0.14.5
4
+ Summary: DataJoint for Python is a framework for scientific workflow management based on relational principles. DataJoint is built on the foundation of the relational data model and prescribes a consistent method for organizing, populating, computing, and querying data.
5
5
  Author: Raphael Guzman, Edgar Walker
6
6
  Author-email: Dimitri Yatsenko <dimitri@datajoint.com>, DataJoint Contributors <support@datajoint.com>
7
7
  Maintainer-email: Dimitri Yatsenko <dimitri@datajoint.com>, DataJoint Contributors <support@datajoint.com>
@@ -510,18 +510,27 @@ License: GNU LESSER GENERAL PUBLIC LICENSE
510
510
 
511
511
  That's all there is to it!
512
512
 
513
- Project-URL: Homepage, https://datajoint.com/docs
514
- Project-URL: Documentation, https://datajoint.com/docs
513
+ Project-URL: Homepage, https://docs.datajoint.com/
514
+ Project-URL: Documentation, https://docs.datajoint.com/
515
515
  Project-URL: Repository, https://github.com/datajoint/datajoint-python
516
516
  Project-URL: Bug Tracker, https://github.com/datajoint/datajoint-python/issues
517
- Project-URL: Changelog, https://github.com/datajoint/datajoint-python/blob/master/CHANGELOG.md
518
- Keywords: database,data pipelines,scientific computing,automated research workflows
517
+ Project-URL: Release Notes, https://github.com/datajoint/datajoint-python/releases
518
+ Keywords: database,automated,automation,compute,data,pipeline,workflow,scientific,science,research,neuroscience,bioinformatics,bio-informatics,datajoint
519
519
  Classifier: Programming Language :: Python
520
- Requires-Python: <4.0,>=3.8
520
+ Classifier: Development Status :: 5 - Production/Stable
521
+ Classifier: Intended Audience :: Science/Research
522
+ Classifier: Intended Audience :: Healthcare Industry
523
+ Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
524
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
525
+ Classifier: Topic :: Scientific/Engineering
526
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
527
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
528
+ Requires-Python: <4.0,>=3.9
521
529
  Description-Content-Type: text/markdown
522
530
  License-File: LICENSE.txt
523
531
  Requires-Dist: numpy
524
532
  Requires-Dist: pymysql>=0.7.2
533
+ Requires-Dist: deepdiff
525
534
  Requires-Dist: pyparsing
526
535
  Requires-Dist: ipython
527
536
  Requires-Dist: pandas
@@ -534,31 +543,132 @@ Requires-Dist: otumat
534
543
  Requires-Dist: faker
535
544
  Requires-Dist: cryptography
536
545
  Requires-Dist: urllib3
546
+ Requires-Dist: setuptools
537
547
  Provides-Extra: test
538
548
  Requires-Dist: pytest; extra == "test"
539
549
  Requires-Dist: pytest-cov; extra == "test"
540
- Requires-Dist: black==24.2.0; extra == "test"
541
- Requires-Dist: flake8; extra == "test"
542
-
543
- [![DOI](https://zenodo.org/badge/16774/datajoint/datajoint-python.svg)](https://zenodo.org/badge/latestdoi/16774/datajoint/datajoint-python)
544
- [![Coverage Status](https://coveralls.io/repos/datajoint/datajoint-python/badge.svg?branch=master&service=github)](https://coveralls.io/github/datajoint/datajoint-python?branch=master)
545
- [![PyPI version](https://badge.fury.io/py/datajoint.svg)](http://badge.fury.io/py/datajoint)
546
- [![Slack](https://img.shields.io/badge/slack-chat-green.svg)](https://datajoint.slack.com/)
550
+ Provides-Extra: dev
551
+ Requires-Dist: pre-commit; extra == "dev"
552
+ Requires-Dist: black==24.2.0; extra == "dev"
553
+ Requires-Dist: flake8; extra == "dev"
554
+ Requires-Dist: isort; extra == "dev"
555
+ Requires-Dist: codespell; extra == "dev"
556
+ Requires-Dist: pytest; extra == "dev"
557
+ Requires-Dist: pytest-cov; extra == "dev"
558
+ Dynamic: license-file
547
559
 
548
560
  # Welcome to DataJoint for Python!
549
561
 
550
- DataJoint for Python is a framework for scientific workflow management based on
551
- relational principles. DataJoint is built on the foundation of the relational data
552
- model and prescribes a consistent method for organizing, populating, computing, and
562
+ <table>
563
+ <!-- Thank Zarr for providing badge insights! -->
564
+ <!-- https://github.com/zarr-developers/zarr-python/blob/main/README.md -->
565
+ <tr>
566
+ <td>PyPI</td>
567
+ <td>
568
+ <a href="https://pypi.org/project/datajoint/">
569
+ <img src="https://img.shields.io/pypi/v/datajoint?color=blue" alt="pypi release" />
570
+ </a>
571
+ <br>
572
+ <a href="https://pypi.org/project/datajoint/">
573
+ <img src="https://img.shields.io/pypi/dm/datajoint?color=yellow" alt="pypi downloads" />
574
+ </a>
575
+ </td>
576
+ </tr>
577
+ <tr>
578
+ <td>Conda Forge</td>
579
+ <td>
580
+ <a href="https://anaconda.org/conda-forge/datajoint">
581
+ <img src="https://img.shields.io/conda/vn/conda-forge/datajoint?color=brightgreen" alt="conda-forge release" />
582
+ </a>
583
+ <br>
584
+ <a href="https://anaconda.org/conda-forge/datajoint">
585
+ <img src="https://img.shields.io/conda/dn/conda-forge/datajoint?color=brightgreen" alt="conda-forge downloads" />
586
+ </a>
587
+ </td>
588
+ </tr>
589
+ <tr>
590
+ <td>Since Release</td>
591
+ <td>
592
+ <a id="commit-since-release-link" href="https://github.com/datajoint/datajoint-python/compare/v0.14.5...master">
593
+ <img id="commit-since-release-img" src="https://img.shields.io/github/commits-since/datajoint/datajoint-python/v0.14.5?color=red" alt="commit since last release" />
594
+ </a>
595
+ </td>
596
+ </tr>
597
+ <tr>
598
+ <td>Test Status</td>
599
+ <td>
600
+ <a href="https://github.com/datajoint/datajoint-python/actions/workflows/test.yaml">
601
+ <img src="https://github.com/datajoint/datajoint-python/actions/workflows/test.yaml/badge.svg" alt="test status" />
602
+ </a>
603
+ </td>
604
+ </tr>
605
+ <tr>
606
+ <td>Release Status</td>
607
+ <td>
608
+ <a href="https://github.com/datajoint/datajoint-python/actions/workflows/post_draft_release_published.yaml">
609
+ <img src="https://github.com/datajoint/datajoint-python/actions/workflows/post_draft_release_published.yaml/badge.svg" alt="release status" />
610
+ </a>
611
+ </td>
612
+ </tr>
613
+ <tr>
614
+ <td>Doc Status</td>
615
+ <td>
616
+ <a href="https://docs.datajoint.com">
617
+ <img src="https://github.com/datajoint/datajoint-python/actions/workflows/pages/pages-build-deployment/badge.svg" alt="doc status" />
618
+ </a>
619
+ </td>
620
+ </tr>
621
+ <tr>
622
+ <td>Coverage</td>
623
+ <td>
624
+ <a href="https://coveralls.io/github/datajoint/datajoint-python?branch=master">
625
+ <img src="https://coveralls.io/repos/datajoint/datajoint-python/badge.svg?branch=master&service=github"/ alt="coverage">
626
+ </a>
627
+ </td>
628
+ </tr>
629
+ <tr>
630
+ <td>Developer Chat</td>
631
+ <td>
632
+ <a href="https://datajoint.slack.com/">
633
+ <img src="https://img.shields.io/badge/slack-datajoint-purple.svg" alt="datajoint slack"/>
634
+ </a>
635
+ </td>
636
+ </tr>
637
+ <tr>
638
+ <td>License</td>
639
+ <td>
640
+ <a href="https://github.com/datajoint/datajoint-python/blob/master/LICENSE.txt">
641
+ <img src="https://img.shields.io/github/license/datajoint/datajoint-python" alt="LGPL-2.1" />
642
+ </a>
643
+ </td>
644
+ </tr>
645
+ <tr>
646
+ <td>Citation</td>
647
+ <td>
648
+ <a href="https://doi.org/10.1101/031658">
649
+ <img src="https://img.shields.io/badge/DOI-10.1101/bioRxiv.031658-B31B1B.svg" alt="bioRxiv">
650
+ </a>
651
+ <br>
652
+ <a href="https://doi.org/10.5281/zenodo.6829062">
653
+ <img src="https://zenodo.org/badge/DOI/10.5281/zenodo.6829062.svg" alt="zenodo">
654
+ </a>
655
+ </td>
656
+ </tr>
657
+
658
+ </table>
659
+
660
+ DataJoint for Python is a framework for scientific workflow management based on
661
+ relational principles. DataJoint is built on the foundation of the relational data
662
+ model and prescribes a consistent method for organizing, populating, computing, and
553
663
  querying data.
554
664
 
555
- DataJoint was initially developed in 2009 by Dimitri Yatsenko in Andreas Tolias' Lab at
556
- Baylor College of Medicine for the distributed processing and management of large
557
- volumes of data streaming from regular experiments. Starting in 2011, DataJoint has
558
- been available as an open-source project adopted by other labs and improved through
665
+ DataJoint was initially developed in 2009 by Dimitri Yatsenko in Andreas Tolias' Lab at
666
+ Baylor College of Medicine for the distributed processing and management of large
667
+ volumes of data streaming from regular experiments. Starting in 2011, DataJoint has
668
+ been available as an open-source project adopted by other labs and improved through
559
669
  contributions from several developers.
560
- Presently, the primary developer of DataJoint open-source software is the company
561
- DataJoint (https://datajoint.com).
670
+ Presently, the primary developer of DataJoint open-source software is the company
671
+ DataJoint (<https://datajoint.com>).
562
672
 
563
673
  ## Data Pipeline Example
564
674
 
@@ -580,13 +690,13 @@ DataJoint (https://datajoint.com).
580
690
  pip install datajoint
581
691
  ```
582
692
 
583
- - [Documentation & Tutorials](https://datajoint.com/docs/core/datajoint-python/)
693
+ - [Documentation & Tutorials](https://docs.datajoint.com/core/datajoint-python/)
584
694
 
585
695
  - [Interactive Tutorials](https://github.com/datajoint/datajoint-tutorials) on GitHub Codespaces
586
696
 
587
- - [DataJoint Elements](https://datajoint.com/docs/elements/) - Catalog of example pipelines for neuroscience experiments
697
+ - [DataJoint Elements](https://docs.datajoint.com/elements/) - Catalog of example pipelines for neuroscience experiments
588
698
 
589
699
  - Contribute
590
- - [Development Environment](https://datajoint.com/docs/core/datajoint-python/latest/develop/)
700
+ - [Contribution Guidelines](https://docs.datajoint.com/about/contribute/)
591
701
 
592
- - [Guidelines](https://datajoint.com/docs/about/contribute/)
702
+ - [Developer Guide](https://docs.datajoint.com/core/datajoint-python/latest/develop/)
@@ -0,0 +1,143 @@
1
+ # Welcome to DataJoint for Python!
2
+
3
+ <table>
4
+ <!-- Thank Zarr for providing badge insights! -->
5
+ <!-- https://github.com/zarr-developers/zarr-python/blob/main/README.md -->
6
+ <tr>
7
+ <td>PyPI</td>
8
+ <td>
9
+ <a href="https://pypi.org/project/datajoint/">
10
+ <img src="https://img.shields.io/pypi/v/datajoint?color=blue" alt="pypi release" />
11
+ </a>
12
+ <br>
13
+ <a href="https://pypi.org/project/datajoint/">
14
+ <img src="https://img.shields.io/pypi/dm/datajoint?color=yellow" alt="pypi downloads" />
15
+ </a>
16
+ </td>
17
+ </tr>
18
+ <tr>
19
+ <td>Conda Forge</td>
20
+ <td>
21
+ <a href="https://anaconda.org/conda-forge/datajoint">
22
+ <img src="https://img.shields.io/conda/vn/conda-forge/datajoint?color=brightgreen" alt="conda-forge release" />
23
+ </a>
24
+ <br>
25
+ <a href="https://anaconda.org/conda-forge/datajoint">
26
+ <img src="https://img.shields.io/conda/dn/conda-forge/datajoint?color=brightgreen" alt="conda-forge downloads" />
27
+ </a>
28
+ </td>
29
+ </tr>
30
+ <tr>
31
+ <td>Since Release</td>
32
+ <td>
33
+ <a id="commit-since-release-link" href="https://github.com/datajoint/datajoint-python/compare/v0.14.5...master">
34
+ <img id="commit-since-release-img" src="https://img.shields.io/github/commits-since/datajoint/datajoint-python/v0.14.5?color=red" alt="commit since last release" />
35
+ </a>
36
+ </td>
37
+ </tr>
38
+ <tr>
39
+ <td>Test Status</td>
40
+ <td>
41
+ <a href="https://github.com/datajoint/datajoint-python/actions/workflows/test.yaml">
42
+ <img src="https://github.com/datajoint/datajoint-python/actions/workflows/test.yaml/badge.svg" alt="test status" />
43
+ </a>
44
+ </td>
45
+ </tr>
46
+ <tr>
47
+ <td>Release Status</td>
48
+ <td>
49
+ <a href="https://github.com/datajoint/datajoint-python/actions/workflows/post_draft_release_published.yaml">
50
+ <img src="https://github.com/datajoint/datajoint-python/actions/workflows/post_draft_release_published.yaml/badge.svg" alt="release status" />
51
+ </a>
52
+ </td>
53
+ </tr>
54
+ <tr>
55
+ <td>Doc Status</td>
56
+ <td>
57
+ <a href="https://docs.datajoint.com">
58
+ <img src="https://github.com/datajoint/datajoint-python/actions/workflows/pages/pages-build-deployment/badge.svg" alt="doc status" />
59
+ </a>
60
+ </td>
61
+ </tr>
62
+ <tr>
63
+ <td>Coverage</td>
64
+ <td>
65
+ <a href="https://coveralls.io/github/datajoint/datajoint-python?branch=master">
66
+ <img src="https://coveralls.io/repos/datajoint/datajoint-python/badge.svg?branch=master&service=github"/ alt="coverage">
67
+ </a>
68
+ </td>
69
+ </tr>
70
+ <tr>
71
+ <td>Developer Chat</td>
72
+ <td>
73
+ <a href="https://datajoint.slack.com/">
74
+ <img src="https://img.shields.io/badge/slack-datajoint-purple.svg" alt="datajoint slack"/>
75
+ </a>
76
+ </td>
77
+ </tr>
78
+ <tr>
79
+ <td>License</td>
80
+ <td>
81
+ <a href="https://github.com/datajoint/datajoint-python/blob/master/LICENSE.txt">
82
+ <img src="https://img.shields.io/github/license/datajoint/datajoint-python" alt="LGPL-2.1" />
83
+ </a>
84
+ </td>
85
+ </tr>
86
+ <tr>
87
+ <td>Citation</td>
88
+ <td>
89
+ <a href="https://doi.org/10.1101/031658">
90
+ <img src="https://img.shields.io/badge/DOI-10.1101/bioRxiv.031658-B31B1B.svg" alt="bioRxiv">
91
+ </a>
92
+ <br>
93
+ <a href="https://doi.org/10.5281/zenodo.6829062">
94
+ <img src="https://zenodo.org/badge/DOI/10.5281/zenodo.6829062.svg" alt="zenodo">
95
+ </a>
96
+ </td>
97
+ </tr>
98
+
99
+ </table>
100
+
101
+ DataJoint for Python is a framework for scientific workflow management based on
102
+ relational principles. DataJoint is built on the foundation of the relational data
103
+ model and prescribes a consistent method for organizing, populating, computing, and
104
+ querying data.
105
+
106
+ DataJoint was initially developed in 2009 by Dimitri Yatsenko in Andreas Tolias' Lab at
107
+ Baylor College of Medicine for the distributed processing and management of large
108
+ volumes of data streaming from regular experiments. Starting in 2011, DataJoint has
109
+ been available as an open-source project adopted by other labs and improved through
110
+ contributions from several developers.
111
+ Presently, the primary developer of DataJoint open-source software is the company
112
+ DataJoint (<https://datajoint.com>).
113
+
114
+ ## Data Pipeline Example
115
+
116
+ ![pipeline](https://raw.githubusercontent.com/datajoint/datajoint-python/master/images/pipeline.png)
117
+
118
+ [Yatsenko et al., bioRxiv 2021](https://doi.org/10.1101/2021.03.30.437358)
119
+
120
+ ## Getting Started
121
+
122
+ - Install with Conda
123
+
124
+ ```bash
125
+ conda install -c conda-forge datajoint
126
+ ```
127
+
128
+ - Install with pip
129
+
130
+ ```bash
131
+ pip install datajoint
132
+ ```
133
+
134
+ - [Documentation & Tutorials](https://docs.datajoint.com/core/datajoint-python/)
135
+
136
+ - [Interactive Tutorials](https://github.com/datajoint/datajoint-tutorials) on GitHub Codespaces
137
+
138
+ - [DataJoint Elements](https://docs.datajoint.com/elements/) - Catalog of example pipelines for neuroscience experiments
139
+
140
+ - Contribute
141
+ - [Contribution Guidelines](https://docs.datajoint.com/about/contribute/)
142
+
143
+ - [Developer Guide](https://docs.datajoint.com/core/datajoint-python/latest/develop/)
@@ -55,24 +55,23 @@ __all__ = [
55
55
  "cli",
56
56
  ]
57
57
 
58
- from .logging import logger
59
- from .version import __version__
60
- from .settings import config
61
- from .connection import conn, Connection
62
- from .schemas import Schema
63
- from .schemas import VirtualModule, list_schemas
64
- from .table import Table, FreeTable
65
- from .user_tables import Manual, Lookup, Imported, Computed, Part
66
- from .expression import Not, AndList, U, Top
67
- from .diagram import Diagram
68
- from .admin import set_password, kill
58
+ from . import errors
59
+ from .admin import kill, set_password
60
+ from .attribute_adapter import AttributeAdapter
69
61
  from .blob import MatCell, MatStruct
62
+ from .cli import cli
63
+ from .connection import Connection, conn
64
+ from .diagram import Diagram
65
+ from .errors import DataJointError
66
+ from .expression import AndList, Not, Top, U
70
67
  from .fetch import key
71
68
  from .hash import key_hash
72
- from .attribute_adapter import AttributeAdapter
73
- from . import errors
74
- from .errors import DataJointError
75
- from .cli import cli
69
+ from .logging import logger
70
+ from .schemas import Schema, VirtualModule, list_schemas
71
+ from .settings import config
72
+ from .table import FreeTable, Table
73
+ from .user_tables import Computed, Imported, Lookup, Manual, Part
74
+ from .version import __version__
76
75
 
77
76
  ERD = Di = Diagram # Aliases for Diagram
78
77
  schema = Schema # Aliases for Schema
@@ -1,10 +1,12 @@
1
- import pymysql
1
+ import logging
2
2
  from getpass import getpass
3
+
4
+ import pymysql
3
5
  from packaging import version
6
+
4
7
  from .connection import conn
5
8
  from .settings import config
6
9
  from .utils import user_choice
7
- import logging
8
10
 
9
11
  logger = logging.getLogger(__name__.split(".")[0])
10
12
 
@@ -1,4 +1,5 @@
1
1
  import re
2
+
2
3
  from .errors import DataJointError, _support_adapted_types
3
4
  from .plugin import type_plugins
4
5
 
@@ -1,17 +1,20 @@
1
1
  """This module defines class dj.AutoPopulate"""
2
2
 
3
- import logging
3
+ import contextlib
4
4
  import datetime
5
- import traceback
6
- import random
7
5
  import inspect
6
+ import logging
7
+ import multiprocessing as mp
8
+ import random
9
+ import signal
10
+ import traceback
11
+
12
+ import deepdiff
8
13
  from tqdm import tqdm
9
- from .hash import key_hash
10
- from .expression import QueryExpression, AndList
14
+
11
15
  from .errors import DataJointError, LostConnectionError
12
- import signal
13
- import multiprocessing as mp
14
- import contextlib
16
+ from .expression import AndList, QueryExpression
17
+ from .hash import key_hash
15
18
 
16
19
  # noinspection PyExceptionInherit,PyCallingNonCallable
17
20
 
@@ -92,13 +95,76 @@ class AutoPopulate:
92
95
 
93
96
  def make(self, key):
94
97
  """
95
- Derived classes must implement method `make` that fetches data from tables
96
- above them in the dependency hierarchy, restricting by the given key,
97
- computes secondary attributes, and inserts the new tuples into self.
98
+ This method must be implemented by derived classes to perform automated computation.
99
+ The method must implement the following three steps:
100
+
101
+ 1. Fetch data from tables above in the dependency hierarchy, restricted by the given key.
102
+ 2. Compute secondary attributes based on the fetched data.
103
+ 3. Insert the new tuple(s) into the current table.
104
+
105
+ The method can be implemented either as:
106
+ (a) Regular method: All three steps are performed in a single database transaction.
107
+ The method must return None.
108
+ (b) Generator method:
109
+ The make method is split into three functions:
110
+ - `make_fetch`: Fetches data from the parent tables.
111
+ - `make_compute`: Computes secondary attributes based on the fetched data.
112
+ - `make_insert`: Inserts the computed data into the current table.
113
+
114
+ Then populate logic is executes as follows:
115
+
116
+ <pseudocode>
117
+ fetched_data1 = self.make_fetch(key)
118
+ computed_result = self.make_compute(key, *fetched_data1)
119
+ begin transaction:
120
+ fetched_data2 = self.make_fetch(key)
121
+ if fetched_data1 != fetched_data2:
122
+ cancel transaction
123
+ else:
124
+ self.make_insert(key, *computed_result)
125
+ commit_transaction
126
+ <pseudocode>
127
+
128
+ Importantly, the output of make_fetch is a tuple that serves as the input into `make_compute`.
129
+ The output of `make_compute` is a tuple that serves as the input into `make_insert`.
130
+
131
+ The functionality must be strictly divided between these three methods:
132
+ - All database queries must be completed in `make_fetch`.
133
+ - All computation must be completed in `make_compute`.
134
+ - All database inserts must be completed in `make_insert`.
135
+
136
+ DataJoint may programmatically enforce this separation in the future.
137
+
138
+ :param key: The primary key value used to restrict the data fetching.
139
+ :raises NotImplementedError: If the derived class does not implement the required methods.
98
140
  """
99
- raise NotImplementedError(
100
- "Subclasses of AutoPopulate must implement the method `make`"
101
- )
141
+
142
+ if not (
143
+ hasattr(self, "make_fetch")
144
+ and hasattr(self, "make_insert")
145
+ and hasattr(self, "make_compute")
146
+ ):
147
+ # user must implement `make`
148
+ raise NotImplementedError(
149
+ "Subclasses of AutoPopulate must implement the method `make` "
150
+ "or (`make_fetch` + `make_compute` + `make_insert`)"
151
+ )
152
+
153
+ # User has implemented `_fetch`, `_compute`, and `_insert` methods instead
154
+
155
+ # Step 1: Fetch data from parent tables
156
+ fetched_data = self.make_fetch(key) # fetched_data is a tuple
157
+ computed_result = yield fetched_data # passed as input into make_compute
158
+
159
+ # Step 2: If computed result is not passed in, compute the result
160
+ if computed_result is None:
161
+ # this is only executed in the first invocation
162
+ computed_result = self.make_compute(key, *fetched_data)
163
+ yield computed_result # this is passed to the second invocation of make
164
+
165
+ # Step 3: Insert the computed result into the current table.
166
+ self.make_insert(key, *computed_result)
167
+ yield
102
168
 
103
169
  @property
104
170
  def target(self):
@@ -200,9 +266,8 @@ class AutoPopulate:
200
266
  self.connection.schemas[self.target.database].jobs if reserve_jobs else None
201
267
  )
202
268
 
203
- # define and set up signal handler for SIGTERM:
204
269
  if reserve_jobs:
205
-
270
+ # Define a signal handler for SIGTERM
206
271
  def handler(signum, frame):
207
272
  logger.info("Populate terminated by SIGTERM")
208
273
  raise SystemExit("SIGTERM received")
@@ -262,13 +327,16 @@ class AutoPopulate:
262
327
  # spawn multiple processes
263
328
  self.connection.close() # disconnect parent process from MySQL server
264
329
  del self.connection._conn.ctx # SSLContext is not pickleable
265
- with mp.Pool(
266
- processes, _initialize_populate, (self, jobs, populate_kwargs)
267
- ) as pool, (
268
- tqdm(desc="Processes: ", total=nkeys)
269
- if display_progress
270
- else contextlib.nullcontext()
271
- ) as progress_bar:
330
+ with (
331
+ mp.Pool(
332
+ processes, _initialize_populate, (self, jobs, populate_kwargs)
333
+ ) as pool,
334
+ (
335
+ tqdm(desc="Processes: ", total=nkeys)
336
+ if display_progress
337
+ else contextlib.nullcontext()
338
+ ) as progress_bar,
339
+ ):
272
340
  for status in pool.imap(_call_populate1, keys, chunksize=1):
273
341
  if status is True:
274
342
  success_list.append(1)
@@ -309,17 +377,47 @@ class AutoPopulate:
309
377
  ):
310
378
  return False
311
379
 
312
- self.connection.start_transaction()
380
+ # if make is a generator, it transaction can be delayed until the final stage
381
+ is_generator = inspect.isgeneratorfunction(make)
382
+ if not is_generator:
383
+ self.connection.start_transaction()
384
+
313
385
  if key in self.target: # already populated
314
- self.connection.cancel_transaction()
386
+ if not is_generator:
387
+ self.connection.cancel_transaction()
315
388
  if jobs is not None:
316
389
  jobs.complete(self.target.table_name, self._job_key(key))
317
390
  return False
318
391
 
319
392
  logger.debug(f"Making {key} -> {self.target.full_table_name}")
320
393
  self.__class__._allow_insert = True
394
+
321
395
  try:
322
- make(dict(key), **(make_kwargs or {}))
396
+ if not is_generator:
397
+ make(dict(key), **(make_kwargs or {}))
398
+ else:
399
+ # tripartite make - transaction is delayed until the final stage
400
+ gen = make(dict(key), **(make_kwargs or {}))
401
+ fetched_data = next(gen)
402
+ fetch_hash = deepdiff.DeepHash(
403
+ fetched_data, ignore_iterable_order=False
404
+ )[fetched_data]
405
+ computed_result = next(gen) # perform the computation
406
+ # fetch and insert inside a transaction
407
+ self.connection.start_transaction()
408
+ gen = make(dict(key), **(make_kwargs or {})) # restart make
409
+ fetched_data = next(gen)
410
+ if (
411
+ fetch_hash
412
+ != deepdiff.DeepHash(fetched_data, ignore_iterable_order=False)[
413
+ fetched_data
414
+ ]
415
+ ): # raise error if fetched data has changed
416
+ raise DataJointError(
417
+ "Referential integrity failed! The `make_fetch` data has changed"
418
+ )
419
+ gen.send(computed_result) # insert
420
+
323
421
  except (KeyboardInterrupt, SystemExit, Exception) as error:
324
422
  try:
325
423
  self.connection.cancel_transaction()
@@ -3,17 +3,18 @@
3
3
  compatibility with Matlab-based serialization implemented by mYm.
4
4
  """
5
5
 
6
- import zlib
7
- from itertools import repeat
8
6
  import collections
9
- from decimal import Decimal
10
7
  import datetime
11
8
  import uuid
9
+ import zlib
10
+ from decimal import Decimal
11
+ from itertools import repeat
12
+
12
13
  import numpy as np
14
+
13
15
  from .errors import DataJointError
14
16
  from .settings import config
15
17
 
16
-
17
18
  deserialize_lookup = {
18
19
  0: {"dtype": None, "scalar_type": "UNKNOWN"},
19
20
  1: {"dtype": None, "scalar_type": "CELL"},
@@ -139,7 +140,7 @@ class Blob:
139
140
  "S": self.read_struct, # matlab struct array
140
141
  "C": self.read_cell_array, # matlab cell array
141
142
  # basic data types
142
- "\xFF": self.read_none, # None
143
+ "\xff": self.read_none, # None
143
144
  "\x01": self.read_tuple, # a Sequence (e.g. tuple)
144
145
  "\x02": self.read_list, # a MutableSequence (e.g. list)
145
146
  "\x03": self.read_set, # a Set
@@ -204,7 +205,7 @@ class Blob:
204
205
  return self.pack_dict(obj)
205
206
  if isinstance(obj, str):
206
207
  return self.pack_string(obj)
207
- if isinstance(obj, collections.abc.ByteString):
208
+ if isinstance(obj, (bytes, bytearray)):
208
209
  return self.pack_bytes(obj)
209
210
  if isinstance(obj, collections.abc.MutableSequence):
210
211
  return self.pack_list(obj)
@@ -400,7 +401,7 @@ class Blob:
400
401
 
401
402
  @staticmethod
402
403
  def pack_none():
403
- return b"\xFF"
404
+ return b"\xff"
404
405
 
405
406
  def read_tuple(self):
406
407
  return tuple(
@@ -1,6 +1,7 @@
1
1
  import argparse
2
2
  from code import interact
3
3
  from collections import ChainMap
4
+
4
5
  import datajoint as dj
5
6
 
6
7