howler-api 4.0.0.dev1308__tar.gz → 4.0.0.dev1337__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 (225) hide show
  1. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/PKG-INFO +2 -2
  2. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/README.md +3 -4
  3. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/collection.py +92 -22
  4. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/external/reindex_data.py +1 -0
  5. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/README.md +5 -2
  6. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/case.py +4 -4
  7. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/random_data.py +5 -1
  8. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/README.md +26 -19
  9. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/pyproject.toml +5 -5
  10. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/README.md +0 -0
  11. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/__init__.py +0 -0
  12. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/__init__.py +0 -0
  13. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/add_label.py +0 -0
  14. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/add_to_bundle.py +0 -0
  15. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/add_to_case.py +0 -0
  16. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/change_field.py +0 -0
  17. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/demote.py +0 -0
  18. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/example_plugin.py +0 -0
  19. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/prioritization.py +0 -0
  20. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/promote.py +0 -0
  21. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/remove_from_bundle.py +0 -0
  22. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/remove_label.py +0 -0
  23. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/actions/transition.py +0 -0
  24. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/__init__.py +0 -0
  25. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/base.py +0 -0
  26. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/socket.py +0 -0
  27. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/__init__.py +0 -0
  28. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/action.py +0 -0
  29. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/analytic.py +0 -0
  30. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/auth.py +0 -0
  31. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/clue.py +0 -0
  32. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/configs.py +0 -0
  33. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/dossier.py +0 -0
  34. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/help.py +0 -0
  35. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/hit.py +0 -0
  36. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/notebook.py +0 -0
  37. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/overview.py +0 -0
  38. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/search.py +0 -0
  39. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/template.py +0 -0
  40. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/tool.py +0 -0
  41. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/user.py +0 -0
  42. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/utils/__init__.py +0 -0
  43. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/utils/etag.py +0 -0
  44. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/utils/params.py +0 -0
  45. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v1/view.py +0 -0
  46. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v2/__init__.py +0 -0
  47. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v2/case.py +0 -0
  48. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v2/fuzzy.py +0 -0
  49. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v2/ingest.py +0 -0
  50. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/api/v2/search.py +0 -0
  51. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/app.py +0 -0
  52. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/README.md +0 -0
  53. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/__init__.py +0 -0
  54. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/classification.py +0 -0
  55. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/classification.yml +0 -0
  56. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/exceptions.py +0 -0
  57. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/loader.py +0 -0
  58. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/logging/__init__.py +0 -0
  59. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/logging/audit.py +0 -0
  60. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/logging/format.py +0 -0
  61. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/net.py +0 -0
  62. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/net_static.py +0 -0
  63. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/random_user.py +0 -0
  64. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/common/swagger.py +0 -0
  65. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/config.py +0 -0
  66. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/cronjobs/__init__.py +0 -0
  67. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/cronjobs/action_queue_worker.py +0 -0
  68. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/cronjobs/correlation.py +0 -0
  69. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/cronjobs/retention.py +0 -0
  70. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/cronjobs/view_cleanup.py +0 -0
  71. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/__init__.py +0 -0
  72. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/bulk.py +0 -0
  73. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/constants.py +0 -0
  74. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/exceptions.py +0 -0
  75. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/howler_store.py +0 -0
  76. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/migrations/fix_process.py +0 -0
  77. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/operations.py +0 -0
  78. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/schemas.py +0 -0
  79. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/store.py +0 -0
  80. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/support/__init__.py +0 -0
  81. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/support/build.py +0 -0
  82. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/support/schemas.py +0 -0
  83. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/datastore/types.py +0 -0
  84. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/error.py +0 -0
  85. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/external/README.md +0 -0
  86. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/external/__init__.py +0 -0
  87. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/external/generate_mitre.py +0 -0
  88. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/external/generate_sigma_rules.py +0 -0
  89. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/external/generate_tlds.py +0 -0
  90. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/external/wipe_databases.py +0 -0
  91. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/gunicorn_config.py +0 -0
  92. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/healthz.py +0 -0
  93. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/__init__.py +0 -0
  94. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/azure.py +0 -0
  95. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/discover.py +0 -0
  96. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/hit.py +0 -0
  97. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/oauth.py +0 -0
  98. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/search.py +0 -0
  99. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/workflow.py +0 -0
  100. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/helper/ws.py +0 -0
  101. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/__init__.py +0 -0
  102. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/base.py +0 -0
  103. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/charter.txt +0 -0
  104. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/constants.py +0 -0
  105. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/helper.py +0 -0
  106. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/howler_enum.py +0 -0
  107. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/mixins.py +0 -0
  108. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/__init__.py +0 -0
  109. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/action.py +0 -0
  110. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/analytic.py +0 -0
  111. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/assemblyline.py +0 -0
  112. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/aws.py +0 -0
  113. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/azure.py +0 -0
  114. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/cbs.py +0 -0
  115. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/clue.py +0 -0
  116. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/config.py +0 -0
  117. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/dossier.py +0 -0
  118. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/__init__.py +0 -0
  119. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/agent.py +0 -0
  120. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/autonomous_system.py +0 -0
  121. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/client.py +0 -0
  122. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/cloud.py +0 -0
  123. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/code_signature.py +0 -0
  124. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/container.py +0 -0
  125. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/dns.py +0 -0
  126. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/egress.py +0 -0
  127. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/elf.py +0 -0
  128. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/email.py +0 -0
  129. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/error.py +0 -0
  130. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/event.py +0 -0
  131. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/faas.py +0 -0
  132. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/file.py +0 -0
  133. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/geo.py +0 -0
  134. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/group.py +0 -0
  135. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/hash.py +0 -0
  136. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/host.py +0 -0
  137. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/http.py +0 -0
  138. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/ingress.py +0 -0
  139. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/interface.py +0 -0
  140. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/network.py +0 -0
  141. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/observer.py +0 -0
  142. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/organization.py +0 -0
  143. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/os.py +0 -0
  144. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/pe.py +0 -0
  145. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/process.py +0 -0
  146. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/registry.py +0 -0
  147. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/related.py +0 -0
  148. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/rule.py +0 -0
  149. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/server.py +0 -0
  150. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/threat.py +0 -0
  151. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/tls.py +0 -0
  152. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/url.py +0 -0
  153. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/user.py +0 -0
  154. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/user_agent.py +0 -0
  155. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/ecs/vulnerability.py +0 -0
  156. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/event.py +0 -0
  157. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/gcp.py +0 -0
  158. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/hit.py +0 -0
  159. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/howler_data.py +0 -0
  160. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/lead.py +0 -0
  161. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/localized_label.py +0 -0
  162. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/overview.py +0 -0
  163. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/pivot.py +0 -0
  164. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/record.py +0 -0
  165. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/template.py +0 -0
  166. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/user.py +0 -0
  167. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/models/view.py +0 -0
  168. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/odm/randomizer.py +0 -0
  169. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/patched.py +0 -0
  170. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/plugins/__init__.py +0 -0
  171. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/plugins/config.py +0 -0
  172. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/__init__.py +0 -0
  173. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/__init__.py +0 -0
  174. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/counters.py +0 -0
  175. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/events.py +0 -0
  176. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/hash.py +0 -0
  177. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/lock.py +0 -0
  178. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/queues/__init__.py +0 -0
  179. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/queues/comms.py +0 -0
  180. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/queues/multi.py +0 -0
  181. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/queues/named.py +0 -0
  182. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/queues/priority.py +0 -0
  183. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/set.py +0 -0
  184. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  185. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/security/__init__.py +0 -0
  186. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/security/socket.py +0 -0
  187. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/security/utils.py +0 -0
  188. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/__init__.py +0 -0
  189. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/action_service.py +0 -0
  190. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/analytic_service.py +0 -0
  191. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/auth_service.py +0 -0
  192. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/bundle_compat_service.py +0 -0
  193. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/case_service.py +0 -0
  194. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/comms_service.py +0 -0
  195. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/config_service.py +0 -0
  196. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/correlation_service.py +0 -0
  197. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/docs_service.py +0 -0
  198. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/dossier_service.py +0 -0
  199. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/event_service.py +0 -0
  200. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/fuzzy_service.py +0 -0
  201. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/hit_service.py +0 -0
  202. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/jwt_service.py +0 -0
  203. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/lucene_service.py +0 -0
  204. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/notebook_service.py +0 -0
  205. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/overview_service.py +0 -0
  206. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/search_service.py +0 -0
  207. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/template_service.py +0 -0
  208. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/user_service.py +0 -0
  209. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/services/viewer_service.py +0 -0
  210. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/telemetry.py +0 -0
  211. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/__init__.py +0 -0
  212. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/annotations.py +0 -0
  213. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/chunk.py +0 -0
  214. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/compat.py +0 -0
  215. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/constants.py +0 -0
  216. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/dict_utils.py +0 -0
  217. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/indexes.py +0 -0
  218. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/isotime.py +0 -0
  219. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/list_utils.py +0 -0
  220. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/lucene.py +0 -0
  221. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/net_utils.py +0 -0
  222. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/path.py +0 -0
  223. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/socket_utils.py +0 -0
  224. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/str_utils.py +0 -0
  225. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1337}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howler-api
3
- Version: 4.0.0.dev1308
3
+ Version: 4.0.0.dev1337
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -38,7 +38,7 @@ Requires-Dist: opentelemetry-instrumentation-flask (==0.61b0)
38
38
  Requires-Dist: opentelemetry-sdk (==1.40.0)
39
39
  Requires-Dist: packaging (<25.0)
40
40
  Requires-Dist: passlib (==1.7.4)
41
- Requires-Dist: prometheus-client (==0.25.0)
41
+ Requires-Dist: prometheus-client (==0.26.0)
42
42
  Requires-Dist: pydantic (>=2.11.4,<3.0.0)
43
43
  Requires-Dist: pydantic-settings[yaml] (>=2.9.1,<3.0.0)
44
44
  Requires-Dist: pydash (>=8.0.5,<9.0.0)
@@ -37,10 +37,9 @@ from howler.common import loader
37
37
  from myapp.models.mymodel import MyModel
38
38
 
39
39
  ds = loader.get_esstore()
40
- ds.register('mymodel', MyModel)
40
+ ds.register("mymodel", MyModel)
41
41
 
42
42
  my_document = ds.mymodel.get(document_id)
43
-
44
43
  ```
45
44
 
46
45
  ### Creating your own datastore
@@ -59,10 +58,10 @@ from myapp.models.mycollection import MyCollection
59
58
 
60
59
 
61
60
  class MyDatastore(object):
62
- def __init__(self, esstore_object: ESStore = None ):
61
+ def __init__(self, esstore_object: ESStore = None):
63
62
 
64
63
  self.ds = esstore_object or loader.get_esstore()
65
- self.ds.register('mycollection', MyCollection)
64
+ self.ds.register("mycollection", MyCollection)
66
65
  # ... + all other collections
67
66
 
68
67
  def __enter__(self):
@@ -252,19 +252,50 @@ class ESCollection(Generic[ModelType]):
252
252
 
253
253
  @property
254
254
  def index_list_full(self):
255
+ """Return every physical index for this collection, newest ILM index first.
256
+
257
+ Maintenance operations that must visit historical rollover indexes should use this
258
+ property. The active index is included even when no ILM rollover index exists.
259
+ """
255
260
  if not self._index_list:
256
- self._index_list = list(self.with_retries(self.datastore.client.indices.get, index=f"{self.name}-*").keys())
261
+ self._index_list = self._get_ilm_index_names()
257
262
 
258
- return [self.index_name] + sorted(self._index_list, reverse=True)
263
+ return list(dict.fromkeys([self.index_name, *sorted(self._index_list, reverse=True)]))
259
264
 
260
265
  @property
261
266
  def index_list(self):
262
- """This property contains the list of valid indexes for the current collection.
267
+ """Return the active physical write index for this collection.
263
268
 
264
- :return: list of valid indexes for this collection
269
+ Historical ILM rollover indexes are intentionally excluded. Bulk plans use this
270
+ list for default write, update, and delete targets, and widening it would fan those
271
+ operations out across historical indexes.
265
272
  """
266
273
  return [self.index_name]
267
274
 
275
+ def _get_ilm_index_names(self) -> list[str]:
276
+ """Return physical ILM rollover indexes, excluding temporary maintenance indexes."""
277
+ try:
278
+ indices = self.datastore.client.indices.get(
279
+ index=f"{self.name}-0*",
280
+ ignore_unavailable=True,
281
+ )
282
+ except elasticsearch.exceptions.NotFoundError:
283
+ return []
284
+
285
+ index_pattern = re.compile(rf"^{re.escape(self.name)}-\d{{6}}$")
286
+ return sorted(index for index in indices if index_pattern.fullmatch(index))
287
+
288
+ def _refresh_ilm_index_name(self):
289
+ """Set ``index_name`` to the latest existing ILM index, when one exists."""
290
+ if not self.ilm_config:
291
+ return
292
+
293
+ ilm_indices = self._get_ilm_index_names()
294
+
295
+ if ilm_indices:
296
+ self._index_list = ilm_indices
297
+ self.index_name = ilm_indices[-1]
298
+
268
299
  def scan_with_retry(
269
300
  self,
270
301
  query,
@@ -730,7 +761,7 @@ class ESCollection(Generic[ModelType]):
730
761
  def reindex(self, allow_failures: bool = False, request_timeout: int = 60):
731
762
  """Reindex all the data of the collection into a freshly mapped index.
732
763
 
733
- For every index in ``self.index_list`` the data is copied into a temporary
764
+ For every physical index in ``self.index_list_full`` the data is copied into a temporary
734
765
  ``__reindex`` index that uses the current mappings/settings. Writes to the source
735
766
  index are blocked while the copy runs so the reindex result and document counts can
736
767
  be validated before the original index is deleted. The temporary index is only
@@ -750,7 +781,8 @@ class ESCollection(Generic[ModelType]):
750
781
  operation can be recovered with :meth:`reindex_cleanup`.
751
782
  """
752
783
  logger.warning("Beginning Reindex")
753
- for index in self.index_list:
784
+ self._refresh_ilm_index_name()
785
+ for index in self.index_list_full:
754
786
  new_name = f"{index}__reindex"
755
787
  index_data = None
756
788
  source_count = None
@@ -798,7 +830,7 @@ class ESCollection(Generic[ModelType]):
798
830
  self.datastore.client.indices.create,
799
831
  index=new_name,
800
832
  mappings=self._get_index_mappings(),
801
- settings=self._get_index_settings(),
833
+ settings=self._get_reindex_settings(index_data),
802
834
  )
803
835
 
804
836
  # Reindex data into target
@@ -847,12 +879,10 @@ class ESCollection(Generic[ModelType]):
847
879
  )
848
880
 
849
881
  alias_actions = []
850
- aliases = index_data.get("aliases", {}) or {self.name: {"is_write_index": True}}
882
+ aliases = index_data.get("aliases", {})
851
883
  for alias, alias_data in aliases.items():
852
884
  alias_action = {"index": index, "alias": alias}
853
885
  alias_action.update(alias_data)
854
- if alias == self.name or alias_data.get("is_write_index", False):
855
- alias_action["is_write_index"] = True
856
886
  alias_actions.append({"add": alias_action})
857
887
  alias_actions.append({"remove_index": {"index": new_name}})
858
888
  self.with_retries(self.datastore.client.indices.update_aliases, actions=alias_actions)
@@ -880,6 +910,14 @@ class ESCollection(Generic[ModelType]):
880
910
 
881
911
  return True
882
912
 
913
+ def _get_reindex_settings(self, index_data: dict) -> dict:
914
+ """Build settings for a reindex target without dropping ILM lifecycle metadata."""
915
+ settings = self._get_index_settings()
916
+ lifecycle = index_data.get("settings", {}).get("index", {}).get("lifecycle")
917
+ if lifecycle:
918
+ settings["index"]["lifecycle"] = deepcopy(lifecycle)
919
+ return settings
920
+
883
921
  def _validate_reindex_result(self, index, new_name, reindex_result, allow_failures):
884
922
  """Validate the result of an Elasticsearch reindex task.
885
923
 
@@ -956,17 +994,18 @@ class ESCollection(Generic[ModelType]):
956
994
  def reindex_cleanup(self):
957
995
  """Recover from a failed or interrupted :meth:`reindex` run.
958
996
 
959
- For every index that still has a leftover ``__reindex`` index, restore the source
960
- index as the writable target and delete the orphaned ``__reindex`` index. If the
961
- source index is missing, raise an error instead of deleting ``__reindex`` because
962
- it may be the only remaining copy of the data.
997
+ For every physical index that still has a leftover ``__reindex`` index, restore the source
998
+ index's original aliases and delete the orphaned ``__reindex`` index. If the source
999
+ index is missing, raise an error instead of deleting ``__reindex`` because it may
1000
+ be the only remaining copy of the data.
963
1001
 
964
1002
  Write blocks set during reindexing are cleared so the collection is usable again.
965
1003
 
966
1004
  :return: ``True`` when cleanup completed on all indexes
967
1005
  """
968
1006
  logger.warning("Beginning reindex cleanup")
969
- for index in self.index_list:
1007
+ self._refresh_ilm_index_name()
1008
+ for index in self.index_list_full:
970
1009
  new_name = f"{index}__reindex"
971
1010
 
972
1011
  if not self.with_retries(self.datastore.client.indices.exists, index=new_name):
@@ -987,17 +1026,13 @@ class ESCollection(Generic[ModelType]):
987
1026
  reindex_aliases = new_index_data.get("aliases", {})
988
1027
 
989
1028
  alias_actions = []
990
- for alias in sorted(set(source_aliases) | set(reindex_aliases) | {self.name}):
1029
+ for alias in sorted(set(source_aliases) | set(reindex_aliases)):
991
1030
  source_alias_data = source_aliases.get(alias, {})
992
1031
  reindex_alias_data = reindex_aliases.get(alias, {})
993
1032
 
994
1033
  add_alias_data = {"index": index, "alias": alias}
995
1034
  add_alias_data.update(source_alias_data)
996
- if (
997
- alias == self.name
998
- or source_alias_data.get("is_write_index", False)
999
- or reindex_alias_data.get("is_write_index", False)
1000
- ):
1035
+ if source_alias_data.get("is_write_index", False) or reindex_alias_data.get("is_write_index", False):
1001
1036
  add_alias_data["is_write_index"] = True
1002
1037
 
1003
1038
  alias_actions.append({"add": add_alias_data})
@@ -2905,7 +2940,42 @@ class ESCollection(Generic[ModelType]):
2905
2940
  if existing_ilm_indices:
2906
2941
  # ILM already bootstrapped — ensure the alias exists
2907
2942
  latest = sorted(existing_ilm_indices)[-1]
2908
- if not self.with_retries(self.datastore.client.indices.exists_alias, name=self.name):
2943
+ legacy_hot_index = f"{self.name}_hot"
2944
+ if self.with_retries(self.datastore.client.indices.exists_alias, name=self.name):
2945
+ alias_indices = self.with_retries(self.datastore.client.indices.get_alias, name=self.name)
2946
+ alias_actions = []
2947
+ for alias_index, alias_index_data in alias_indices.items():
2948
+ alias_data = alias_index_data.get("aliases", {}).get(self.name, {})
2949
+ if alias_index == legacy_hot_index:
2950
+ alias_actions.append({"remove": {"index": alias_index, "alias": self.name}})
2951
+ elif alias_index != latest and alias_data.get("is_write_index", False):
2952
+ alias_actions.append(
2953
+ {
2954
+ "add": {
2955
+ "index": alias_index,
2956
+ "alias": self.name,
2957
+ **alias_data,
2958
+ "is_write_index": False,
2959
+ }
2960
+ }
2961
+ )
2962
+
2963
+ latest_alias_data = alias_indices.get(latest, {}).get("aliases", {}).get(self.name, {})
2964
+ if not latest_alias_data.get("is_write_index", False):
2965
+ alias_actions.append(
2966
+ {
2967
+ "add": {
2968
+ "index": latest,
2969
+ "alias": self.name,
2970
+ **latest_alias_data,
2971
+ "is_write_index": True,
2972
+ }
2973
+ }
2974
+ )
2975
+
2976
+ if alias_actions:
2977
+ self.with_retries(self.datastore.client.indices.update_aliases, actions=alias_actions)
2978
+ else:
2909
2979
  # Find the latest index to set as write index
2910
2980
  self.with_retries(
2911
2981
  self.datastore.client.indices.put_alias,
@@ -99,6 +99,7 @@ if __name__ == "__main__":
99
99
 
100
100
  for index_name in selected:
101
101
  collection: ESCollection = getattr(ds, index_name)
102
+ collection._refresh_ilm_index_name()
102
103
 
103
104
  if args.verbose:
104
105
  print(f"Index schema for '{index_name}':")
@@ -11,15 +11,18 @@ Here's example of a user model with settings and stats:
11
11
  ```python
12
12
  from howler import odm
13
13
 
14
+
14
15
  @odm.model(index=True, store=False, description="Settings of user")
15
16
  class Settings(odm.Model):
16
- default_view: str = odm.Enum(value=['detail', 'simple'], default='simple', description="Some random setting")
17
+ default_view: str = odm.Enum(value=["detail", "simple"], default="simple", description="Some random setting")
18
+
17
19
 
18
20
  @odm.model(index=True, store=False, description="Settings of user")
19
21
  class Stats(odm.Model):
20
- last_login: str = odm.Date(default='NOW', description="Last time user logged in")
22
+ last_login: str = odm.Date(default="NOW", description="Last time user logged in")
21
23
  login_count: str = odm.Integer(default=0, description="Number of time the user logged in")
22
24
 
25
+
23
26
  @odm.model(index=True, store=True, description="User example")
24
27
  class User(odm.Model):
25
28
  username: str = odm.Keyword(description="Username of the user")
@@ -153,17 +153,17 @@ class CaseTask(odm.Model):
153
153
  item: str = odm.Keyword(description="Associated case item id.", optional=True)
154
154
 
155
155
 
156
- @odm.model(index=True, store=True, description="Enrichment annotations associated with a case path.")
156
+ @odm.model(index=True, store=True, description="Enrichment annotations associated with a case item id.")
157
157
  class CaseEnrichment(odm.Model):
158
- path: str = odm.Keyword(description="Case item path associated with these annotations.")
158
+ item: str = odm.Keyword(description="Case item id associated with these annotations.")
159
159
  annotations: list[str] = odm.List(
160
160
  odm.Keyword(),
161
161
  default=[],
162
- description="Annotation IDs associated with the path.",
162
+ description="Annotation IDs associated with the case item id.",
163
163
  )
164
164
 
165
165
 
166
- @odm.model(index=True, store=True, description="Case model with path-based items, enrichments, rules, and tasks.")
166
+ @odm.model(index=True, store=True, description="Case model with items, enrichments, rules, and tasks.")
167
167
  class Case(DatastoreMixin["Case"], odm.Model):
168
168
  case_id: str = odm.UUID(description="A unique identifier for this case.")
169
169
  classification: str = odm.Classification(
@@ -867,8 +867,12 @@ def wipe_actions(ds: HowlerDatastore):
867
867
  def create_dossiers(ds: HowlerDatastore, num_dossiers: int = 5):
868
868
  "Create random dossiers"
869
869
  users = ds.user.search("*:*")["items"]
870
- for _ in range(num_dossiers):
870
+ for index in range(num_dossiers):
871
871
  dossier = generate_useful_dossier(users)
872
+ if index == 0:
873
+ dossier.type = "personal"
874
+ elif index == 1:
875
+ dossier.type = "global"
872
876
  ds.dossier.save(dossier.dossier_id, dossier)
873
877
 
874
878
  ds.dossier.commit()
@@ -25,9 +25,10 @@ Example:
25
25
 
26
26
  ```python
27
27
  from howler.remote.datatypes.counters import Counters
28
- with Counters('test-counter') as ct:
28
+
29
+ with Counters("test-counter") as ct:
29
30
  # Increment counter by 4
30
- ct.inc('value_1', 4)
31
+ ct.inc("value_1", 4)
31
32
 
32
33
  # Get Counter values
33
34
  ct.get_queues_sizes()
@@ -60,19 +61,20 @@ Example, A container register a watcher for a specific event:
60
61
  import time
61
62
  from howler.remote.datatypes.events import EventWatcher
62
63
 
64
+
63
65
  def callback_func(data: dict[str, Any]):
64
66
  print(data)
65
67
 
68
+
66
69
  watcher = EventWatcher()
67
70
  try:
68
71
  # register for the test event in the event group
69
- watcher.register('event.test', callback_func)
72
+ watcher.register("event.test", callback_func)
70
73
  watcher.start()
71
74
  while True:
72
75
  time.sleep(1)
73
76
  finally:
74
77
  watcher.stop()
75
-
76
78
  ```
77
79
 
78
80
  Another container creates an event to wake up the first container:
@@ -82,10 +84,10 @@ import time
82
84
  from howler.remote.datatypes.events import EventSender
83
85
 
84
86
  # create a sender for the event group
85
- sender = EventSender('event.', redis_connection)
87
+ sender = EventSender("event.", redis_connection)
86
88
 
87
89
  # send a test even
88
- sender.send('test', {'payload': 100})
90
+ sender.send("test", {"payload": 100})
89
91
  # After this call, the first container will have woken up and executed its callback function
90
92
  # that would print: {'payload': 100}
91
93
  ```
@@ -114,7 +116,8 @@ Example:
114
116
 
115
117
  ```python
116
118
  from howler.remote.datatypes.hash import Hash
117
- with Hash('test-hashmap') as h:
119
+
120
+ with Hash("test-hashmap") as h:
118
121
  h.add("key", "value")
119
122
  print(h.exists("key"))
120
123
  print(h.get("key"))
@@ -172,10 +175,11 @@ Example:
172
175
 
173
176
  ```python
174
177
  from howler.remote.datatypes.set import Set
175
- with Set('test-set') as s:
176
- values = ['a', 'b', 1, 2]
178
+
179
+ with Set("test-set") as s:
180
+ values = ["a", "b", 1, 2]
177
181
  s.add(*values)
178
- print(s.exist('b'))
182
+ print(s.exist("b"))
179
183
  print(s.pop())
180
184
  print(s.length())
181
185
  ```
@@ -184,7 +188,7 @@ Output:
184
188
 
185
189
  ```python
186
190
  True
187
- 'a' or 'b' or 1 or 2
191
+ "a" or "b" or 1 or 2
188
192
  3
189
193
  ```
190
194
 
@@ -234,7 +238,7 @@ Example of message receiver:
234
238
  ```python
235
239
  from howler.remote.datatypes.queues.comms import CommsQueue
236
240
 
237
- with CommsQueue('test-comms-queue') as cq:
241
+ with CommsQueue("test-comms-queue") as cq:
238
242
  for msg in cq.listen(blocking=True):
239
243
  if msg == "stop":
240
244
  break
@@ -247,7 +251,7 @@ Example of message sender:
247
251
  ```python
248
252
  from howler.remote.datatypes.queues.comms import CommsQueue
249
253
 
250
- with CommsQueue('test-comms-queue') as cq:
254
+ with CommsQueue("test-comms-queue") as cq:
251
255
  # send a message to the receiver
252
256
  cq.publish("This is my message!")
253
257
 
@@ -273,7 +277,8 @@ Example:
273
277
 
274
278
  ```python
275
279
  from howler.remote.datatypes.queues.named import NamedQueue, select
276
- with NamedQueue('test-named-queue') as nq:
280
+
281
+ with NamedQueue("test-named-queue") as nq:
277
282
  for x in range(5):
278
283
  nq.push(x)
279
284
 
@@ -307,12 +312,13 @@ Example:
307
312
 
308
313
  ```python
309
314
  from howler.remote.datatypes.queues.priority import PriorityQueue, length, select
310
- with PriorityQueue('test-priority-queue') as pq:
315
+
316
+ with PriorityQueue("test-priority-queue") as pq:
311
317
  for x in range(10):
312
318
  pq.push(100, x)
313
319
 
314
- a_key = pq.push(101, 'a')
315
- z_key = pq.push(99, 'z')
320
+ a_key = pq.push(101, "a")
321
+ z_key = pq.push(99, "z")
316
322
  print(pq.rank(a_key))
317
323
  print(pq.rank(z_key))
318
324
  print(pq.pop())
@@ -323,7 +329,7 @@ Output:
323
329
  ```python
324
330
  0
325
331
  11
326
- 'a'
332
+ "a"
327
333
  ```
328
334
 
329
335
  #### Unique Priority queues
@@ -334,7 +340,8 @@ Example:
334
340
 
335
341
  ```python
336
342
  from howler.remote.datatypes.queues.priority import PriorityQueue, length, select
337
- with PriorityQueue('test-priority-queue') as pq:
343
+
344
+ with PriorityQueue("test-priority-queue") as pq:
338
345
  for x in range(10):
339
346
  pq.push(100, x)
340
347
 
@@ -152,7 +152,7 @@ suppress-none-returning = true
152
152
  [tool.poetry]
153
153
  package-mode = true
154
154
  name = "howler-api"
155
- version = "4.0.0.dev1308"
155
+ version = "4.0.0.dev1337"
156
156
  description = "Howler - API server"
157
157
  authors = [
158
158
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",
@@ -206,7 +206,7 @@ gevent = "^25.9.1"
206
206
  flask-caching = "2.4.1"
207
207
  packaging = "<25.0"
208
208
  passlib = "1.7.4"
209
- prometheus-client = "0.25.0"
209
+ prometheus-client = "0.26.0"
210
210
  pyjwt = "2.13.0"
211
211
  python-baseconv = "1.2.2"
212
212
  python-datemath = "3.0.3"
@@ -235,7 +235,7 @@ azure-monitor-opentelemetry = "^1.8.7"
235
235
 
236
236
  [tool.poetry.group.dev.dependencies]
237
237
  pre-commit = "^3.7.0"
238
- ruff = ">=0.8,<0.16"
238
+ ruff = ">=0.8,<0.17"
239
239
  pyright = { extras = ["nodejs"], version = "^1.1.408" }
240
240
  mypy = "^1.6.1"
241
241
 
@@ -252,10 +252,10 @@ coverage = { extras = ["toml"], version = "^7.4.4" }
252
252
 
253
253
  [tool.poetry.group.types.dependencies]
254
254
  typing-extensions = "^4.12.2"
255
- types-PyYAML = "6.0.12.20260518"
255
+ types-PyYAML = "6.0.12.20260724"
256
256
  types-paramiko = "3.5.0.20250801"
257
257
  types-pyOpenSSL = "23.3.0.20240106"
258
- types-six = "1.17.0.20260721"
258
+ types-six = "1.17.0.20260724"
259
259
  types-requests = "<2.33.0.20260713"
260
260
  websocket-client = "1.9.0"
261
261
  types-pytz = "^2024.1.0.20240417"