simple-module-images 0.0.14__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.
Files changed (649) hide show
  1. simple_module_images-0.0.14/.gitignore +57 -0
  2. simple_module_images-0.0.14/NOTICE +61 -0
  3. simple_module_images-0.0.14/PKG-INFO +202 -0
  4. simple_module_images-0.0.14/README.md +160 -0
  5. simple_module_images-0.0.14/docs/access.md +196 -0
  6. simple_module_images-0.0.14/docs/code-layout.md +61 -0
  7. simple_module_images-0.0.14/docs/imports.md +224 -0
  8. simple_module_images-0.0.14/docs/index.md +227 -0
  9. simple_module_images-0.0.14/docs/migrating-from-portal.md +139 -0
  10. simple_module_images-0.0.14/docs/pipeline.md +406 -0
  11. simple_module_images-0.0.14/docs/worker.md +251 -0
  12. simple_module_images-0.0.14/docs/writing-a-plugin.md +268 -0
  13. simple_module_images-0.0.14/package.json +31 -0
  14. simple_module_images-0.0.14/pyproject.toml +120 -0
  15. simple_module_images-0.0.14/sm_images/__init__.py +7 -0
  16. simple_module_images-0.0.14/sm_images/contracts/__init__.py +78 -0
  17. simple_module_images-0.0.14/sm_images/contracts/events.py +86 -0
  18. simple_module_images-0.0.14/sm_images/contracts/reads.py +145 -0
  19. simple_module_images-0.0.14/sm_images/contracts/schemas.py +93 -0
  20. simple_module_images-0.0.14/sm_images/core/__init__.py +5 -0
  21. simple_module_images-0.0.14/sm_images/core/access/__init__.py +275 -0
  22. simple_module_images-0.0.14/sm_images/core/access/redaction.py +173 -0
  23. simple_module_images-0.0.14/sm_images/core/access/resource_types.py +66 -0
  24. simple_module_images-0.0.14/sm_images/core/access/starter_right.py +81 -0
  25. simple_module_images-0.0.14/sm_images/core/access/write.py +91 -0
  26. simple_module_images-0.0.14/sm_images/core/billing/__init__.py +203 -0
  27. simple_module_images-0.0.14/sm_images/core/billing/install.py +206 -0
  28. simple_module_images-0.0.14/sm_images/core/billing/metering_keys.py +27 -0
  29. simple_module_images-0.0.14/sm_images/core/billing/ops.py +275 -0
  30. simple_module_images-0.0.14/sm_images/core/billing/repair.py +224 -0
  31. simple_module_images-0.0.14/sm_images/core/billing/repair_cursor.py +100 -0
  32. simple_module_images-0.0.14/sm_images/core/billing/settle.py +211 -0
  33. simple_module_images-0.0.14/sm_images/core/billing/subject.py +156 -0
  34. simple_module_images-0.0.14/sm_images/core/clock/__init__.py +17 -0
  35. simple_module_images-0.0.14/sm_images/core/clock/db.py +43 -0
  36. simple_module_images-0.0.14/sm_images/core/constants.py +277 -0
  37. simple_module_images-0.0.14/sm_images/core/errors.py +199 -0
  38. simple_module_images-0.0.14/sm_images/core/events.py +82 -0
  39. simple_module_images-0.0.14/sm_images/core/settings/__init__.py +141 -0
  40. simple_module_images-0.0.14/sm_images/core/settings/boot.py +49 -0
  41. simple_module_images-0.0.14/sm_images/core/storage/__init__.py +145 -0
  42. simple_module_images-0.0.14/sm_images/core/storage/intents.py +73 -0
  43. simple_module_images-0.0.14/sm_images/core/storage/keys.py +71 -0
  44. simple_module_images-0.0.14/sm_images/core/tenancy/__init__.py +263 -0
  45. simple_module_images-0.0.14/sm_images/core/tenancy/_guard.py +100 -0
  46. simple_module_images-0.0.14/sm_images/core/tenancy/_mode.py +273 -0
  47. simple_module_images-0.0.14/sm_images/core/tenancy/request_context.py +50 -0
  48. simple_module_images-0.0.14/sm_images/index.ts +11 -0
  49. simple_module_images-0.0.14/sm_images/ingest/__init__.py +23 -0
  50. simple_module_images-0.0.14/sm_images/ingest/_holds_host.py +30 -0
  51. simple_module_images-0.0.14/sm_images/ingest/admission.py +148 -0
  52. simple_module_images-0.0.14/sm_images/ingest/b64.py +40 -0
  53. simple_module_images-0.0.14/sm_images/ingest/dedupe.py +122 -0
  54. simple_module_images-0.0.14/sm_images/ingest/direct.py +247 -0
  55. simple_module_images-0.0.14/sm_images/ingest/guards.py +106 -0
  56. simple_module_images-0.0.14/sm_images/ingest/imports/__init__.py +1 -0
  57. simple_module_images-0.0.14/sm_images/ingest/imports/access.py +106 -0
  58. simple_module_images-0.0.14/sm_images/ingest/imports/beat.py +85 -0
  59. simple_module_images-0.0.14/sm_images/ingest/imports/chunk.py +216 -0
  60. simple_module_images-0.0.14/sm_images/ingest/imports/claims.py +71 -0
  61. simple_module_images-0.0.14/sm_images/ingest/imports/cleanup.py +132 -0
  62. simple_module_images-0.0.14/sm_images/ingest/imports/controls.py +194 -0
  63. simple_module_images-0.0.14/sm_images/ingest/imports/dns.py +115 -0
  64. simple_module_images-0.0.14/sm_images/ingest/imports/download.py +195 -0
  65. simple_module_images-0.0.14/sm_images/ingest/imports/errors.py +27 -0
  66. simple_module_images-0.0.14/sm_images/ingest/imports/features.py +212 -0
  67. simple_module_images-0.0.14/sm_images/ingest/imports/fetch.py +252 -0
  68. simple_module_images-0.0.14/sm_images/ingest/imports/filename_pattern.py +138 -0
  69. simple_module_images-0.0.14/sm_images/ingest/imports/geojson_stream.py +173 -0
  70. simple_module_images-0.0.14/sm_images/ingest/imports/item_claim.py +140 -0
  71. simple_module_images-0.0.14/sm_images/ingest/imports/item_errors.py +93 -0
  72. simple_module_images-0.0.14/sm_images/ingest/imports/jobs.py +244 -0
  73. simple_module_images-0.0.14/sm_images/ingest/imports/launch.py +80 -0
  74. simple_module_images-0.0.14/sm_images/ingest/imports/log_redact.py +70 -0
  75. simple_module_images-0.0.14/sm_images/ingest/imports/lookup.py +63 -0
  76. simple_module_images-0.0.14/sm_images/ingest/imports/manage_right.py +82 -0
  77. simple_module_images-0.0.14/sm_images/ingest/imports/mapping.py +73 -0
  78. simple_module_images-0.0.14/sm_images/ingest/imports/netsafe.py +100 -0
  79. simple_module_images-0.0.14/sm_images/ingest/imports/rate_limit.py +144 -0
  80. simple_module_images-0.0.14/sm_images/ingest/imports/recover.py +261 -0
  81. simple_module_images-0.0.14/sm_images/ingest/imports/reset.py +159 -0
  82. simple_module_images-0.0.14/sm_images/ingest/imports/retrying.py +188 -0
  83. simple_module_images-0.0.14/sm_images/ingest/imports/runner.py +229 -0
  84. simple_module_images-0.0.14/sm_images/ingest/imports/service.py +132 -0
  85. simple_module_images-0.0.14/sm_images/ingest/imports/settle.py +279 -0
  86. simple_module_images-0.0.14/sm_images/ingest/imports/stage.py +82 -0
  87. simple_module_images-0.0.14/sm_images/ingest/imports/staging.py +158 -0
  88. simple_module_images-0.0.14/sm_images/ingest/imports/tasks.py +60 -0
  89. simple_module_images-0.0.14/sm_images/ingest/imports/terminal.py +178 -0
  90. simple_module_images-0.0.14/sm_images/ingest/imports/url_safety.py +181 -0
  91. simple_module_images-0.0.14/sm_images/ingest/imports/values.py +165 -0
  92. simple_module_images-0.0.14/sm_images/ingest/imports/zip_abort.py +47 -0
  93. simple_module_images-0.0.14/sm_images/ingest/imports/zip_entries.py +126 -0
  94. simple_module_images-0.0.14/sm_images/ingest/imports/zip_eocd.py +83 -0
  95. simple_module_images-0.0.14/sm_images/ingest/imports/zip_import.py +241 -0
  96. simple_module_images-0.0.14/sm_images/ingest/imports/zip_metadata.py +70 -0
  97. simple_module_images-0.0.14/sm_images/ingest/imports/zip_safety.py +252 -0
  98. simple_module_images-0.0.14/sm_images/ingest/imports/zip_source.py +127 -0
  99. simple_module_images-0.0.14/sm_images/ingest/imports/zip_upload.py +260 -0
  100. simple_module_images-0.0.14/sm_images/ingest/meta.py +137 -0
  101. simple_module_images-0.0.14/sm_images/ingest/multipart.py +165 -0
  102. simple_module_images-0.0.14/sm_images/ingest/service.py +238 -0
  103. simple_module_images-0.0.14/sm_images/ingest/service_holds.py +67 -0
  104. simple_module_images-0.0.14/sm_images/ingest/slots.py +194 -0
  105. simple_module_images-0.0.14/sm_images/ingest/sniff.py +50 -0
  106. simple_module_images-0.0.14/sm_images/ingest/ticket.py +92 -0
  107. simple_module_images-0.0.14/sm_images/ingest/upload_reaper.py +111 -0
  108. simple_module_images-0.0.14/sm_images/ingest/upload_session.py +220 -0
  109. simple_module_images-0.0.14/sm_images/jobs/__init__.py +1 -0
  110. simple_module_images-0.0.14/sm_images/jobs/janitor.py +256 -0
  111. simple_module_images-0.0.14/sm_images/jobs/phases.py +52 -0
  112. simple_module_images-0.0.14/sm_images/jobs/placeholders.py +78 -0
  113. simple_module_images-0.0.14/sm_images/jobs/purge.py +222 -0
  114. simple_module_images-0.0.14/sm_images/jobs/purge_delete.py +121 -0
  115. simple_module_images-0.0.14/sm_images/jobs/purge_select.py +241 -0
  116. simple_module_images-0.0.14/sm_images/jobs/reconcile.py +204 -0
  117. simple_module_images-0.0.14/sm_images/jobs/reconcile_dispatch.py +121 -0
  118. simple_module_images-0.0.14/sm_images/jobs/regroup/__init__.py +1 -0
  119. simple_module_images-0.0.14/sm_images/jobs/regroup/control.py +103 -0
  120. simple_module_images-0.0.14/sm_images/jobs/regroup/jobs.py +257 -0
  121. simple_module_images-0.0.14/sm_images/jobs/regroup/runner.py +103 -0
  122. simple_module_images-0.0.14/sm_images/locales/de.json +682 -0
  123. simple_module_images-0.0.14/sm_images/locales/en.json +682 -0
  124. simple_module_images-0.0.14/sm_images/map/__init__.py +15 -0
  125. simple_module_images-0.0.14/sm_images/map/build.py +223 -0
  126. simple_module_images-0.0.14/sm_images/map/objects.py +33 -0
  127. simple_module_images-0.0.14/sm_images/map/pmtiles_build.py +147 -0
  128. simple_module_images-0.0.14/sm_images/map/points.py +136 -0
  129. simple_module_images-0.0.14/sm_images/map/recover.py +56 -0
  130. simple_module_images-0.0.14/sm_images/map/revoke.py +121 -0
  131. simple_module_images-0.0.14/sm_images/map/schedule.py +208 -0
  132. simple_module_images-0.0.14/sm_images/map/style.py +71 -0
  133. simple_module_images-0.0.14/sm_images/map/tasks.py +35 -0
  134. simple_module_images-0.0.14/sm_images/models/__init__.py +66 -0
  135. simple_module_images-0.0.14/sm_images/models/_base.py +14 -0
  136. simple_module_images-0.0.14/sm_images/models/_cols.py +56 -0
  137. simple_module_images-0.0.14/sm_images/models/billing_op.py +84 -0
  138. simple_module_images-0.0.14/sm_images/models/collection.py +82 -0
  139. simple_module_images-0.0.14/sm_images/models/enums.py +88 -0
  140. simple_module_images-0.0.14/sm_images/models/group.py +25 -0
  141. simple_module_images-0.0.14/sm_images/models/image.py +120 -0
  142. simple_module_images-0.0.14/sm_images/models/import_item.py +51 -0
  143. simple_module_images-0.0.14/sm_images/models/import_job.py +71 -0
  144. simple_module_images-0.0.14/sm_images/models/object_intent.py +35 -0
  145. simple_module_images-0.0.14/sm_images/models/pipeline_restart.py +37 -0
  146. simple_module_images-0.0.14/sm_images/models/prompt.py +93 -0
  147. simple_module_images-0.0.14/sm_images/models/regroup_job.py +94 -0
  148. simple_module_images-0.0.14/sm_images/models/rendition.py +30 -0
  149. simple_module_images-0.0.14/sm_images/models/step_run.py +50 -0
  150. simple_module_images-0.0.14/sm_images/models/upload_admission.py +33 -0
  151. simple_module_images-0.0.14/sm_images/models/upload_session.py +59 -0
  152. simple_module_images-0.0.14/sm_images/module.py +245 -0
  153. simple_module_images-0.0.14/sm_images/pagebuilder-blocks.ts +43 -0
  154. simple_module_images-0.0.14/sm_images/pages/Collection.tsx +254 -0
  155. simple_module_images-0.0.14/sm_images/pages/Collections.tsx +75 -0
  156. simple_module_images-0.0.14/sm_images/pages/Image.tsx +111 -0
  157. simple_module_images-0.0.14/sm_images/pages/PublicCollection.tsx +72 -0
  158. simple_module_images-0.0.14/sm_images/pages/Review.tsx +190 -0
  159. simple_module_images-0.0.14/sm_images/pipeline/__init__.py +91 -0
  160. simple_module_images-0.0.14/sm_images/pipeline/advance.py +196 -0
  161. simple_module_images-0.0.14/sm_images/pipeline/ai/__init__.py +21 -0
  162. simple_module_images-0.0.14/sm_images/pipeline/ai/codes.py +46 -0
  163. simple_module_images-0.0.14/sm_images/pipeline/ai/cross_check.py +138 -0
  164. simple_module_images-0.0.14/sm_images/pipeline/ai/group_inputs.py +103 -0
  165. simple_module_images-0.0.14/sm_images/pipeline/ai/group_lease.py +189 -0
  166. simple_module_images-0.0.14/sm_images/pipeline/ai/group_load.py +179 -0
  167. simple_module_images-0.0.14/sm_images/pipeline/ai/group_members.py +159 -0
  168. simple_module_images-0.0.14/sm_images/pipeline/ai/group_request.py +145 -0
  169. simple_module_images-0.0.14/sm_images/pipeline/ai/group_run.py +221 -0
  170. simple_module_images-0.0.14/sm_images/pipeline/ai/group_store.py +78 -0
  171. simple_module_images-0.0.14/sm_images/pipeline/ai/prompt_steps.py +171 -0
  172. simple_module_images-0.0.14/sm_images/pipeline/ai/reads.py +51 -0
  173. simple_module_images-0.0.14/sm_images/pipeline/ai/results.py +193 -0
  174. simple_module_images-0.0.14/sm_images/pipeline/ai/review.py +150 -0
  175. simple_module_images-0.0.14/sm_images/pipeline/ai/run.py +191 -0
  176. simple_module_images-0.0.14/sm_images/pipeline/ai/runner.py +158 -0
  177. simple_module_images-0.0.14/sm_images/pipeline/ai/schema_model.py +172 -0
  178. simple_module_images-0.0.14/sm_images/pipeline/ai/schema_safety.py +221 -0
  179. simple_module_images-0.0.14/sm_images/pipeline/builtin_steps.py +103 -0
  180. simple_module_images-0.0.14/sm_images/pipeline/claim.py +250 -0
  181. simple_module_images-0.0.14/sm_images/pipeline/config.py +214 -0
  182. simple_module_images-0.0.14/sm_images/pipeline/control.py +163 -0
  183. simple_module_images-0.0.14/sm_images/pipeline/cycle.py +113 -0
  184. simple_module_images-0.0.14/sm_images/pipeline/eager_drain.py +70 -0
  185. simple_module_images-0.0.14/sm_images/pipeline/executor.py +218 -0
  186. simple_module_images-0.0.14/sm_images/pipeline/extensions.py +122 -0
  187. simple_module_images-0.0.14/sm_images/pipeline/finish.py +243 -0
  188. simple_module_images-0.0.14/sm_images/pipeline/keeper.py +17 -0
  189. simple_module_images-0.0.14/sm_images/pipeline/load.py +135 -0
  190. simple_module_images-0.0.14/sm_images/pipeline/orchestrate.py +203 -0
  191. simple_module_images-0.0.14/sm_images/pipeline/plan.py +237 -0
  192. simple_module_images-0.0.14/sm_images/pipeline/presets.py +102 -0
  193. simple_module_images-0.0.14/sm_images/pipeline/processing/__init__.py +1 -0
  194. simple_module_images-0.0.14/sm_images/pipeline/processing/exif.py +147 -0
  195. simple_module_images-0.0.14/sm_images/pipeline/processing/heif.py +28 -0
  196. simple_module_images-0.0.14/sm_images/pipeline/processing/renditions.py +58 -0
  197. simple_module_images-0.0.14/sm_images/pipeline/publish.py +222 -0
  198. simple_module_images-0.0.14/sm_images/pipeline/registry.py +247 -0
  199. simple_module_images-0.0.14/sm_images/pipeline/reopen.py +84 -0
  200. simple_module_images-0.0.14/sm_images/pipeline/restart.py +165 -0
  201. simple_module_images-0.0.14/sm_images/pipeline/runtime.py +129 -0
  202. simple_module_images-0.0.14/sm_images/pipeline/step.py +152 -0
  203. simple_module_images-0.0.14/sm_images/pipeline/steps/__init__.py +1 -0
  204. simple_module_images-0.0.14/sm_images/pipeline/steps/anonymize/__init__.py +19 -0
  205. simple_module_images-0.0.14/sm_images/pipeline/steps/anonymize/blur.py +72 -0
  206. simple_module_images-0.0.14/sm_images/pipeline/steps/anonymize/detectors.py +138 -0
  207. simple_module_images-0.0.14/sm_images/pipeline/steps/anonymize/models.py +229 -0
  208. simple_module_images-0.0.14/sm_images/pipeline/steps/anonymize/step.py +200 -0
  209. simple_module_images-0.0.14/sm_images/pipeline/steps/anonymize/weights.py +191 -0
  210. simple_module_images-0.0.14/sm_images/pipeline/steps/classify.py +111 -0
  211. simple_module_images-0.0.14/sm_images/pipeline/steps/quality.py +115 -0
  212. simple_module_images-0.0.14/sm_images/pipeline/storage_hold.py +229 -0
  213. simple_module_images-0.0.14/sm_images/pipeline/worker_runtime.py +196 -0
  214. simple_module_images-0.0.14/sm_images/task_config.py +65 -0
  215. simple_module_images-0.0.14/sm_images/tasks.py +179 -0
  216. simple_module_images-0.0.14/sm_images/ui/components/ChipGroup.tsx +39 -0
  217. simple_module_images-0.0.14/sm_images/ui/components/ConfirmDialog.tsx +90 -0
  218. simple_module_images-0.0.14/sm_images/ui/components/ImagesLayout.tsx +9 -0
  219. simple_module_images-0.0.14/sm_images/ui/components/block/ImageGalleryBlock.test.tsx +191 -0
  220. simple_module_images-0.0.14/sm_images/ui/components/block/ImageGalleryBlock.tsx +118 -0
  221. simple_module_images-0.0.14/sm_images/ui/components/block/ImageStatsBlock.test.tsx +210 -0
  222. simple_module_images-0.0.14/sm_images/ui/components/block/ImageStatsBlock.tsx +106 -0
  223. simple_module_images-0.0.14/sm_images/ui/components/block/ImageStatsRender.tsx +118 -0
  224. simple_module_images-0.0.14/sm_images/ui/components/collections/CollectionCard.tsx +32 -0
  225. simple_module_images-0.0.14/sm_images/ui/components/collections/CreateCollectionDialog.tsx +126 -0
  226. simple_module_images-0.0.14/sm_images/ui/components/collections/PublicLink.tsx +42 -0
  227. simple_module_images-0.0.14/sm_images/ui/components/collections/VisibilitySelect.tsx +42 -0
  228. simple_module_images-0.0.14/sm_images/ui/components/gallery/Gallery.tsx +105 -0
  229. simple_module_images-0.0.14/sm_images/ui/components/gallery/GalleryTile.tsx +62 -0
  230. simple_module_images-0.0.14/sm_images/ui/components/gallery/UploadButton.tsx +81 -0
  231. simple_module_images-0.0.14/sm_images/ui/components/groups/GroupCard.tsx +95 -0
  232. simple_module_images-0.0.14/sm_images/ui/components/groups/GroupForm.tsx +81 -0
  233. simple_module_images-0.0.14/sm_images/ui/components/groups/GroupsTab.tsx +116 -0
  234. simple_module_images-0.0.14/sm_images/ui/components/groups/MemberThumb.tsx +36 -0
  235. simple_module_images-0.0.14/sm_images/ui/components/groups/RegroupPanel.tsx +159 -0
  236. simple_module_images-0.0.14/sm_images/ui/components/imports/ImportFailures.tsx +54 -0
  237. simple_module_images-0.0.14/sm_images/ui/components/imports/ImportWizard.tsx +261 -0
  238. simple_module_images-0.0.14/sm_images/ui/components/imports/ImportsTab.tsx +70 -0
  239. simple_module_images-0.0.14/sm_images/ui/components/imports/JobRow.tsx +157 -0
  240. simple_module_images-0.0.14/sm_images/ui/components/imports/JobRowFailures.test.tsx +66 -0
  241. simple_module_images-0.0.14/sm_images/ui/components/imports/MappingFields.tsx +98 -0
  242. simple_module_images-0.0.14/sm_images/ui/components/imports/PreviewSummary.tsx +68 -0
  243. simple_module_images-0.0.14/sm_images/ui/components/map/CollectionMap.test.tsx +115 -0
  244. simple_module_images-0.0.14/sm_images/ui/components/map/CollectionMap.tsx +98 -0
  245. simple_module_images-0.0.14/sm_images/ui/components/map/MapCanvas.test.tsx +229 -0
  246. simple_module_images-0.0.14/sm_images/ui/components/map/MapCanvas.tsx +214 -0
  247. simple_module_images-0.0.14/sm_images/ui/components/map/mapRevision.test.ts +23 -0
  248. simple_module_images-0.0.14/sm_images/ui/components/map/mapRevision.ts +15 -0
  249. simple_module_images-0.0.14/sm_images/ui/components/map/mapSource.test.ts +138 -0
  250. simple_module_images-0.0.14/sm_images/ui/components/map/mapSource.ts +101 -0
  251. simple_module_images-0.0.14/sm_images/ui/components/map/mapWorker.test.ts +24 -0
  252. simple_module_images-0.0.14/sm_images/ui/components/map/mapWorker.ts +22 -0
  253. simple_module_images-0.0.14/sm_images/ui/components/pipeline/ParamsForm.tsx +246 -0
  254. simple_module_images-0.0.14/sm_images/ui/components/pipeline/PipelineTab.tsx +271 -0
  255. simple_module_images-0.0.14/sm_images/ui/components/pipeline/StepCard.tsx +103 -0
  256. simple_module_images-0.0.14/sm_images/ui/components/prompts/GroupResults.tsx +128 -0
  257. simple_module_images-0.0.14/sm_images/ui/components/prompts/PresetPicker.tsx +85 -0
  258. simple_module_images-0.0.14/sm_images/ui/components/prompts/PromptForm.tsx +196 -0
  259. simple_module_images-0.0.14/sm_images/ui/components/prompts/PromptRow.tsx +169 -0
  260. simple_module_images-0.0.14/sm_images/ui/components/prompts/PromptsTab.tsx +178 -0
  261. simple_module_images-0.0.14/sm_images/ui/components/prompts/RunConfirm.tsx +79 -0
  262. simple_module_images-0.0.14/sm_images/ui/components/prompts/RunOnImages.tsx +113 -0
  263. simple_module_images-0.0.14/sm_images/ui/components/prompts/SchemaEditor.tsx +122 -0
  264. simple_module_images-0.0.14/sm_images/ui/components/prompts/SchemaFieldBuilder.tsx +139 -0
  265. simple_module_images-0.0.14/sm_images/ui/components/public/Lightbox.test.tsx +74 -0
  266. simple_module_images-0.0.14/sm_images/ui/components/public/Lightbox.tsx +78 -0
  267. simple_module_images-0.0.14/sm_images/ui/components/public/PublicGallery.test.tsx +71 -0
  268. simple_module_images-0.0.14/sm_images/ui/components/public/PublicGallery.tsx +138 -0
  269. simple_module_images-0.0.14/sm_images/ui/components/results/GenericResultView.test.tsx +71 -0
  270. simple_module_images-0.0.14/sm_images/ui/components/results/GenericResultView.tsx +61 -0
  271. simple_module_images-0.0.14/sm_images/ui/components/results/PromptAnswer.test.tsx +58 -0
  272. simple_module_images-0.0.14/sm_images/ui/components/results/PromptAnswer.tsx +54 -0
  273. simple_module_images-0.0.14/sm_images/ui/components/results/ResultView.tsx +13 -0
  274. simple_module_images-0.0.14/sm_images/ui/components/results/plugins.ts +14 -0
  275. simple_module_images-0.0.14/sm_images/ui/components/results/registry.test.tsx +90 -0
  276. simple_module_images-0.0.14/sm_images/ui/components/results/registry.ts +55 -0
  277. simple_module_images-0.0.14/sm_images/ui/components/review/CorrectionForm.tsx +187 -0
  278. simple_module_images-0.0.14/sm_images/ui/components/review/ReviewPanel.tsx +136 -0
  279. simple_module_images-0.0.14/sm_images/ui/components/share/ShareDialog.tsx +155 -0
  280. simple_module_images-0.0.14/sm_images/ui/components/viewer/GroupEditor.tsx +170 -0
  281. simple_module_images-0.0.14/sm_images/ui/components/viewer/ImageMeta.tsx +86 -0
  282. simple_module_images-0.0.14/sm_images/ui/components/viewer/ImageViewer.tsx +85 -0
  283. simple_module_images-0.0.14/sm_images/ui/components/viewer/NeighborNav.tsx +74 -0
  284. simple_module_images-0.0.14/sm_images/ui/hooks/useCollections.ts +21 -0
  285. simple_module_images-0.0.14/sm_images/ui/hooks/useCursorList.ts +90 -0
  286. simple_module_images-0.0.14/sm_images/ui/hooks/useGeoJsonPreview.ts +37 -0
  287. simple_module_images-0.0.14/sm_images/ui/hooks/useGroups.ts +42 -0
  288. simple_module_images-0.0.14/sm_images/ui/hooks/useImages.ts +47 -0
  289. simple_module_images-0.0.14/sm_images/ui/hooks/useImportJobs.ts +99 -0
  290. simple_module_images-0.0.14/sm_images/ui/hooks/usePipelinePoll.ts +57 -0
  291. simple_module_images-0.0.14/sm_images/ui/hooks/usePromptResults.ts +121 -0
  292. simple_module_images-0.0.14/sm_images/ui/hooks/useRegroupJob.test.tsx +89 -0
  293. simple_module_images-0.0.14/sm_images/ui/hooks/useRegroupJob.ts +71 -0
  294. simple_module_images-0.0.14/sm_images/ui/hooks/useReviewKeys.ts +43 -0
  295. simple_module_images-0.0.14/sm_images/ui/hooks/useReviewQueue.ts +148 -0
  296. simple_module_images-0.0.14/sm_images/ui/hooks/useShares.ts +83 -0
  297. simple_module_images-0.0.14/sm_images/ui/page-tests/Collection.test.tsx +175 -0
  298. simple_module_images-0.0.14/sm_images/ui/page-tests/CollectionMapTab.test.tsx +69 -0
  299. simple_module_images-0.0.14/sm_images/ui/page-tests/CollectionPublicLink.test.tsx +53 -0
  300. simple_module_images-0.0.14/sm_images/ui/page-tests/Collections.test.tsx +66 -0
  301. simple_module_images-0.0.14/sm_images/ui/page-tests/GroupResults.test.tsx +280 -0
  302. simple_module_images-0.0.14/sm_images/ui/page-tests/GroupsEdit.test.tsx +233 -0
  303. simple_module_images-0.0.14/sm_images/ui/page-tests/GroupsTab.test.tsx +103 -0
  304. simple_module_images-0.0.14/sm_images/ui/page-tests/Image.test.tsx +149 -0
  305. simple_module_images-0.0.14/sm_images/ui/page-tests/ImageNav.test.tsx +66 -0
  306. simple_module_images-0.0.14/sm_images/ui/page-tests/ImportWizard.test.tsx +179 -0
  307. simple_module_images-0.0.14/sm_images/ui/page-tests/ImportsTab.test.tsx +150 -0
  308. simple_module_images-0.0.14/sm_images/ui/page-tests/PipelineFixes.test.tsx +181 -0
  309. simple_module_images-0.0.14/sm_images/ui/page-tests/PipelineRestartWatch.test.tsx +122 -0
  310. simple_module_images-0.0.14/sm_images/ui/page-tests/PipelineTab.test.tsx +216 -0
  311. simple_module_images-0.0.14/sm_images/ui/page-tests/PromptRunConfirm.test.tsx +106 -0
  312. simple_module_images-0.0.14/sm_images/ui/page-tests/PromptsFixes.test.tsx +193 -0
  313. simple_module_images-0.0.14/sm_images/ui/page-tests/PromptsTab.test.tsx +225 -0
  314. simple_module_images-0.0.14/sm_images/ui/page-tests/PublicCollection.test.tsx +113 -0
  315. simple_module_images-0.0.14/sm_images/ui/page-tests/Review.test.tsx +137 -0
  316. simple_module_images-0.0.14/sm_images/ui/page-tests/ReviewLabel.test.tsx +20 -0
  317. simple_module_images-0.0.14/sm_images/ui/page-tests/ReviewPaging.test.tsx +149 -0
  318. simple_module_images-0.0.14/sm_images/ui/page-tests/ShareDialog.test.tsx +108 -0
  319. simple_module_images-0.0.14/sm_images/ui/page-tests/TestReportFixes.test.tsx +165 -0
  320. simple_module_images-0.0.14/sm_images/ui/page-tests/pagebuilder-blocks.test.ts +18 -0
  321. simple_module_images-0.0.14/sm_images/ui/page-tests/reviewSupport.tsx +56 -0
  322. simple_module_images-0.0.14/sm_images/ui/page-tests/support.tsx +152 -0
  323. simple_module_images-0.0.14/sm_images/ui/page-tests/test-dom.tsx +121 -0
  324. simple_module_images-0.0.14/sm_images/ui/utils/api-groups.ts +66 -0
  325. simple_module_images-0.0.14/sm_images/ui/utils/api-imports.ts +60 -0
  326. simple_module_images-0.0.14/sm_images/ui/utils/api-net.ts +76 -0
  327. simple_module_images-0.0.14/sm_images/ui/utils/api-prompts.ts +71 -0
  328. simple_module_images-0.0.14/sm_images/ui/utils/api-public.ts +67 -0
  329. simple_module_images-0.0.14/sm_images/ui/utils/api-review.ts +48 -0
  330. simple_module_images-0.0.14/sm_images/ui/utils/api-shares.ts +42 -0
  331. simple_module_images-0.0.14/sm_images/ui/utils/api.ts +175 -0
  332. simple_module_images-0.0.14/sm_images/ui/utils/csrf.ts +62 -0
  333. simple_module_images-0.0.14/sm_images/ui/utils/direct-upload.test.ts +112 -0
  334. simple_module_images-0.0.14/sm_images/ui/utils/direct-upload.ts +92 -0
  335. simple_module_images-0.0.14/sm_images/ui/utils/geojsonDetect.ts +81 -0
  336. simple_module_images-0.0.14/sm_images/ui/utils/geojsonHeadScanner.ts +197 -0
  337. simple_module_images-0.0.14/sm_images/ui/utils/geojsonPreview.test.ts +101 -0
  338. simple_module_images-0.0.14/sm_images/ui/utils/geojsonPreview.ts +146 -0
  339. simple_module_images-0.0.14/sm_images/ui/utils/i18n.ts +182 -0
  340. simple_module_images-0.0.14/sm_images/ui/utils/labels.ts +86 -0
  341. simple_module_images-0.0.14/sm_images/ui/utils/schemaFields.test.ts +64 -0
  342. simple_module_images-0.0.14/sm_images/ui/utils/schemaFields.ts +134 -0
  343. simple_module_images-0.0.14/sm_images/ui/utils/types-prompts.ts +70 -0
  344. simple_module_images-0.0.14/sm_images/ui/utils/types-public.ts +39 -0
  345. simple_module_images-0.0.14/sm_images/ui/utils/types.ts +245 -0
  346. simple_module_images-0.0.14/sm_images/web/__init__.py +3 -0
  347. simple_module_images-0.0.14/sm_images/web/endpoints/__init__.py +1 -0
  348. simple_module_images-0.0.14/sm_images/web/endpoints/api/__init__.py +50 -0
  349. simple_module_images-0.0.14/sm_images/web/endpoints/api/_runtime.py +24 -0
  350. simple_module_images-0.0.14/sm_images/web/endpoints/api/collections.py +118 -0
  351. simple_module_images-0.0.14/sm_images/web/endpoints/api/groups.py +199 -0
  352. simple_module_images-0.0.14/sm_images/web/endpoints/api/images.py +246 -0
  353. simple_module_images-0.0.14/sm_images/web/endpoints/api/imports.py +227 -0
  354. simple_module_images-0.0.14/sm_images/web/endpoints/api/map.py +58 -0
  355. simple_module_images-0.0.14/sm_images/web/endpoints/api/pipeline.py +107 -0
  356. simple_module_images-0.0.14/sm_images/web/endpoints/api/presets.py +50 -0
  357. simple_module_images-0.0.14/sm_images/web/endpoints/api/prompts.py +188 -0
  358. simple_module_images-0.0.14/sm_images/web/endpoints/api/review.py +90 -0
  359. simple_module_images-0.0.14/sm_images/web/endpoints/api/serve.py +65 -0
  360. simple_module_images-0.0.14/sm_images/web/endpoints/api/shares.py +60 -0
  361. simple_module_images-0.0.14/sm_images/web/endpoints/api/uploads.py +163 -0
  362. simple_module_images-0.0.14/sm_images/web/endpoints/csrf.py +26 -0
  363. simple_module_images-0.0.14/sm_images/web/endpoints/deps.py +29 -0
  364. simple_module_images-0.0.14/sm_images/web/endpoints/map_params.py +69 -0
  365. simple_module_images-0.0.14/sm_images/web/endpoints/menu.py +29 -0
  366. simple_module_images-0.0.14/sm_images/web/endpoints/public.py +173 -0
  367. simple_module_images-0.0.14/sm_images/web/endpoints/public_views.py +58 -0
  368. simple_module_images-0.0.14/sm_images/web/endpoints/views.py +150 -0
  369. simple_module_images-0.0.14/sm_images/web/schemas/__init__.py +1 -0
  370. simple_module_images-0.0.14/sm_images/web/schemas/collection.py +65 -0
  371. simple_module_images-0.0.14/sm_images/web/schemas/group.py +100 -0
  372. simple_module_images-0.0.14/sm_images/web/schemas/image.py +179 -0
  373. simple_module_images-0.0.14/sm_images/web/schemas/imports.py +85 -0
  374. simple_module_images-0.0.14/sm_images/web/schemas/pipeline.py +30 -0
  375. simple_module_images-0.0.14/sm_images/web/schemas/prompt.py +132 -0
  376. simple_module_images-0.0.14/sm_images/web/schemas/review.py +38 -0
  377. simple_module_images-0.0.14/sm_images/web/services/__init__.py +32 -0
  378. simple_module_images-0.0.14/sm_images/web/services/collections.py +169 -0
  379. simple_module_images-0.0.14/sm_images/web/services/cursor.py +62 -0
  380. simple_module_images-0.0.14/sm_images/web/services/gallery.py +155 -0
  381. simple_module_images-0.0.14/sm_images/web/services/groups.py +265 -0
  382. simple_module_images-0.0.14/sm_images/web/services/neighbors.py +50 -0
  383. simple_module_images-0.0.14/sm_images/web/services/present.py +102 -0
  384. simple_module_images-0.0.14/sm_images/web/services/presets.py +161 -0
  385. simple_module_images-0.0.14/sm_images/web/services/prompt_answers.py +48 -0
  386. simple_module_images-0.0.14/sm_images/web/services/prompts.py +211 -0
  387. simple_module_images-0.0.14/sm_images/web/services/public_gallery.py +81 -0
  388. simple_module_images-0.0.14/sm_images/web/services/public_stats.py +113 -0
  389. simple_module_images-0.0.14/sm_images/web/services/regroup.py +198 -0
  390. simple_module_images-0.0.14/sm_images/web/services/regroup_write.py +153 -0
  391. simple_module_images-0.0.14/sm_images/web/services/review_queue.py +101 -0
  392. simple_module_images-0.0.14/sm_images/web/services/slugs.py +19 -0
  393. simple_module_images-0.0.14/sm_images/web/services/stats.py +150 -0
  394. simple_module_images-0.0.14/sm_images/web/services/viewer_stats.py +89 -0
  395. simple_module_images-0.0.14/sm_images/web/serving/__init__.py +2 -0
  396. simple_module_images-0.0.14/sm_images/web/serving/cache.py +156 -0
  397. simple_module_images-0.0.14/sm_images/web/serving/ranges.py +90 -0
  398. simple_module_images-0.0.14/sm_images/web/serving/respond.py +263 -0
  399. simple_module_images-0.0.14/sm_images/web/serving/urls.py +124 -0
  400. simple_module_images-0.0.14/tests/__init__.py +11 -0
  401. simple_module_images-0.0.14/tests/conftest.py +100 -0
  402. simple_module_images-0.0.14/tests/core/__init__.py +0 -0
  403. simple_module_images-0.0.14/tests/core/access/__init__.py +0 -0
  404. simple_module_images-0.0.14/tests/core/access/test_access.py +127 -0
  405. simple_module_images-0.0.14/tests/core/access/test_access_sql.py +178 -0
  406. simple_module_images-0.0.14/tests/core/access/test_access_tenants.py +66 -0
  407. simple_module_images-0.0.14/tests/core/access/test_share_candidates.py +153 -0
  408. simple_module_images-0.0.14/tests/core/access/test_sharing_routes.py +215 -0
  409. simple_module_images-0.0.14/tests/core/access/test_starter_rights.py +156 -0
  410. simple_module_images-0.0.14/tests/core/billing/__init__.py +0 -0
  411. simple_module_images-0.0.14/tests/core/billing/test_billing_op_db_time.py +91 -0
  412. simple_module_images-0.0.14/tests/core/billing/test_billing_subject.py +176 -0
  413. simple_module_images-0.0.14/tests/core/billing/test_billing_subject_columns.py +16 -0
  414. simple_module_images-0.0.14/tests/core/billing/test_metering_keys.py +85 -0
  415. simple_module_images-0.0.14/tests/core/billing/test_storage_metering.py +150 -0
  416. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_closure.py +199 -0
  417. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_deadline.py +128 -0
  418. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_direct.py +84 -0
  419. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_durable.py +136 -0
  420. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_pipeline.py +130 -0
  421. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_pipeline_subject.py +152 -0
  422. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_real.py +194 -0
  423. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_repair.py +118 -0
  424. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_subject.py +242 -0
  425. simple_module_images-0.0.14/tests/core/billing/test_storage_metering_swap.py +241 -0
  426. simple_module_images-0.0.14/tests/core/storage/__init__.py +0 -0
  427. simple_module_images-0.0.14/tests/core/storage/test_storage.py +127 -0
  428. simple_module_images-0.0.14/tests/core/storage/test_storage_keys.py +44 -0
  429. simple_module_images-0.0.14/tests/core/test_contracts.py +145 -0
  430. simple_module_images-0.0.14/tests/core/test_error_labels.py +93 -0
  431. simple_module_images-0.0.14/tests/core/test_intents.py +66 -0
  432. simple_module_images-0.0.14/tests/core/test_models.py +89 -0
  433. simple_module_images-0.0.14/tests/core/test_module_boot.py +125 -0
  434. simple_module_images-0.0.14/tests/core/test_seed_guard.py +92 -0
  435. simple_module_images-0.0.14/tests/core/test_task_discovery.py +28 -0
  436. simple_module_images-0.0.14/tests/fixtures/geotagged.jpg +0 -0
  437. simple_module_images-0.0.14/tests/fixtures/make_fixtures.py +79 -0
  438. simple_module_images-0.0.14/tests/fixtures/real_face.jpg +0 -0
  439. simple_module_images-0.0.14/tests/fixtures/real_plate.jpg +0 -0
  440. simple_module_images-0.0.14/tests/fixtures/rotated.jpg +0 -0
  441. simple_module_images-0.0.14/tests/fixtures/sample.heic +0 -0
  442. simple_module_images-0.0.14/tests/fixtures/transparent.png +0 -0
  443. simple_module_images-0.0.14/tests/fixtures/zero_gps.jpg +0 -0
  444. simple_module_images-0.0.14/tests/ingest/__init__.py +0 -0
  445. simple_module_images-0.0.14/tests/ingest/imports/__init__.py +0 -0
  446. simple_module_images-0.0.14/tests/ingest/imports/test_ai_import_fixes.py +54 -0
  447. simple_module_images-0.0.14/tests/ingest/imports/test_import_api.py +164 -0
  448. simple_module_images-0.0.14/tests/ingest/imports/test_import_claim_at_slot.py +96 -0
  449. simple_module_images-0.0.14/tests/ingest/imports/test_import_controls.py +266 -0
  450. simple_module_images-0.0.14/tests/ingest/imports/test_import_download.py +251 -0
  451. simple_module_images-0.0.14/tests/ingest/imports/test_import_fencing.py +266 -0
  452. simple_module_images-0.0.14/tests/ingest/imports/test_import_fixes.py +164 -0
  453. simple_module_images-0.0.14/tests/ingest/imports/test_import_fixes2.py +116 -0
  454. simple_module_images-0.0.14/tests/ingest/imports/test_import_fixes3.py +124 -0
  455. simple_module_images-0.0.14/tests/ingest/imports/test_import_item_errors.py +92 -0
  456. simple_module_images-0.0.14/tests/ingest/imports/test_import_manage_right.py +107 -0
  457. simple_module_images-0.0.14/tests/ingest/imports/test_import_parse.py +190 -0
  458. simple_module_images-0.0.14/tests/ingest/imports/test_import_runner.py +217 -0
  459. simple_module_images-0.0.14/tests/ingest/imports/test_import_tasks.py +200 -0
  460. simple_module_images-0.0.14/tests/ingest/imports/test_imports_fetch.py +253 -0
  461. simple_module_images-0.0.14/tests/ingest/imports/test_imports_fetch_deadline.py +126 -0
  462. simple_module_images-0.0.14/tests/ingest/imports/test_imports_fetch_hardening.py +173 -0
  463. simple_module_images-0.0.14/tests/ingest/imports/test_imports_fetch_tls.py +152 -0
  464. simple_module_images-0.0.14/tests/ingest/imports/test_imports_log_redact.py +83 -0
  465. simple_module_images-0.0.14/tests/ingest/imports/test_imports_rate_limit.py +178 -0
  466. simple_module_images-0.0.14/tests/ingest/imports/test_imports_url_safety.py +192 -0
  467. simple_module_images-0.0.14/tests/ingest/imports/test_imports_user_agent.py +40 -0
  468. simple_module_images-0.0.14/tests/ingest/imports/test_phase4_api.py +126 -0
  469. simple_module_images-0.0.14/tests/ingest/imports/test_phase4_fixes.py +211 -0
  470. simple_module_images-0.0.14/tests/ingest/imports/test_phase4_fixes2.py +178 -0
  471. simple_module_images-0.0.14/tests/ingest/imports/test_phase4_round2.py +149 -0
  472. simple_module_images-0.0.14/tests/ingest/imports/test_phase4_round3.py +98 -0
  473. simple_module_images-0.0.14/tests/ingest/imports/test_phase4_round4.py +122 -0
  474. simple_module_images-0.0.14/tests/ingest/imports/test_zip_api.py +123 -0
  475. simple_module_images-0.0.14/tests/ingest/imports/test_zip_fixes.py +253 -0
  476. simple_module_images-0.0.14/tests/ingest/imports/test_zip_fixes2.py +147 -0
  477. simple_module_images-0.0.14/tests/ingest/imports/test_zip_fixes3.py +124 -0
  478. simple_module_images-0.0.14/tests/ingest/imports/test_zip_fixes4.py +148 -0
  479. simple_module_images-0.0.14/tests/ingest/imports/test_zip_import.py +206 -0
  480. simple_module_images-0.0.14/tests/ingest/imports/test_zip_import_recovery.py +126 -0
  481. simple_module_images-0.0.14/tests/ingest/imports/test_zip_safety.py +139 -0
  482. simple_module_images-0.0.14/tests/ingest/test_direct_upload.py +120 -0
  483. simple_module_images-0.0.14/tests/ingest/test_direct_upload_review.py +183 -0
  484. simple_module_images-0.0.14/tests/ingest/test_direct_upload_transient.py +127 -0
  485. simple_module_images-0.0.14/tests/ingest/test_ingest_guards.py +111 -0
  486. simple_module_images-0.0.14/tests/ingest/test_ingest_hold_outcome.py +96 -0
  487. simple_module_images-0.0.14/tests/ingest/test_ingest_hold_rollback.py +92 -0
  488. simple_module_images-0.0.14/tests/ingest/test_ingest_hold_subject.py +116 -0
  489. simple_module_images-0.0.14/tests/ingest/test_ingest_staged_size.py +43 -0
  490. simple_module_images-0.0.14/tests/ingest/test_review_round1.py +122 -0
  491. simple_module_images-0.0.14/tests/ingest/test_service_holds_host.py +43 -0
  492. simple_module_images-0.0.14/tests/ingest/test_slots_savepoint_commit.py +28 -0
  493. simple_module_images-0.0.14/tests/ingest/test_upload_admission.py +105 -0
  494. simple_module_images-0.0.14/tests/ingest/test_upload_admission_race.py +114 -0
  495. simple_module_images-0.0.14/tests/ingest/test_upload_api.py +215 -0
  496. simple_module_images-0.0.14/tests/ingest/test_upload_base64.py +128 -0
  497. simple_module_images-0.0.14/tests/ingest/test_upload_body_limit.py +66 -0
  498. simple_module_images-0.0.14/tests/ingest/test_upload_file_db.py +37 -0
  499. simple_module_images-0.0.14/tests/ingest/test_upload_lease.py +215 -0
  500. simple_module_images-0.0.14/tests/ingest/test_upload_lease_r3.py +133 -0
  501. simple_module_images-0.0.14/tests/ingest/test_upload_reaper.py +86 -0
  502. simple_module_images-0.0.14/tests/ingest/test_upload_reaper_race.py +68 -0
  503. simple_module_images-0.0.14/tests/ingest/test_upload_session.py +164 -0
  504. simple_module_images-0.0.14/tests/ingest/test_upload_subject.py +134 -0
  505. simple_module_images-0.0.14/tests/jobs/__init__.py +0 -0
  506. simple_module_images-0.0.14/tests/jobs/test_janitor.py +192 -0
  507. simple_module_images-0.0.14/tests/jobs/test_janitor_task.py +228 -0
  508. simple_module_images-0.0.14/tests/jobs/test_phase_isolation.py +137 -0
  509. simple_module_images-0.0.14/tests/jobs/test_purge_failures.py +225 -0
  510. simple_module_images-0.0.14/tests/jobs/test_purge_failures_r2.py +75 -0
  511. simple_module_images-0.0.14/tests/jobs/test_purge_shares.py +91 -0
  512. simple_module_images-0.0.14/tests/map/__init__.py +0 -0
  513. simple_module_images-0.0.14/tests/map/test_map_build.py +215 -0
  514. simple_module_images-0.0.14/tests/map/test_map_points.py +226 -0
  515. simple_module_images-0.0.14/tests/map/test_map_points_etag.py +64 -0
  516. simple_module_images-0.0.14/tests/map/test_map_revoke.py +212 -0
  517. simple_module_images-0.0.14/tests/map/test_map_revoke_moves.py +192 -0
  518. simple_module_images-0.0.14/tests/map/test_map_stale.py +73 -0
  519. simple_module_images-0.0.14/tests/map/test_map_style.py +88 -0
  520. simple_module_images-0.0.14/tests/map/test_map_tiles.py +217 -0
  521. simple_module_images-0.0.14/tests/map/test_map_tippecanoe.py +132 -0
  522. simple_module_images-0.0.14/tests/pg_support.py +76 -0
  523. simple_module_images-0.0.14/tests/pipeline/__init__.py +0 -0
  524. simple_module_images-0.0.14/tests/pipeline/ai/__init__.py +0 -0
  525. simple_module_images-0.0.14/tests/pipeline/ai/test_ai_auto_run.py +58 -0
  526. simple_module_images-0.0.14/tests/pipeline/ai/test_ai_fixes.py +124 -0
  527. simple_module_images-0.0.14/tests/pipeline/ai/test_ai_fixes2.py +151 -0
  528. simple_module_images-0.0.14/tests/pipeline/ai/test_ai_schema_fixes3.py +42 -0
  529. simple_module_images-0.0.14/tests/pipeline/ai/test_ai_schema_safety.py +196 -0
  530. simple_module_images-0.0.14/tests/pipeline/ai/test_ai_steps.py +245 -0
  531. simple_module_images-0.0.14/tests/pipeline/ai/test_ai_subject.py +82 -0
  532. simple_module_images-0.0.14/tests/pipeline/ai/test_cross_check_executor.py +160 -0
  533. simple_module_images-0.0.14/tests/pipeline/ai/test_group_prompts.py +235 -0
  534. simple_module_images-0.0.14/tests/pipeline/ai/test_group_prompts_api.py +120 -0
  535. simple_module_images-0.0.14/tests/pipeline/ai/test_group_prompts_store.py +139 -0
  536. simple_module_images-0.0.14/tests/pipeline/ai/test_group_run_hardening.py +159 -0
  537. simple_module_images-0.0.14/tests/pipeline/ai/test_presets_api.py +154 -0
  538. simple_module_images-0.0.14/tests/pipeline/ai/test_presets_contract.py +75 -0
  539. simple_module_images-0.0.14/tests/pipeline/ai/test_prompts_api.py +183 -0
  540. simple_module_images-0.0.14/tests/pipeline/ai/test_prompts_api_fixes.py +86 -0
  541. simple_module_images-0.0.14/tests/pipeline/ai/test_review_api.py +230 -0
  542. simple_module_images-0.0.14/tests/pipeline/ai/test_review_fixes.py +117 -0
  543. simple_module_images-0.0.14/tests/pipeline/ai/test_step_run_answers.py +94 -0
  544. simple_module_images-0.0.14/tests/pipeline/ai/test_viewer_prompt_results.py +49 -0
  545. simple_module_images-0.0.14/tests/pipeline/steps/__init__.py +0 -0
  546. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_degenerate.py +213 -0
  547. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_fork.py +75 -0
  548. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_malformed.py +99 -0
  549. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_mapping.py +91 -0
  550. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_models.py +132 -0
  551. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_pipeline.py +165 -0
  552. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_real.py +97 -0
  553. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_step.py +266 -0
  554. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_weights.py +146 -0
  555. simple_module_images-0.0.14/tests/pipeline/steps/test_anonymize_wiring.py +131 -0
  556. simple_module_images-0.0.14/tests/pipeline/steps/test_classify_vocabulary.py +27 -0
  557. simple_module_images-0.0.14/tests/pipeline/steps/test_exif.py +113 -0
  558. simple_module_images-0.0.14/tests/pipeline/steps/test_processing_review.py +90 -0
  559. simple_module_images-0.0.14/tests/pipeline/steps/test_quality_step.py +141 -0
  560. simple_module_images-0.0.14/tests/pipeline/steps/test_renditions.py +69 -0
  561. simple_module_images-0.0.14/tests/pipeline/test_collection_default_pipeline.py +25 -0
  562. simple_module_images-0.0.14/tests/pipeline/test_extensions.py +144 -0
  563. simple_module_images-0.0.14/tests/pipeline/test_framework_pins.py +33 -0
  564. simple_module_images-0.0.14/tests/pipeline/test_pipeline_api.py +106 -0
  565. simple_module_images-0.0.14/tests/pipeline/test_pipeline_api_put.py +76 -0
  566. simple_module_images-0.0.14/tests/pipeline/test_pipeline_api_run.py +123 -0
  567. simple_module_images-0.0.14/tests/pipeline/test_pipeline_config.py +75 -0
  568. simple_module_images-0.0.14/tests/pipeline/test_pipeline_executor.py +253 -0
  569. simple_module_images-0.0.14/tests/pipeline/test_pipeline_leases.py +216 -0
  570. simple_module_images-0.0.14/tests/pipeline/test_pipeline_missing_stale.py +80 -0
  571. simple_module_images-0.0.14/tests/pipeline/test_pipeline_reopen.py +170 -0
  572. simple_module_images-0.0.14/tests/pipeline/test_pipeline_restart.py +146 -0
  573. simple_module_images-0.0.14/tests/pipeline/test_pipeline_review_fixes.py +257 -0
  574. simple_module_images-0.0.14/tests/pipeline/test_pipeline_review_fixes2.py +132 -0
  575. simple_module_images-0.0.14/tests/pipeline/test_pipeline_review_fixes3.py +100 -0
  576. simple_module_images-0.0.14/tests/pipeline/test_pipeline_review_fixes4.py +141 -0
  577. simple_module_images-0.0.14/tests/pipeline/test_pipeline_review_fixes5.py +48 -0
  578. simple_module_images-0.0.14/tests/pipeline/test_pipeline_tenancy.py +193 -0
  579. simple_module_images-0.0.14/tests/pipeline/test_pipeline_web.py +115 -0
  580. simple_module_images-0.0.14/tests/pipeline/test_pipeline_worker.py +168 -0
  581. simple_module_images-0.0.14/tests/pipeline/test_plugin_e2e.py +106 -0
  582. simple_module_images-0.0.14/tests/pipeline/test_registry.py +178 -0
  583. simple_module_images-0.0.14/tests/pipeline/test_step_context.py +144 -0
  584. simple_module_images-0.0.14/tests/pipeline/test_step_run_labels.py +90 -0
  585. simple_module_images-0.0.14/tests/plugin_fixture/broken_fixture/__init__.py +3 -0
  586. simple_module_images-0.0.14/tests/plugin_fixture/images_testplugin/__init__.py +5 -0
  587. simple_module_images-0.0.14/tests/plugin_fixture/images_testplugin/images_extensions.py +85 -0
  588. simple_module_images-0.0.14/tests/plugin_fixture/images_testplugin/module.py +9 -0
  589. simple_module_images-0.0.14/tests/plugin_fixture/lucas_fixture/__init__.py +1 -0
  590. simple_module_images-0.0.14/tests/plugin_fixture/lucas_fixture/images_extensions.py +30 -0
  591. simple_module_images-0.0.14/tests/support/__init__.py +1 -0
  592. simple_module_images-0.0.14/tests/support/access.py +147 -0
  593. simple_module_images-0.0.14/tests/support/ai.py +125 -0
  594. simple_module_images-0.0.14/tests/support/anonymize.py +77 -0
  595. simple_module_images-0.0.14/tests/support/app_harness.py +140 -0
  596. simple_module_images-0.0.14/tests/support/billing.py +274 -0
  597. simple_module_images-0.0.14/tests/support/direct.py +39 -0
  598. simple_module_images-0.0.14/tests/support/fetch.py +89 -0
  599. simple_module_images-0.0.14/tests/support/groups.py +80 -0
  600. simple_module_images-0.0.14/tests/support/imports.py +194 -0
  601. simple_module_images-0.0.14/tests/support/isolation.py +62 -0
  602. simple_module_images-0.0.14/tests/support/map.py +61 -0
  603. simple_module_images-0.0.14/tests/support/onnx.py +112 -0
  604. simple_module_images-0.0.14/tests/support/pipeline.py +214 -0
  605. simple_module_images-0.0.14/tests/support/pipeline_api.py +57 -0
  606. simple_module_images-0.0.14/tests/support/prompts.py +44 -0
  607. simple_module_images-0.0.14/tests/support/public_stats.py +76 -0
  608. simple_module_images-0.0.14/tests/support/read_routes.py +80 -0
  609. simple_module_images-0.0.14/tests/support/serve.py +143 -0
  610. simple_module_images-0.0.14/tests/support/step.py +27 -0
  611. simple_module_images-0.0.14/tests/support/stub_auth.py +64 -0
  612. simple_module_images-0.0.14/tests/support/upload.py +110 -0
  613. simple_module_images-0.0.14/tests/support/zip.py +177 -0
  614. simple_module_images-0.0.14/tests/web/__init__.py +0 -0
  615. simple_module_images-0.0.14/tests/web/collections/__init__.py +0 -0
  616. simple_module_images-0.0.14/tests/web/collections/test_collection_public_path.py +13 -0
  617. simple_module_images-0.0.14/tests/web/collections/test_collections_api.py +266 -0
  618. simple_module_images-0.0.14/tests/web/collections/test_collections_list.py +164 -0
  619. simple_module_images-0.0.14/tests/web/collections/test_console_views.py +223 -0
  620. simple_module_images-0.0.14/tests/web/collections/test_gallery_api.py +134 -0
  621. simple_module_images-0.0.14/tests/web/collections/test_image_neighbors.py +94 -0
  622. simple_module_images-0.0.14/tests/web/collections/test_public_page.py +103 -0
  623. simple_module_images-0.0.14/tests/web/collections/test_public_stats.py +184 -0
  624. simple_module_images-0.0.14/tests/web/collections/test_public_stats_bounded.py +87 -0
  625. simple_module_images-0.0.14/tests/web/collections/test_stats.py +230 -0
  626. simple_module_images-0.0.14/tests/web/collections/test_viewer_stats.py +179 -0
  627. simple_module_images-0.0.14/tests/web/groups/__init__.py +0 -0
  628. simple_module_images-0.0.14/tests/web/groups/test_group_fixes.py +208 -0
  629. simple_module_images-0.0.14/tests/web/groups/test_groups.py +264 -0
  630. simple_module_images-0.0.14/tests/web/groups/test_groups_fences.py +134 -0
  631. simple_module_images-0.0.14/tests/web/groups/test_groups_jobs.py +253 -0
  632. simple_module_images-0.0.14/tests/web/groups/test_groups_races.py +109 -0
  633. simple_module_images-0.0.14/tests/web/serving/__init__.py +0 -0
  634. simple_module_images-0.0.14/tests/web/serving/test_cache_headers.py +130 -0
  635. simple_module_images-0.0.14/tests/web/serving/test_ranges.py +69 -0
  636. simple_module_images-0.0.14/tests/web/serving/test_read_routes.py +209 -0
  637. simple_module_images-0.0.14/tests/web/serving/test_serve.py +178 -0
  638. simple_module_images-0.0.14/tests/web/serving/test_serve_display_browser.py +74 -0
  639. simple_module_images-0.0.14/tests/web/serving/test_serve_display_origin.py +128 -0
  640. simple_module_images-0.0.14/tests/web/serving/test_serve_display_trust.py +153 -0
  641. simple_module_images-0.0.14/tests/web/serving/test_serve_gate.py +84 -0
  642. simple_module_images-0.0.14/tests/web/serving/test_serve_public.py +159 -0
  643. simple_module_images-0.0.14/tests/web/serving/test_serve_redaction.py +236 -0
  644. simple_module_images-0.0.14/tests/web/serving/test_serve_revalidate.py +105 -0
  645. simple_module_images-0.0.14/tests/web/serving/test_serve_versions.py +139 -0
  646. simple_module_images-0.0.14/tests/web/serving/test_urls.py +171 -0
  647. simple_module_images-0.0.14/tests/web/serving/test_viewer_error_shape.py +114 -0
  648. simple_module_images-0.0.14/tests/web/serving/test_viewer_withheld.py +143 -0
  649. simple_module_images-0.0.14/tsconfig.json +10 -0
@@ -0,0 +1,57 @@
1
+ .claude/settings.local.json
2
+
3
+ # Python
4
+ .venv/
5
+ __pycache__/
6
+ *.pyc
7
+ *.egg-info/
8
+
9
+ # Node
10
+ node_modules/
11
+ dist/
12
+
13
+ # Built module frontend bundles (force-included into wheels at build time)
14
+ modules/*/*/static/dist/
15
+
16
+ # Host build output and the module-pages manifest regenerated by `make gen-pages`
17
+ host/static/dist/
18
+ host/client_app/modules.manifest.json
19
+ host/client_app/modules.generated.ts
20
+ host/client_app/modules.generated.css
21
+ host/client_app/modules.assets.json
22
+
23
+ # Local databases. `make migrate` resolves alembic's script_location relative
24
+ # to the repo root, so running it the documented way leaves ./app.db here —
25
+ # not under host/ — and it must never be committed.
26
+ host/*.db
27
+ app.db*
28
+ # SQLite runs in WAL mode since framework 0.0.35 (#339): its sidecar files.
29
+ host/*.db-wal
30
+ host/*.db-shm
31
+ # `make beat` keeps Celery beat's schedule state in the repo root.
32
+ celerybeat-schedule*
33
+
34
+ # Runtime upload storage (PagebuilderSettings.media_root)
35
+ var/
36
+ # file_storage's local backend (DEFAULT_FS_ROOT = ./uploads), which the dev
37
+ # host creates in the repo root
38
+ uploads/
39
+
40
+ # Env
41
+ .env
42
+
43
+ # Playwright
44
+ playwright-report/
45
+ test-results/
46
+ .e2e-shards/
47
+ blob-report/
48
+ .playwright-mcp/
49
+
50
+ # macOS
51
+ .DS_Store
52
+
53
+ # QA / verify pipeline artifacts (/qa, /vf)
54
+ .qa/
55
+ .verify/
56
+ # Scratch database a /qa run boots against, so it never touches host/app.db.
57
+ qa.db*
@@ -0,0 +1,61 @@
1
+ simple_module_images
2
+ Copyright (c) Anto Subash. Licensed under the MIT License.
3
+
4
+ The optional `anonymize` step downloads the following third-party models at
5
+ run time. They are not included in this package; their notices are reproduced
6
+ here because a deployment that caches or redistributes them must keep them.
7
+
8
+ -------------------------------------------------------------------------------
9
+ YuNet face detector - face_detection_yunet_2026may.onnx
10
+ Source: https://github.com/opencv/opencv_zoo/tree/eb9f4f2d4b79b58e5513b5d25d5f0243a8357bf4/models/face_detection_yunet
11
+ Training code: https://github.com/ShiqiYu/libfacedetection.train
12
+ License: MIT
13
+
14
+ MIT License
15
+
16
+ Copyright (c) 2020 Shiqi Yu <shiqi.yu@gmail.com>
17
+
18
+ Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ of this software and associated documentation files (the "Software"), to deal
20
+ in the Software without restriction, including without limitation the rights
21
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
+ copies of the Software, and to permit persons to whom the Software is
23
+ furnished to do so, subject to the following conditions:
24
+
25
+ The above copyright notice and this permission notice shall be included in all
26
+ copies or substantial portions of the Software.
27
+
28
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34
+ SOFTWARE.
35
+
36
+ -------------------------------------------------------------------------------
37
+ YOLOv9 licence-plate detector - yolo-v9-s-608-license-plates-end2end.onnx
38
+ Source: https://github.com/ankandrew/open-image-models/releases/tag/assets
39
+ License: MIT
40
+
41
+ MIT License
42
+
43
+ Copyright (c) 2024 ankandrew
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining a copy
46
+ of this software and associated documentation files (the "Software"), to deal
47
+ in the Software without restriction, including without limitation the rights
48
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49
+ copies of the Software, and to permit persons to whom the Software is
50
+ furnished to do so, subject to the following conditions:
51
+
52
+ The above copyright notice and this permission notice shall be included in all
53
+ copies or substantial portions of the Software.
54
+
55
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
61
+ SOFTWARE.
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.5
2
+ Name: simple_module_images
3
+ Version: 0.0.14
4
+ Summary: Image collections with a processing pipeline: EXIF, renditions, quality checks, optional anonymisation, geo-located imports and map tiles
5
+ Project-URL: Repository, https://github.com/antosubash/simple_module_python_modules
6
+ Author-email: Anto Subash <antosubash@live.com>
7
+ License-Expression: MIT
8
+ License-File: NOTICE
9
+ Keywords: exif,gallery,geo,images,simple-module
10
+ Requires-Python: >=3.12
11
+ Requires-Dist: httpx>=0.27
12
+ Requires-Dist: ijson>=3.2
13
+ Requires-Dist: itsdangerous<3,>=2.0
14
+ Requires-Dist: pillow-heif>=1.4
15
+ Requires-Dist: pillow>=10.0
16
+ Requires-Dist: pydantic-settings>=2.0
17
+ Requires-Dist: regex>=2023.0
18
+ Requires-Dist: simple-module-background-tasks<0.1,>=0.0.44
19
+ Requires-Dist: simple-module-core<0.1,>=0.0.42
20
+ Requires-Dist: simple-module-db<0.1,>=0.0.41
21
+ Requires-Dist: simple-module-file-storage<0.1,>=0.0.44
22
+ Requires-Dist: simple-module-hosting<0.1,>=0.0.42
23
+ Requires-Dist: simple-module-inertia<0.1,>=0.0.41
24
+ Requires-Dist: simple-module-settings<0.1,>=0.0.41
25
+ Requires-Dist: simple-module-sharing<0.1,>=0.0.44
26
+ Provides-Extra: ai
27
+ Requires-Dist: simple-module-ai<0.1,>=0.0.14; extra == 'ai'
28
+ Provides-Extra: anonymize
29
+ Requires-Dist: onnxruntime>=1.18; extra == 'anonymize'
30
+ Provides-Extra: billing
31
+ Requires-Dist: simple-module-billing<0.1,>=0.0.14; extra == 'billing'
32
+ Provides-Extra: dev
33
+ Requires-Dist: pmtiles>=3.2; extra == 'dev'
34
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0; extra == 'dev'
36
+ Requires-Dist: simple-module-test<0.1,>=0.0.41; extra == 'dev'
37
+ Provides-Extra: pagebuilder
38
+ Requires-Dist: simple-module-pagebuilder<0.1,>=0.0.12; extra == 'pagebuilder'
39
+ Provides-Extra: quality
40
+ Requires-Dist: opencv-python-headless>=4.9; extra == 'quality'
41
+ Description-Content-Type: text/markdown
42
+
43
+ # simple_module_images
44
+
45
+ Image collections for SimpleModule hosts. A collection holds images whose
46
+ **originals are immutable**; everything derived from them (EXIF and location,
47
+ renditions, quality metrics, an optionally anonymised display copy, map tiles)
48
+ is produced by pipeline steps that run as background tasks. Collections are
49
+ private to their owner, shared with chosen users, internal to the organisation
50
+ or public.
51
+
52
+ Imports take single files, batches, large direct uploads, ZIP archives and
53
+ GeoJSON sources of up to a million located images. Groups, AI prompts with a
54
+ review queue, a map (GeoJSON points and PMTiles) and a public gallery are
55
+ included. Design:
56
+ `docs/superpowers/specs/2026-10-28-images-module-design.md` in the source repo;
57
+ the guides are in [`docs/`](docs/index.md).
58
+
59
+ ## Install
60
+
61
+ ```bash
62
+ pip install simple_module_images
63
+ ```
64
+
65
+ Add `simple_module_images` to your host's dependencies; for an in-repo checkout,
66
+ resolve it from the workspace:
67
+
68
+ ```toml
69
+ [tool.uv.sources.simple_module_images]
70
+ workspace = true
71
+ ```
72
+
73
+ A plain install pulls no onnxruntime or OpenCV. Heavy processors are
74
+ extras, imported only inside the step that needs them:
75
+
76
+ | Extra | Adds |
77
+ | --- | --- |
78
+ | `quality` | OpenCV: resolution, blur and exposure metrics |
79
+ | `anonymize` | onnxruntime: YuNet face and YOLOv9 plate detection (MIT models), blurred into a display copy (the original is kept); weights from `anonymize_weights_path` or a pinned, checksummed download on first use |
80
+ | `ai` | `simple_module_ai`: prompt-based image analysis |
81
+ | `billing` | `simple_module_billing`: storage and request metering |
82
+ | `pagebuilder` | `simple_module_pagebuilder`: an image gallery block |
83
+
84
+ The map view needs no extra: its PMTiles archive is built by the `tippecanoe`
85
+ binary (`tippecanoe_path`), which must be on the worker's machine.
86
+
87
+ **Models and licences.** The `anonymize` extra installs only onnxruntime
88
+ (MIT). The step downloads two MIT-licensed ONNX models on first use, pinned by
89
+ SHA-256: **YuNet** (faces; Shiqi Yu, via
90
+ [OpenCV Zoo](https://github.com/opencv/opencv_zoo/tree/eb9f4f2d4b79b58e5513b5d25d5f0243a8357bf4/models/face_detection_yunet))
91
+ and **YOLOv9 licence-plate detector** (ankandrew,
92
+ [open-image-models](https://github.com/ankandrew/open-image-models)). Their
93
+ copyright notices are in this module's `NOTICE`. Recall is unverified, and
94
+ weights are cached under `~/.cache/simple_module_images/models` unless
95
+ `anonymize_weights_path` points at `face.onnx` and `plate.onnx`. See
96
+ [docs/index.md](docs/index.md#anonymize-models-and-licences).
97
+
98
+ The module needs the framework's `settings`, `sharing`, `file_storage` and
99
+ `background_tasks` modules. Migrations live in the consuming host
100
+ (`make migration`), never in the wheel.
101
+
102
+ Image processing runs in Celery workers (`make worker`, `worker-imports`,
103
+ `worker-heavy`, `worker-gpu`, `beat`) or inline with
104
+ `SM_BG_TASKS_TASK_ALWAYS_EAGER=true`. A plugin that adds steps ships an
105
+ `images_extensions.py` and must be installed in the web process and every
106
+ worker. See [docs/worker.md](docs/worker.md) and
107
+ [docs/writing-a-plugin.md](docs/writing-a-plugin.md).
108
+
109
+ ## Usage
110
+
111
+ The console is at `/admin/images`, the JSON API under `/api/images` and public
112
+ collections at `/images/c/{slug}`. Every router binds a tenant: a single-tenant
113
+ host uses `default`, a multi-tenant host the organisation the framework
114
+ resolved (403 `tenant_required` for the console, 404 for public routes when
115
+ none).
116
+
117
+ ### Permissions
118
+
119
+ | Permission | Allows |
120
+ | --- | --- |
121
+ | `images.view` | See collections and images the access policy admits |
122
+ | `images.create` | Create collections and upload images |
123
+ | `images.publish` | Make a collection public or internal |
124
+ | `images.manage` | Manage every collection regardless of owner |
125
+ | `images.originals.view` | Download the immutable original |
126
+
127
+ ### Settings
128
+
129
+ The module's settings are governed by the framework's `settings.edit`, as every
130
+ other module's are; images has no settings permission of its own.
131
+
132
+ Stored in the database and edited on the Settings screen; there is no
133
+ `SM_IMAGES_*` environment variable. System scope: one configuration for every
134
+ tenant. Fields marked as needing a restart (`tippecanoe_path`,
135
+ `public_asset_base_url`) are read once at boot; workers pick up the rest within
136
+ about 30 seconds.
137
+
138
+ | Setting | Default |
139
+ | --- | --- |
140
+ | `max_image_bytes` | 50 MiB |
141
+ | `batch_max` | 50 |
142
+ | `upload_body_max_bytes` | 100 MiB |
143
+ | `direct_upload_threshold` | 20 MiB |
144
+ | `max_open_uploads_per_tenant` | 20 |
145
+ | `zip_max_bytes` / `zip_max_entries` | 2 GiB / 10 000 |
146
+ | `zip_max_entry_bytes` / `zip_max_total_bytes` / `zip_max_ratio` | 200 MiB / 8 GiB / 200 |
147
+ | `geojson_max_features` / `geojson_max_bytes` / `geojson_max_feature_bytes` | 1 000 000 / 2 GiB / 60 MiB |
148
+ | `download_concurrency_per_domain` / `download_concurrency_total` (per download task) / `download_timeout` | 4 / 32 / 60 s |
149
+ | `thumbnail_sizes` | marker 64, small 160, medium 400, large 1024 |
150
+ | `dedupe_by_hash` | off |
151
+ | `tippecanoe_path`, `anonymize_weights_path` | `tippecanoe`, empty |
152
+ | `map_rebuild_threshold_pct` / `map_rebuild_threshold_abs` | 5 / 100 |
153
+ | `map_style_url` (basemap; empty = flat, no third-party request) | `https://tiles.openfreemap.org/styles/positron` |
154
+ | `public_asset_base_url` | empty |
155
+ | `janitor_grace_days`, `step_output_max_bytes`, `step_lease_seconds` | 7, 65 536, 1 800 |
156
+
157
+ ### Routes
158
+
159
+ Upload routes (`/api/images/collections/{id}/images`, `.../imports`,
160
+ `.../imports/zip` and `/api/images/uploads/`) carry a request-body ceiling of
161
+ `upload_body_max_bytes` plus multipart framing; the rest use the host's global
162
+ limit. Public exemptions are `GET`/`HEAD` only, under `/images/c/` and
163
+ `/api/images/public/`.
164
+
165
+ ### Map
166
+
167
+ - `GET /api/images/collections/{id}/points?bbox=minx,miny,maxx,maxy&limit=&cursor=`
168
+ (anonymous twin: `/api/images/public/c/{slug}/points`) answers a GeoJSON
169
+ `FeatureCollection`. Each point carries only `id`, `captured_at` and
170
+ `group_id`; an image whose display mutator has not settled is not a point.
171
+ `limit` is clamped to 5000; follow `next_cursor` for the rest.
172
+ - `GET|HEAD …/collections/{id}/map.pmtiles` (twin: `/api/images/public/c/{slug}/map.pmtiles`)
173
+ serves the collection's PMTiles archive with `Range`, checking access on
174
+ every request. It is a 404 until a map is built.
175
+ - `images.build_map` (queue `images`) builds the archive with `tippecanoe`.
176
+ A rebuild starts once the changes since the last build reach
177
+ `map_rebuild_threshold_abs` or `map_rebuild_threshold_pct` percent of its
178
+ points (both at least 1). A move does not wait for the threshold. A visibility
179
+ change, a removed point (an image trashed or its location cleared) and a
180
+ pipeline save that changes the redaction gate withdraw the archive in the
181
+ same transaction and build a fresh one. An archive is stamped with the
182
+ redaction gate it was built under, and is a 404 under any other (for
183
+ example once a mutator plugin is removed) until `images.reconcile` rebuilds it.
184
+ - The `images.tippecanoe` health check is degraded while the binary cannot be
185
+ found. Points keep working.
186
+ - The points are drawn over the basemap `map_style_url` names (OpenFreeMap's
187
+ Positron by default; its origin is added to the CSP). Viewers' browsers
188
+ fetch its tiles from that host, so it sees their IP and the area they view;
189
+ set it to empty for a flat background with no third-party request. A style
190
+ that cannot be fetched falls back to the flat background.
191
+
192
+ ## Documentation
193
+
194
+ | Page | For |
195
+ | --- | --- |
196
+ | [docs/index.md](docs/index.md) | Concepts, install, permissions, every setting |
197
+ | [docs/access.md](docs/access.md) | Visibility, shares, originals, withheld images |
198
+ | [docs/imports.md](docs/imports.md) | Uploads, direct upload and bucket CORS, ZIP, GeoJSON, limits |
199
+ | [docs/pipeline.md](docs/pipeline.md) | Steps, leases, AI prompts, groups, presets, review, storage metering |
200
+ | [docs/writing-a-plugin.md](docs/writing-a-plugin.md) | Steps, presets and result views from another module |
201
+ | [docs/worker.md](docs/worker.md) | Workers, beat, timeouts, tuning, recovery times |
202
+ | [docs/migrating-from-portal.md](docs/migrating-from-portal.md) | Moving off the portal's feature |
@@ -0,0 +1,160 @@
1
+ # simple_module_images
2
+
3
+ Image collections for SimpleModule hosts. A collection holds images whose
4
+ **originals are immutable**; everything derived from them (EXIF and location,
5
+ renditions, quality metrics, an optionally anonymised display copy, map tiles)
6
+ is produced by pipeline steps that run as background tasks. Collections are
7
+ private to their owner, shared with chosen users, internal to the organisation
8
+ or public.
9
+
10
+ Imports take single files, batches, large direct uploads, ZIP archives and
11
+ GeoJSON sources of up to a million located images. Groups, AI prompts with a
12
+ review queue, a map (GeoJSON points and PMTiles) and a public gallery are
13
+ included. Design:
14
+ `docs/superpowers/specs/2026-10-28-images-module-design.md` in the source repo;
15
+ the guides are in [`docs/`](docs/index.md).
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pip install simple_module_images
21
+ ```
22
+
23
+ Add `simple_module_images` to your host's dependencies; for an in-repo checkout,
24
+ resolve it from the workspace:
25
+
26
+ ```toml
27
+ [tool.uv.sources.simple_module_images]
28
+ workspace = true
29
+ ```
30
+
31
+ A plain install pulls no onnxruntime or OpenCV. Heavy processors are
32
+ extras, imported only inside the step that needs them:
33
+
34
+ | Extra | Adds |
35
+ | --- | --- |
36
+ | `quality` | OpenCV: resolution, blur and exposure metrics |
37
+ | `anonymize` | onnxruntime: YuNet face and YOLOv9 plate detection (MIT models), blurred into a display copy (the original is kept); weights from `anonymize_weights_path` or a pinned, checksummed download on first use |
38
+ | `ai` | `simple_module_ai`: prompt-based image analysis |
39
+ | `billing` | `simple_module_billing`: storage and request metering |
40
+ | `pagebuilder` | `simple_module_pagebuilder`: an image gallery block |
41
+
42
+ The map view needs no extra: its PMTiles archive is built by the `tippecanoe`
43
+ binary (`tippecanoe_path`), which must be on the worker's machine.
44
+
45
+ **Models and licences.** The `anonymize` extra installs only onnxruntime
46
+ (MIT). The step downloads two MIT-licensed ONNX models on first use, pinned by
47
+ SHA-256: **YuNet** (faces; Shiqi Yu, via
48
+ [OpenCV Zoo](https://github.com/opencv/opencv_zoo/tree/eb9f4f2d4b79b58e5513b5d25d5f0243a8357bf4/models/face_detection_yunet))
49
+ and **YOLOv9 licence-plate detector** (ankandrew,
50
+ [open-image-models](https://github.com/ankandrew/open-image-models)). Their
51
+ copyright notices are in this module's `NOTICE`. Recall is unverified, and
52
+ weights are cached under `~/.cache/simple_module_images/models` unless
53
+ `anonymize_weights_path` points at `face.onnx` and `plate.onnx`. See
54
+ [docs/index.md](docs/index.md#anonymize-models-and-licences).
55
+
56
+ The module needs the framework's `settings`, `sharing`, `file_storage` and
57
+ `background_tasks` modules. Migrations live in the consuming host
58
+ (`make migration`), never in the wheel.
59
+
60
+ Image processing runs in Celery workers (`make worker`, `worker-imports`,
61
+ `worker-heavy`, `worker-gpu`, `beat`) or inline with
62
+ `SM_BG_TASKS_TASK_ALWAYS_EAGER=true`. A plugin that adds steps ships an
63
+ `images_extensions.py` and must be installed in the web process and every
64
+ worker. See [docs/worker.md](docs/worker.md) and
65
+ [docs/writing-a-plugin.md](docs/writing-a-plugin.md).
66
+
67
+ ## Usage
68
+
69
+ The console is at `/admin/images`, the JSON API under `/api/images` and public
70
+ collections at `/images/c/{slug}`. Every router binds a tenant: a single-tenant
71
+ host uses `default`, a multi-tenant host the organisation the framework
72
+ resolved (403 `tenant_required` for the console, 404 for public routes when
73
+ none).
74
+
75
+ ### Permissions
76
+
77
+ | Permission | Allows |
78
+ | --- | --- |
79
+ | `images.view` | See collections and images the access policy admits |
80
+ | `images.create` | Create collections and upload images |
81
+ | `images.publish` | Make a collection public or internal |
82
+ | `images.manage` | Manage every collection regardless of owner |
83
+ | `images.originals.view` | Download the immutable original |
84
+
85
+ ### Settings
86
+
87
+ The module's settings are governed by the framework's `settings.edit`, as every
88
+ other module's are; images has no settings permission of its own.
89
+
90
+ Stored in the database and edited on the Settings screen; there is no
91
+ `SM_IMAGES_*` environment variable. System scope: one configuration for every
92
+ tenant. Fields marked as needing a restart (`tippecanoe_path`,
93
+ `public_asset_base_url`) are read once at boot; workers pick up the rest within
94
+ about 30 seconds.
95
+
96
+ | Setting | Default |
97
+ | --- | --- |
98
+ | `max_image_bytes` | 50 MiB |
99
+ | `batch_max` | 50 |
100
+ | `upload_body_max_bytes` | 100 MiB |
101
+ | `direct_upload_threshold` | 20 MiB |
102
+ | `max_open_uploads_per_tenant` | 20 |
103
+ | `zip_max_bytes` / `zip_max_entries` | 2 GiB / 10 000 |
104
+ | `zip_max_entry_bytes` / `zip_max_total_bytes` / `zip_max_ratio` | 200 MiB / 8 GiB / 200 |
105
+ | `geojson_max_features` / `geojson_max_bytes` / `geojson_max_feature_bytes` | 1 000 000 / 2 GiB / 60 MiB |
106
+ | `download_concurrency_per_domain` / `download_concurrency_total` (per download task) / `download_timeout` | 4 / 32 / 60 s |
107
+ | `thumbnail_sizes` | marker 64, small 160, medium 400, large 1024 |
108
+ | `dedupe_by_hash` | off |
109
+ | `tippecanoe_path`, `anonymize_weights_path` | `tippecanoe`, empty |
110
+ | `map_rebuild_threshold_pct` / `map_rebuild_threshold_abs` | 5 / 100 |
111
+ | `map_style_url` (basemap; empty = flat, no third-party request) | `https://tiles.openfreemap.org/styles/positron` |
112
+ | `public_asset_base_url` | empty |
113
+ | `janitor_grace_days`, `step_output_max_bytes`, `step_lease_seconds` | 7, 65 536, 1 800 |
114
+
115
+ ### Routes
116
+
117
+ Upload routes (`/api/images/collections/{id}/images`, `.../imports`,
118
+ `.../imports/zip` and `/api/images/uploads/`) carry a request-body ceiling of
119
+ `upload_body_max_bytes` plus multipart framing; the rest use the host's global
120
+ limit. Public exemptions are `GET`/`HEAD` only, under `/images/c/` and
121
+ `/api/images/public/`.
122
+
123
+ ### Map
124
+
125
+ - `GET /api/images/collections/{id}/points?bbox=minx,miny,maxx,maxy&limit=&cursor=`
126
+ (anonymous twin: `/api/images/public/c/{slug}/points`) answers a GeoJSON
127
+ `FeatureCollection`. Each point carries only `id`, `captured_at` and
128
+ `group_id`; an image whose display mutator has not settled is not a point.
129
+ `limit` is clamped to 5000; follow `next_cursor` for the rest.
130
+ - `GET|HEAD …/collections/{id}/map.pmtiles` (twin: `/api/images/public/c/{slug}/map.pmtiles`)
131
+ serves the collection's PMTiles archive with `Range`, checking access on
132
+ every request. It is a 404 until a map is built.
133
+ - `images.build_map` (queue `images`) builds the archive with `tippecanoe`.
134
+ A rebuild starts once the changes since the last build reach
135
+ `map_rebuild_threshold_abs` or `map_rebuild_threshold_pct` percent of its
136
+ points (both at least 1). A move does not wait for the threshold. A visibility
137
+ change, a removed point (an image trashed or its location cleared) and a
138
+ pipeline save that changes the redaction gate withdraw the archive in the
139
+ same transaction and build a fresh one. An archive is stamped with the
140
+ redaction gate it was built under, and is a 404 under any other (for
141
+ example once a mutator plugin is removed) until `images.reconcile` rebuilds it.
142
+ - The `images.tippecanoe` health check is degraded while the binary cannot be
143
+ found. Points keep working.
144
+ - The points are drawn over the basemap `map_style_url` names (OpenFreeMap's
145
+ Positron by default; its origin is added to the CSP). Viewers' browsers
146
+ fetch its tiles from that host, so it sees their IP and the area they view;
147
+ set it to empty for a flat background with no third-party request. A style
148
+ that cannot be fetched falls back to the flat background.
149
+
150
+ ## Documentation
151
+
152
+ | Page | For |
153
+ | --- | --- |
154
+ | [docs/index.md](docs/index.md) | Concepts, install, permissions, every setting |
155
+ | [docs/access.md](docs/access.md) | Visibility, shares, originals, withheld images |
156
+ | [docs/imports.md](docs/imports.md) | Uploads, direct upload and bucket CORS, ZIP, GeoJSON, limits |
157
+ | [docs/pipeline.md](docs/pipeline.md) | Steps, leases, AI prompts, groups, presets, review, storage metering |
158
+ | [docs/writing-a-plugin.md](docs/writing-a-plugin.md) | Steps, presets and result views from another module |
159
+ | [docs/worker.md](docs/worker.md) | Workers, beat, timeouts, tuning, recovery times |
160
+ | [docs/migrating-from-portal.md](docs/migrating-from-portal.md) | Moving off the portal's feature |