howler-api 3.4.0.dev834__tar.gz → 3.4.0.dev845__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 (202) hide show
  1. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/PKG-INFO +1 -1
  2. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/base.py +80 -21
  3. howler_api-3.4.0.dev845/howler/utils/compat.py +27 -0
  4. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/pyproject.toml +1 -1
  5. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/README.md +0 -0
  6. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/__init__.py +0 -0
  7. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/__init__.py +0 -0
  8. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/add_label.py +0 -0
  9. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/add_to_bundle.py +0 -0
  10. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/change_field.py +0 -0
  11. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/demote.py +0 -0
  12. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/example_plugin.py +0 -0
  13. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/prioritization.py +0 -0
  14. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/promote.py +0 -0
  15. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/remove_from_bundle.py +0 -0
  16. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/remove_label.py +0 -0
  17. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/actions/transition.py +0 -0
  18. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/__init__.py +0 -0
  19. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/base.py +0 -0
  20. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/socket.py +0 -0
  21. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/__init__.py +0 -0
  22. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/action.py +0 -0
  23. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/analytic.py +0 -0
  24. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/auth.py +0 -0
  25. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/clue.py +0 -0
  26. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/configs.py +0 -0
  27. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/dossier.py +0 -0
  28. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/help.py +0 -0
  29. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/hit.py +0 -0
  30. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/notebook.py +0 -0
  31. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/overview.py +0 -0
  32. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/search.py +0 -0
  33. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/template.py +0 -0
  34. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/tool.py +0 -0
  35. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/user.py +0 -0
  36. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/utils/__init__.py +0 -0
  37. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/utils/etag.py +0 -0
  38. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/api/v1/view.py +0 -0
  39. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/app.py +0 -0
  40. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/README.md +0 -0
  41. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/__init__.py +0 -0
  42. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/classification.py +0 -0
  43. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/classification.yml +0 -0
  44. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/exceptions.py +0 -0
  45. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/loader.py +0 -0
  46. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/logging/__init__.py +0 -0
  47. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/logging/audit.py +0 -0
  48. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/logging/format.py +0 -0
  49. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/net.py +0 -0
  50. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/net_static.py +0 -0
  51. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/random_user.py +0 -0
  52. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/common/swagger.py +0 -0
  53. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/config.py +0 -0
  54. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/cronjobs/__init__.py +0 -0
  55. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/cronjobs/retention.py +0 -0
  56. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/cronjobs/rules.py +0 -0
  57. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/cronjobs/view_cleanup.py +0 -0
  58. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/README.md +0 -0
  59. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/__init__.py +0 -0
  60. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/bulk.py +0 -0
  61. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/collection.py +0 -0
  62. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/constants.py +0 -0
  63. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/exceptions.py +0 -0
  64. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/howler_store.py +0 -0
  65. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/migrations/fix_process.py +0 -0
  66. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/operations.py +0 -0
  67. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/schemas.py +0 -0
  68. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/store.py +0 -0
  69. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/support/__init__.py +0 -0
  70. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/support/build.py +0 -0
  71. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/support/schemas.py +0 -0
  72. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/datastore/types.py +0 -0
  73. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/error.py +0 -0
  74. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/external/README.md +0 -0
  75. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/external/__init__.py +0 -0
  76. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/external/generate_mitre.py +0 -0
  77. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/external/generate_sigma_rules.py +0 -0
  78. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/external/generate_tlds.py +0 -0
  79. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/external/reindex_data.py +0 -0
  80. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/external/wipe_databases.py +0 -0
  81. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/gunicorn_config.py +0 -0
  82. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/healthz.py +0 -0
  83. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/__init__.py +0 -0
  84. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/azure.py +0 -0
  85. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/discover.py +0 -0
  86. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/hit.py +0 -0
  87. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/oauth.py +0 -0
  88. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/search.py +0 -0
  89. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/workflow.py +0 -0
  90. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/helper/ws.py +0 -0
  91. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/README.md +0 -0
  92. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/__init__.py +0 -0
  93. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/charter.txt +0 -0
  94. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/helper.py +0 -0
  95. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/howler_enum.py +0 -0
  96. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/__init__.py +0 -0
  97. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/action.py +0 -0
  98. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/analytic.py +0 -0
  99. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/assemblyline.py +0 -0
  100. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/aws.py +0 -0
  101. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/azure.py +0 -0
  102. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/cbs.py +0 -0
  103. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/clue.py +0 -0
  104. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/config.py +0 -0
  105. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/dossier.py +0 -0
  106. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/__init__.py +0 -0
  107. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/agent.py +0 -0
  108. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/autonomous_system.py +0 -0
  109. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/client.py +0 -0
  110. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/cloud.py +0 -0
  111. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/code_signature.py +0 -0
  112. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/container.py +0 -0
  113. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/dns.py +0 -0
  114. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/egress.py +0 -0
  115. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/elf.py +0 -0
  116. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/email.py +0 -0
  117. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/error.py +0 -0
  118. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/event.py +0 -0
  119. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/faas.py +0 -0
  120. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/file.py +0 -0
  121. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/geo.py +0 -0
  122. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/group.py +0 -0
  123. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/hash.py +0 -0
  124. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/host.py +0 -0
  125. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/http.py +0 -0
  126. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/ingress.py +0 -0
  127. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/interface.py +0 -0
  128. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/network.py +0 -0
  129. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/observer.py +0 -0
  130. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/organization.py +0 -0
  131. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/os.py +0 -0
  132. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/pe.py +0 -0
  133. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/process.py +0 -0
  134. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/registry.py +0 -0
  135. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/related.py +0 -0
  136. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/rule.py +0 -0
  137. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/server.py +0 -0
  138. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/threat.py +0 -0
  139. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/tls.py +0 -0
  140. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/url.py +0 -0
  141. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/user.py +0 -0
  142. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/user_agent.py +0 -0
  143. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/ecs/vulnerability.py +0 -0
  144. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/gcp.py +0 -0
  145. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/hit.py +0 -0
  146. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/howler_data.py +0 -0
  147. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/lead.py +0 -0
  148. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/localized_label.py +0 -0
  149. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/overview.py +0 -0
  150. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/pivot.py +0 -0
  151. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/template.py +0 -0
  152. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/user.py +0 -0
  153. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/models/view.py +0 -0
  154. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/random_data.py +0 -0
  155. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/odm/randomizer.py +0 -0
  156. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/patched.py +0 -0
  157. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/plugins/__init__.py +0 -0
  158. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/plugins/config.py +0 -0
  159. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/__init__.py +0 -0
  160. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/README.md +0 -0
  161. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/__init__.py +0 -0
  162. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/counters.py +0 -0
  163. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/events.py +0 -0
  164. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/hash.py +0 -0
  165. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/lock.py +0 -0
  166. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/queues/__init__.py +0 -0
  167. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/queues/comms.py +0 -0
  168. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/queues/multi.py +0 -0
  169. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/queues/named.py +0 -0
  170. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/queues/priority.py +0 -0
  171. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/set.py +0 -0
  172. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  173. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/security/__init__.py +0 -0
  174. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/security/socket.py +0 -0
  175. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/security/utils.py +0 -0
  176. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/__init__.py +0 -0
  177. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/action_service.py +0 -0
  178. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/analytic_service.py +0 -0
  179. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/auth_service.py +0 -0
  180. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/config_service.py +0 -0
  181. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/dossier_service.py +0 -0
  182. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/event_service.py +0 -0
  183. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/hit_service.py +0 -0
  184. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/jwt_service.py +0 -0
  185. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/lucene_service.py +0 -0
  186. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/notebook_service.py +0 -0
  187. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/overview_service.py +0 -0
  188. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/template_service.py +0 -0
  189. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/services/user_service.py +0 -0
  190. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/telemetry.py +0 -0
  191. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/__init__.py +0 -0
  192. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/annotations.py +0 -0
  193. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/chunk.py +0 -0
  194. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/constants.py +0 -0
  195. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/dict_utils.py +0 -0
  196. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/isotime.py +0 -0
  197. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/list_utils.py +0 -0
  198. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/lucene.py +0 -0
  199. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/path.py +0 -0
  200. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/socket_utils.py +0 -0
  201. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/str_utils.py +0 -0
  202. {howler_api-3.4.0.dev834 → howler_api-3.4.0.dev845}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howler-api
3
- Version: 3.4.0.dev834
3
+ Version: 3.4.0.dev845
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -19,7 +19,7 @@ from datetime import datetime
19
19
  from enum import Enum as PyEnum
20
20
  from enum import EnumMeta
21
21
  from typing import Any as _Any
22
- from typing import Dict, Union
22
+ from typing import Callable
23
23
  from venv import logger
24
24
 
25
25
  import arrow
@@ -29,6 +29,8 @@ from dateutil.tz import tzutc
29
29
  from howler.common import loader
30
30
  from howler.common.exceptions import HowlerKeyError, HowlerNotImplementedError, HowlerTypeError, HowlerValueError
31
31
  from howler.common.net import is_valid_domain, is_valid_ip
32
+ from howler.odm.howler_enum import HowlerEnum
33
+ from howler.utils.compat import StrEnum as PyStrEnum
32
34
  from howler.utils.dict_utils import flatten, recursive_update
33
35
  from howler.utils.isotime import now_as_iso
34
36
  from howler.utils.uid import get_random_id
@@ -549,15 +551,23 @@ class Processor(ValidatedKeyword):
549
551
 
550
552
 
551
553
  class Enum(Keyword):
552
- """A field storing a short string that has predefined list of possible values"""
554
+ """A field storing a short string that has predefined list of possible values.
553
555
 
554
- def __init__(self, values: PyEnum | list[typing.Any] | set[typing.Any], *args, **kwargs):
556
+ Accepts values from lists/sets, Enum classes, and StrEnum (PyStrEnum) members.
557
+ """
558
+
559
+ def __init__(
560
+ self,
561
+ values: type[HowlerEnum] | type[PyEnum] | type[PyStrEnum] | list[typing.Any] | set[typing.Any],
562
+ *args,
563
+ **kwargs,
564
+ ):
555
565
  super().__init__(*args, **kwargs)
556
566
  if isinstance(values, set):
557
567
  self.values = values
558
568
  elif isinstance(values, (list, tuple)):
559
569
  self.values = set(values)
560
- elif isinstance(values, (PyEnum, EnumMeta)):
570
+ elif isinstance(values, (PyEnum, PyStrEnum, EnumMeta)):
561
571
  self.values = set([e.value for e in values]) # type: ignore
562
572
  else:
563
573
  raise HowlerTypeError(f"Type unsupported for Enum odm: {type(values)}")
@@ -1063,7 +1073,7 @@ class Optional(_Field):
1063
1073
 
1064
1074
  class Model:
1065
1075
  @classmethod
1066
- def fields(cls, skip_mappings=False) -> dict[str, _Field]:
1076
+ def fields(cls, skip_mappings=False, no_cache=False) -> dict[str, _Field]:
1067
1077
  """Describe the elements of the model.
1068
1078
 
1069
1079
  For compound fields return the field object.
@@ -1071,33 +1081,42 @@ class Model:
1071
1081
  Args:
1072
1082
  skip_mappings (bool): Skip over mappings where the real subfield names are unknown.
1073
1083
  """
1074
- if skip_mappings and hasattr(cls, "_odm_field_cache_skip"):
1084
+ if not no_cache and skip_mappings and "_odm_field_cache_skip" in cls.__dict__:
1075
1085
  return cls._odm_field_cache_skip
1076
1086
 
1077
- if not skip_mappings and hasattr(cls, "_odm_field_cache"):
1087
+ if not no_cache and not skip_mappings and "_odm_field_cache" in cls.__dict__:
1078
1088
  return cls._odm_field_cache
1079
1089
 
1080
1090
  out = dict()
1091
+ # Iterate through inherited classes. If any of them are odm.Model (e.g., they expose fields())
1092
+ # then include their fields as well. This allows for class inheritance.
1093
+ for base in cls.__bases__:
1094
+ _fields: Callable[..., dict[str, _Field]] | None = getattr(base, "fields", None)
1095
+ if _fields and callable(_fields):
1096
+ out.update(_fields(skip_mappings=skip_mappings, no_cache=True))
1097
+
1081
1098
  for name, field_data in cls.__dict__.items():
1082
1099
  if isinstance(field_data, _Field):
1083
1100
  if skip_mappings and isinstance(field_data, Mapping):
1084
1101
  continue
1085
1102
  out[name.rstrip("_")] = field_data
1086
1103
 
1087
- if skip_mappings:
1088
- cls._odm_field_cache_skip = out
1089
- else:
1090
- cls._odm_field_cache = out
1104
+ if not no_cache:
1105
+ if skip_mappings:
1106
+ cls._odm_field_cache_skip = out
1107
+ else:
1108
+ cls._odm_field_cache = out
1109
+
1091
1110
  return out
1092
1111
 
1093
1112
  @classmethod
1094
1113
  def add_namespace(cls, namespace: str, field: _Field, index=None, store=None, description=None):
1095
1114
  recursive_set_name(field, namespace)
1096
1115
 
1097
- if hasattr(cls, "_odm_field_cache_skip"):
1116
+ if "_odm_field_cache_skip" in cls.__dict__:
1098
1117
  cls._odm_field_cache_skip[namespace.rstrip("_")] = field
1099
1118
 
1100
- if hasattr(cls, "_odm_field_cache"):
1119
+ if "_odm_field_cache" in cls.__dict__:
1101
1120
  cls._odm_field_cache[namespace.rstrip("_")] = field
1102
1121
 
1103
1122
  setattr(cls, namespace, field)
@@ -1112,10 +1131,10 @@ class Model:
1112
1131
 
1113
1132
  @classmethod
1114
1133
  def remove_namespace(cls, namespace: str):
1115
- if hasattr(cls, "_odm_field_cache_skip"):
1134
+ if "_odm_field_cache_skip" in cls.__dict__:
1116
1135
  del cls._odm_field_cache_skip[namespace.rstrip("_")]
1117
1136
 
1118
- if hasattr(cls, "_odm_field_cache"):
1137
+ if "_odm_field_cache" in cls.__dict__:
1119
1138
  del cls._odm_field_cache[namespace.rstrip("_")]
1120
1139
 
1121
1140
  delattr(cls, namespace)
@@ -1147,8 +1166,11 @@ class Model:
1147
1166
  else:
1148
1167
  out[name] = sub_field
1149
1168
 
1150
- if isinstance(field, Compound) and show_compound:
1151
- out[name] = field
1169
+ if show_compound:
1170
+ if isinstance(field, Compound):
1171
+ out[name] = field
1172
+ elif isinstance(field, List) and isinstance(field.child_type, Compound):
1173
+ out[name] = field.child_type
1152
1174
 
1153
1175
  return out
1154
1176
 
@@ -1163,6 +1185,11 @@ class Model:
1163
1185
  skip_mappings (bool): Skip over mappings where the real subfield names are unknown.
1164
1186
  """
1165
1187
  out = dict()
1188
+ for base in cls.__bases__:
1189
+ _flat_fields: Callable[..., dict[str, _Field]] | None = getattr(base, "flat_fields", None)
1190
+ if _flat_fields and callable(_flat_fields):
1191
+ out.update(_flat_fields(show_compound=show_compound, skip_mappings=skip_mappings))
1192
+
1166
1193
  for name, field in cls.__dict__.items():
1167
1194
  if isinstance(field, _Field):
1168
1195
  if skip_mappings and isinstance(field, Mapping):
@@ -1185,7 +1212,7 @@ class Model:
1185
1212
  include_autogen_note=True,
1186
1213
  defaults=None,
1187
1214
  url_prefix="/howler/odm/class/",
1188
- ) -> Union[str, Dict]:
1215
+ ) -> str:
1189
1216
  markdown_content = (
1190
1217
  (
1191
1218
  '??? success "Auto-Generated Documentation"\n '
@@ -1476,12 +1503,44 @@ def recursive_set_name(field, name, to_parent=False):
1476
1503
  recursive_set_name(field.child_type, name, to_parent=True)
1477
1504
 
1478
1505
 
1479
- def model(index=None, store=None, description=None):
1480
- """Decorator to create model objects."""
1506
+ def model(index=None, store=None, description=None, id_field=None):
1507
+ """Decorator that finalizes a Model subclass for use with the datastore.
1508
+ Assigns metadata to the class (description, id field), validates that all
1509
+ declared field names are legal, recursively sets each field's name, and
1510
+ applies default index/store settings to every field.
1511
+ If ``id_field`` is not provided, it defaults to ``<classname_lower>_id``.
1512
+ Args:
1513
+ index: Default index setting applied to all fields on the model.
1514
+ store: Default store setting applied to all fields on the model.
1515
+ description: Human-readable description of the model.
1516
+ id_field: Name of the field used as the primary key. Defaults to
1517
+ ``<classname_lower>_id`` when not specified.
1518
+ Returns:
1519
+ A class decorator that configures and returns the decorated Model subclass.
1520
+ Raises:
1521
+ HowlerValueError: If any field name fails the ``FIELD_SANITIZER`` regex
1522
+ or appears in ``BANNED_FIELDS``.
1523
+ """
1481
1524
 
1482
1525
  def _finish_model(cls):
1483
1526
  cls._Model__description = description
1484
- for name, field_data in cls.fields().items():
1527
+ fields = cls.fields()
1528
+
1529
+ if id_field is None:
1530
+ cls._Model__id_field = f"{cls.__name__.lower()}_id"
1531
+ else:
1532
+ if not isinstance(id_field, str):
1533
+ raise HowlerTypeError(f"id_field must be a str, got {type(id_field).__name__}")
1534
+
1535
+ if not FIELD_SANITIZER.match(id_field) or id_field in BANNED_FIELDS:
1536
+ raise HowlerValueError(f"Illegal id_field name: {id_field}")
1537
+
1538
+ if id_field not in fields:
1539
+ raise HowlerValueError(f"id_field must reference a declared field: {id_field}")
1540
+
1541
+ cls._Model__id_field = id_field
1542
+
1543
+ for name, field_data in fields.items():
1485
1544
  if not FIELD_SANITIZER.match(name) or name in BANNED_FIELDS:
1486
1545
  raise HowlerValueError(f"Illegal variable name: {name}")
1487
1546
 
@@ -0,0 +1,27 @@
1
+ """Compatibility shims for symbols added in Python 3.11.
2
+
3
+ Import from this module instead of using `if sys.version_info` guards inline.
4
+ """
5
+
6
+ import sys
7
+
8
+ if sys.version_info >= (3, 11):
9
+ from enum import StrEnum
10
+ from typing import NotRequired, TypedDict
11
+ else:
12
+ from enum import Enum as _Enum
13
+
14
+ class StrEnum(str, _Enum): # type: ignore[no-redef]
15
+ """str + Enum backport for Python < 3.11."""
16
+
17
+ def __str__(self) -> str:
18
+ return str.__str__(self)
19
+
20
+ def __format__(self, format_spec: str) -> str:
21
+ return str.__format__(self, format_spec)
22
+
23
+ # typing_extensions.TypedDict supports Generic[T] mixing on Python < 3.11;
24
+ # the stdlib version does not gain that until 3.11.
25
+ from typing_extensions import NotRequired, TypedDict # noqa: F401
26
+
27
+ __all__ = ["NotRequired", "StrEnum", "TypedDict"]
@@ -152,7 +152,7 @@ suppress-none-returning = true
152
152
  [tool.poetry]
153
153
  package-mode = true
154
154
  name = "howler-api"
155
- version = "3.4.0.dev834"
155
+ version = "3.4.0.dev845"
156
156
  description = "Howler - API server"
157
157
  authors = [
158
158
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",