spanforge 2.0.1__tar.gz → 2.0.2__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 (319) hide show
  1. {spanforge-2.0.1 → spanforge-2.0.2}/PKG-INFO +1 -1
  2. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/redact.md +5 -5
  3. {spanforge-2.0.1 → spanforge-2.0.2}/docs/changelog.md +14 -6
  4. {spanforge-2.0.1 → spanforge-2.0.2}/docs/cli.md +2 -1
  5. {spanforge-2.0.1 → spanforge-2.0.2}/docs/quickstart.md +6 -3
  6. {spanforge-2.0.1 → spanforge-2.0.2}/pyproject.toml +1 -1
  7. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/__init__.py +1 -1
  8. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/redact.py +53 -12
  9. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase11_security.py +1 -1
  10. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_redact.py +274 -197
  11. {spanforge-2.0.1 → spanforge-2.0.2}/.gitattributes +0 -0
  12. {spanforge-2.0.1 → spanforge-2.0.2}/.github/CODEOWNERS +0 -0
  13. {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  14. {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  15. {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  16. {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/rfc.yml +0 -0
  17. {spanforge-2.0.1 → spanforge-2.0.2}/.github/pull_request_template.md +0 -0
  18. {spanforge-2.0.1 → spanforge-2.0.2}/.github/workflows/ci.yml +0 -0
  19. {spanforge-2.0.1 → spanforge-2.0.2}/.github/workflows/release.yml +0 -0
  20. {spanforge-2.0.1 → spanforge-2.0.2}/.gitignore +0 -0
  21. {spanforge-2.0.1 → spanforge-2.0.2}/CNAME +0 -0
  22. {spanforge-2.0.1 → spanforge-2.0.2}/CODE_OF_CONDUCT.md +0 -0
  23. {spanforge-2.0.1 → spanforge-2.0.2}/CONFORMANCE.md +0 -0
  24. {spanforge-2.0.1 → spanforge-2.0.2}/LICENSE +0 -0
  25. {spanforge-2.0.1 → spanforge-2.0.2}/MAINTAINERS.md +0 -0
  26. {spanforge-2.0.1 → spanforge-2.0.2}/PRICING.md +0 -0
  27. {spanforge-2.0.1 → spanforge-2.0.2}/README.md +0 -0
  28. {spanforge-2.0.1 → spanforge-2.0.2}/README.md.bak +0 -0
  29. {spanforge-2.0.1 → spanforge-2.0.2}/RELEASE.md +0 -0
  30. {spanforge-2.0.1 → spanforge-2.0.2}/SECURITY.md +0 -0
  31. {spanforge-2.0.1 → spanforge-2.0.2}/docs/Makefile +0 -0
  32. {spanforge-2.0.1 → spanforge-2.0.2}/docs/_static/.gitkeep +0 -0
  33. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/auto.md +0 -0
  34. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/cache.md +0 -0
  35. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/compliance.md +0 -0
  36. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/consumer.md +0 -0
  37. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/debug.md +0 -0
  38. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/deprecations.md +0 -0
  39. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/event.md +0 -0
  40. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/exceptions.md +0 -0
  41. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/export.md +0 -0
  42. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/governance.md +0 -0
  43. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/hooks.md +0 -0
  44. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/index.md +0 -0
  45. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/integrations.md +0 -0
  46. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/lint.md +0 -0
  47. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/metrics.md +0 -0
  48. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/migrate.md +0 -0
  49. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/models.md +0 -0
  50. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/normalizer.md +0 -0
  51. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/signing.md +0 -0
  52. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/store.md +0 -0
  53. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/stream.md +0 -0
  54. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/testing.md +0 -0
  55. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/trace.md +0 -0
  56. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/types.md +0 -0
  57. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/ulid.md +0 -0
  58. {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/validate.md +0 -0
  59. {spanforge-2.0.1 → spanforge-2.0.2}/docs/conf.py +0 -0
  60. {spanforge-2.0.1 → spanforge-2.0.2}/docs/configuration.md +0 -0
  61. {spanforge-2.0.1 → spanforge-2.0.2}/docs/contributing.md +0 -0
  62. {spanforge-2.0.1 → spanforge-2.0.2}/docs/deployment/air-gapped.md +0 -0
  63. {spanforge-2.0.1 → spanforge-2.0.2}/docs/deployment/kubernetes.md +0 -0
  64. {spanforge-2.0.1 → spanforge-2.0.2}/docs/index.md +0 -0
  65. {spanforge-2.0.1 → spanforge-2.0.2}/docs/installation.md +0 -0
  66. {spanforge-2.0.1 → spanforge-2.0.2}/docs/integrations/crewai.md +0 -0
  67. {spanforge-2.0.1 → spanforge-2.0.2}/docs/make.bat +0 -0
  68. {spanforge-2.0.1 → spanforge-2.0.2}/docs/migrations/from-langfuse.md +0 -0
  69. {spanforge-2.0.1 → spanforge-2.0.2}/docs/migrations/from-langsmith.md +0 -0
  70. {spanforge-2.0.1 → spanforge-2.0.2}/docs/migrations/from-openllmetry.md +0 -0
  71. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/audit.md +0 -0
  72. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/cache.md +0 -0
  73. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/consent.md +0 -0
  74. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/cost.md +0 -0
  75. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/diff.md +0 -0
  76. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/eval.md +0 -0
  77. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/explanation.md +0 -0
  78. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/fence.md +0 -0
  79. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/guard.md +0 -0
  80. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/hitl.md +0 -0
  81. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/index.md +0 -0
  82. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/model_registry.md +0 -0
  83. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/prompt.md +0 -0
  84. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/redact_ns.md +0 -0
  85. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/template.md +0 -0
  86. {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/trace.md +0 -0
  87. {spanforge-2.0.1 → spanforge-2.0.2}/docs/rfc/rfc-0001.md +0 -0
  88. {spanforge-2.0.1 → spanforge-2.0.2}/docs/runbook.md +0 -0
  89. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/README.md +0 -0
  90. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/envelope.schema.json +0 -0
  91. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/agent-run.schema.json +0 -0
  92. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/agent-step.schema.json +0 -0
  93. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/audit.schema.json +0 -0
  94. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/cache.schema.json +0 -0
  95. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/consent.schema.json +0 -0
  96. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/cost.schema.json +0 -0
  97. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/diff.schema.json +0 -0
  98. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/eval.schema.json +0 -0
  99. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/explanation.schema.json +0 -0
  100. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/fence.schema.json +0 -0
  101. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/guard.schema.json +0 -0
  102. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/hitl.schema.json +0 -0
  103. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/model-registry.schema.json +0 -0
  104. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/prompt.schema.json +0 -0
  105. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/redact.schema.json +0 -0
  106. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/span.schema.json +0 -0
  107. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/template.schema.json +0 -0
  108. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/types/common.schema.json +0 -0
  109. {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema-versioning.md +0 -0
  110. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/cache.md +0 -0
  111. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/compliance.md +0 -0
  112. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/custom_exporters.md +0 -0
  113. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/debugging.md +0 -0
  114. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/events.md +0 -0
  115. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/export.md +0 -0
  116. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/governance.md +0 -0
  117. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/index.md +0 -0
  118. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/linting.md +0 -0
  119. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/metrics.md +0 -0
  120. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/migration.md +0 -0
  121. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/redaction.md +0 -0
  122. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/signing.md +0 -0
  123. {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/tracing.md +0 -0
  124. {spanforge-2.0.1 → spanforge-2.0.2}/examples/agent_workflow.py +0 -0
  125. {spanforge-2.0.1 → spanforge-2.0.2}/examples/budget_alert.py +0 -0
  126. {spanforge-2.0.1 → spanforge-2.0.2}/examples/docker/Dockerfile +0 -0
  127. {spanforge-2.0.1 → spanforge-2.0.2}/examples/docker/docker-compose.yml +0 -0
  128. {spanforge-2.0.1 → spanforge-2.0.2}/examples/docker/otel-config.yaml +0 -0
  129. {spanforge-2.0.1 → spanforge-2.0.2}/examples/langchain_chain.py +0 -0
  130. {spanforge-2.0.1 → spanforge-2.0.2}/examples/multi_agent_rag.py +0 -0
  131. {spanforge-2.0.1 → spanforge-2.0.2}/examples/multi_tenant.py +0 -0
  132. {spanforge-2.0.1 → spanforge-2.0.2}/examples/openai_chat.py +0 -0
  133. {spanforge-2.0.1 → spanforge-2.0.2}/examples/otlp_grafana.py +0 -0
  134. {spanforge-2.0.1 → spanforge-2.0.2}/examples/production_multi_agent.py +0 -0
  135. {spanforge-2.0.1 → spanforge-2.0.2}/examples/secure_pipeline.py +0 -0
  136. {spanforge-2.0.1 → spanforge-2.0.2}/examples/streaming_response.py +0 -0
  137. {spanforge-2.0.1 → spanforge-2.0.2}/sonar-project.properties +0 -0
  138. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_batch_exporter.py +0 -0
  139. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_cli.py +0 -0
  140. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_hooks.py +0 -0
  141. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_server.py +0 -0
  142. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_span.py +0 -0
  143. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_store.py +0 -0
  144. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_stream.py +0 -0
  145. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_trace.py +0 -0
  146. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_tracer.py +0 -0
  147. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/actor.py +0 -0
  148. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/alerts.py +0 -0
  149. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/auto.py +0 -0
  150. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/baseline.py +0 -0
  151. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/config.py +0 -0
  152. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/consent.py +0 -0
  153. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/consumer.py +0 -0
  154. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/core/__init__.py +0 -0
  155. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/core/compliance_mapping.py +0 -0
  156. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/cost.py +0 -0
  157. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/debug.py +0 -0
  158. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/drift.py +0 -0
  159. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/egress.py +0 -0
  160. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/eval.py +0 -0
  161. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/event.py +0 -0
  162. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exceptions.py +0 -0
  163. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/explain.py +0 -0
  164. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/__init__.py +0 -0
  165. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/append_only.py +0 -0
  166. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/cloud.py +0 -0
  167. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/datadog.py +0 -0
  168. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/grafana.py +0 -0
  169. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/jsonl.py +0 -0
  170. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/otel_bridge.py +0 -0
  171. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/otlp.py +0 -0
  172. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/otlp_bridge.py +0 -0
  173. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/redis_backend.py +0 -0
  174. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/webhook.py +0 -0
  175. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exporters/__init__.py +0 -0
  176. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exporters/console.py +0 -0
  177. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exporters/jsonl.py +0 -0
  178. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/hitl.py +0 -0
  179. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/inspect.py +0 -0
  180. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/__init__.py +0 -0
  181. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/_pricing.py +0 -0
  182. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/anthropic.py +0 -0
  183. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/bedrock.py +0 -0
  184. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/crewai.py +0 -0
  185. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/gemini.py +0 -0
  186. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/groq.py +0 -0
  187. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/langchain.py +0 -0
  188. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/llamaindex.py +0 -0
  189. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/ollama.py +0 -0
  190. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/openai.py +0 -0
  191. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/together.py +0 -0
  192. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/metrics.py +0 -0
  193. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/metrics_export.py +0 -0
  194. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/migrate.py +0 -0
  195. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/model_registry.py +0 -0
  196. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/models.py +0 -0
  197. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/__init__.py +0 -0
  198. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/audit.py +0 -0
  199. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/cache.py +0 -0
  200. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/chain.py +0 -0
  201. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/confidence.py +0 -0
  202. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/consent.py +0 -0
  203. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/cost.py +0 -0
  204. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/decision.py +0 -0
  205. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/diff.py +0 -0
  206. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/drift.py +0 -0
  207. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/eval_.py +0 -0
  208. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/fence.py +0 -0
  209. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/guard.py +0 -0
  210. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/hitl.py +0 -0
  211. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/latency.py +0 -0
  212. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/prompt.py +0 -0
  213. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/redact.py +0 -0
  214. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/template.py +0 -0
  215. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/tool_call.py +0 -0
  216. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/trace.py +0 -0
  217. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/normalizer.py +0 -0
  218. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/presidio_backend.py +0 -0
  219. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/processor.py +0 -0
  220. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/prompt_registry.py +0 -0
  221. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/py.typed +0 -0
  222. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/sampling.py +0 -0
  223. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/schemas/v1.0/schema.json +0 -0
  224. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/schemas/v2.0/schema.json +0 -0
  225. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/signing.py +0 -0
  226. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/stream.py +0 -0
  227. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/testing.py +0 -0
  228. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/trace.py +0 -0
  229. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/types.py +0 -0
  230. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/ulid.py +0 -0
  231. {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/validate.py +0 -0
  232. {spanforge-2.0.1 → spanforge-2.0.2}/test_agent.jsonl +0 -0
  233. {spanforge-2.0.1 → spanforge-2.0.2}/test_events.jsonl +0 -0
  234. {spanforge-2.0.1 → spanforge-2.0.2}/tests/__init__.py +0 -0
  235. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/__init__.py +0 -0
  236. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/chain.json +0 -0
  237. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/compliance.json +0 -0
  238. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/key_security.json +0 -0
  239. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/migration.json +0 -0
  240. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/pii.json +0 -0
  241. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/signing.json +0 -0
  242. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures.json +0 -0
  243. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/run_conformance.py +0 -0
  244. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/test_conformance.py +0 -0
  245. {spanforge-2.0.1 → spanforge-2.0.2}/tests/conftest.py +0 -0
  246. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_actor.py +0 -0
  247. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_alerts.py +0 -0
  248. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_auto.py +0 -0
  249. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_baseline.py +0 -0
  250. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_benchmarks.py +0 -0
  251. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_budget_alert.py +0 -0
  252. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_cli.py +0 -0
  253. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_compliance_mapping.py +0 -0
  254. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_consent.py +0 -0
  255. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_consumer.py +0 -0
  256. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_cost_event_emission.py +0 -0
  257. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_cost_tracker.py +0 -0
  258. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_costguard_gaps.py +0 -0
  259. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_drift.py +0 -0
  260. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_event.py +0 -0
  261. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_exceptions.py +0 -0
  262. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_explain.py +0 -0
  263. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_cloud.py +0 -0
  264. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_datadog.py +0 -0
  265. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_grafana.py +0 -0
  266. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_jsonl.py +0 -0
  267. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_otel_bridge.py +0 -0
  268. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_otlp.py +0 -0
  269. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_redis_backend.py +0 -0
  270. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_webhook.py +0 -0
  271. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_hitl.py +0 -0
  272. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_inspect.py +0 -0
  273. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_integration.py +0 -0
  274. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_integrations.py +0 -0
  275. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_migrate.py +0 -0
  276. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_model_registry.py +0 -0
  277. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_models.py +0 -0
  278. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_namespaces.py +0 -0
  279. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_otlp_bridge.py +0 -0
  280. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase10_features.py +0 -0
  281. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase1_context_trace.py +0 -0
  282. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase2_observability.py +0 -0
  283. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase3_debug_sampling.py +0 -0
  284. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase4_agent_instrumentation.py +0 -0
  285. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase4_metrics_store.py +0 -0
  286. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase5_console_exporter.py +0 -0
  287. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase5_coverage.py +0 -0
  288. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase5_hooks_crewai.py +0 -0
  289. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase6_openai_integration.py +0 -0
  290. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_processor_coverage.py +0 -0
  291. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_properties.py +0 -0
  292. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_rfc_namespaces.py +0 -0
  293. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sampling_coverage.py +0 -0
  294. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_config.py +0 -0
  295. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_coverage_boost.py +0 -0
  296. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_exporters.py +0 -0
  297. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_final_coverage.py +0 -0
  298. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_gap_filler.py +0 -0
  299. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_openai_integration.py +0 -0
  300. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_phase7_integrations.py +0 -0
  301. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_precision_coverage.py +0 -0
  302. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_span.py +0 -0
  303. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_stream.py +0 -0
  304. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_tracer.py +0 -0
  305. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_validation_coverage.py +0 -0
  306. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_server.py +0 -0
  307. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf11.py +0 -0
  308. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf12.py +0 -0
  309. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf13.py +0 -0
  310. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf14.py +0 -0
  311. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf15.py +0 -0
  312. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf16.py +0 -0
  313. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_signing.py +0 -0
  314. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_stream.py +0 -0
  315. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_trace_decorator.py +0 -0
  316. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_trace_pytest_fixtures.py +0 -0
  317. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_types.py +0 -0
  318. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_ulid.py +0 -0
  319. {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_validate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spanforge
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: SpanForge — AI lifecycle and governance platform (RFC-0001 SPANFORGE)
5
5
  Project-URL: Homepage, https://github.com/veerarag1973/spanforge
6
6
  Project-URL: Documentation, https://github.com/veerarag1973/spanforge/blob/main/docs/index.md
@@ -183,7 +183,7 @@ The original event is **not** mutated.
183
183
 
184
184
  ## Module-level functions
185
185
 
186
- ### `contains_pii(event: Event, *, scan_raw: bool = False) -> bool`
186
+ ### `contains_pii(event: Event, *, scan_raw: bool = True) -> bool`
187
187
 
188
188
  Return `True` if any payload value is a `Redactable` with
189
189
  `sensitivity >= Sensitivity.PII`.
@@ -193,13 +193,13 @@ Return `True` if any payload value is a `Redactable` with
193
193
  | Parameter | Type | Description |
194
194
  |-----------|------|-------------|
195
195
  | `event` | `Event` | The event to inspect. |
196
- | `scan_raw` | `bool` | When `True`, also run regex-based PII scanning on payload strings (via `scan_payload()`), not just check for `Redactable` wrappers. Default `False`. |
196
+ | `scan_raw` | `bool` | When `True` (default), also run regex-based PII scanning on payload strings (via `scan_payload()`), not just check for `Redactable` wrappers. Pass `False` to check `Redactable` wrappers only. |
197
197
 
198
198
  **Returns:** `bool`
199
199
 
200
200
  ---
201
201
 
202
- ### `assert_redacted(event: Event, context: str = "", *, scan_raw: bool = False) -> None`
202
+ ### `assert_redacted(event: Event, context: str = "", *, scan_raw: bool = True) -> None`
203
203
 
204
204
  Raise `PIINotRedactedError` if the event still contains unredacted PII or PHI.
205
205
 
@@ -211,7 +211,7 @@ Use this as a guardrail before exporting events.
211
211
  |-----------|------|-------------|
212
212
  | `event` | `Event` | The event to check. |
213
213
  | `context` | `str` | Optional context string embedded in the exception message. |
214
- | `scan_raw` | `bool` | When `True`, also run regex-based PII scanning. Default `False`. |
214
+ | `scan_raw` | `bool` | When `True` (default), also run regex-based PII scanning. Pass `False` to check `Redactable` wrappers only. |
215
215
 
216
216
  **Raises:** `PIINotRedactedError` — if any `Redactable` PII/PHI values or raw PII patterns remain in the payload.
217
217
 
@@ -287,7 +287,7 @@ Scan a payload dictionary for PII using regex detectors.
287
287
  Walks the entire payload recursively (up to `max_depth`), testing every string
288
288
  value against the built-in pattern set plus any caller-supplied patterns.
289
289
 
290
- **Built-in detectors:** `email`, `phone`, `ssn` (with SSA range validation via `_is_valid_ssn`), `credit_card` (with Luhn validation), `ip_address`, `uk_national_insurance`, `date_of_birth` (with calendar validation via `_is_valid_date`), `address`.
290
+ **Built-in detectors:** `email`, `phone`, `ssn` (with SSA range validation via `_is_valid_ssn`), `credit_card` (with Luhn validation), `ip_address`, `uk_national_insurance`, `date_of_birth` (global formats — ISO, US MDY, day-first DMY, written-month DMY/MDY — with calendar validation via `_is_valid_date`), `address`.
291
291
 
292
292
  **Args:**
293
293
 
@@ -6,7 +6,7 @@ this project adheres to [Semantic Versioning](https://semver.org/).
6
6
 
7
7
  ---
8
8
 
9
- ## 2.0.1 — 2026-04-14
9
+ ## 2.0.2 — 2026-04-14
10
10
 
11
11
  **Compliance Integration Hardening & CostGuard Enhancements**
12
12
 
@@ -108,11 +108,18 @@ this project adheres to [Semantic Versioning](https://semver.org/).
108
108
 
109
109
  ### Added — Extended PII Pattern Coverage
110
110
 
111
- - **`date_of_birth` pattern** — detects dates of birth in `MM/DD/YYYY`,
112
- `MM-DD-YYYY`, `YYYY-MM-DD`, and `YYYY/MM/DD` formats (centuries 1900–2099).
111
+ - **`date_of_birth` pattern** — detects dates of birth across all major global
112
+ formats (centuries 1900–2099):
113
+ - ISO / year-first: `YYYY-MM-DD`, `YYYY/MM/DD`, `YYYY.MM.DD`
114
+ - US month-first: `MM/DD/YYYY`, `MM-DD-YYYY`, `MM.DD.YYYY`
115
+ - Day-first (UK, EU, Germany, Asia, Australia, Latin America): `DD/MM/YYYY`,
116
+ `DD-MM-YYYY`, `DD.MM.YYYY`
117
+ - Written day-first: `15 Jan 2000`, `15-Jan-2000`, `15 January 2000`
118
+ - Written month-first: `Jan 15, 2000`, `January 15 2000`
119
+
113
120
  Secondary calendar validation via `_is_valid_date()` rejects impossible dates
114
- (e.g. `02/30/1990`, `13/01/1990`). Mapped to sensitivity `"high"`.
115
- - **`address` pattern** — detects US street addresses (`<number> <name> <suffix>`)
121
+ (e.g. `02/30/1990`, `31/04/1990`). Mapped to sensitivity `"high"`.
122
+ - **`address` pattern** — detects street addresses (`<number> <name> <suffix>`)
116
123
  with a curated suffix list (Street/St, Avenue/Ave, Road/Rd, Boulevard/Blvd,
117
124
  Drive/Dr, Lane/Ln, Court/Ct, Way, Place/Pl, Circle/Cir, Trail/Trl,
118
125
  Terrace/Ter, Parkway/Pkwy, Highway/Hwy, Route/Rte). Mapped to sensitivity
@@ -122,7 +129,8 @@ this project adheres to [Semantic Versioning](https://semver.org/).
122
129
  `900–999` (ITIN-reserved), group `00`, and serial `0000`, eliminating the
123
130
  most common false-positive ranges.
124
131
  - **`_is_valid_date(date_str)`** — calendar correctness validator applied
125
- post-regex to every `date_of_birth` match. Delegates to
132
+ post-regex to every `date_of_birth` match. Tries 15 `strptime` format
133
+ strings covering all numeric and written-month orderings; delegates to
126
134
  `datetime.strptime` for accurate month-length and leap-year enforcement.
127
135
  - Both validators follow the same pattern as existing `_luhn_check()` and
128
136
  `_verhoeff_check()` — applied inside `scan_payload._walk()` after the regex
@@ -794,7 +794,8 @@ result = scan_payload(event.payload, extra_patterns=DPDP_PATTERNS)
794
794
  ```
795
795
 
796
796
  Built-in types: `email`, `phone`, `ssn`, `credit_card`, `ip_address`,
797
- `uk_national_insurance`, `date_of_birth`, `address`. DPDP add-on types: `aadhaar` (high), `pan` (high).
797
+ `uk_national_insurance`, `date_of_birth` (global formats: ISO, US, day-first
798
+ DMY, written-month), `address`. DPDP add-on types: `aadhaar` (high), `pan` (high).
798
799
 
799
800
  ---
800
801
 
@@ -181,9 +181,12 @@ for hit in result.hits:
181
181
  # address: home (sensitivity=medium)
182
182
  ```
183
183
 
184
- Calendar-invalid dates (e.g. `02/30/1990`) and SSNs in reserved ranges
185
- (area `000`, `666`, `900–999`) are automatically filtered out to reduce false
186
- positives.
184
+ The `date_of_birth` detector recognises all major global formats: ISO
185
+ (`YYYY-MM-DD`, `YYYY.MM.DD`), US month-first (`MM/DD/YYYY`, `MM.DD.YYYY`),
186
+ day-first (UK/EU/Asia: `DD/MM/YYYY`, `DD.MM.YYYY`), and written-month forms
187
+ (`15 Jan 2000`, `January 15, 2000`). Calendar-invalid dates (e.g.
188
+ `02/30/1990`, `31/04/1990`) and SSNs in reserved ranges (area `000`, `666`,
189
+ `900–999`) are automatically filtered out to reduce false positives.
187
190
 
188
191
  ## Exporting events
189
192
 
@@ -7,7 +7,7 @@ build-backend = "hatchling.build"
7
7
  # ---------------------------------------------------------------------------
8
8
  [project]
9
9
  name = "spanforge"
10
- version = "2.0.1"
10
+ version = "2.0.2"
11
11
  description = "SpanForge — AI lifecycle and governance platform (RFC-0001 SPANFORGE)"
12
12
  readme = "README.md"
13
13
  license = { text = "MIT" }
@@ -399,7 +399,7 @@ from spanforge.explain import (
399
399
  )
400
400
  from spanforge.namespaces.consent import ConsentPayload
401
401
  from spanforge.namespaces.hitl import HITLPayload
402
- __version__: str = "2.0.1"
402
+ __version__: str = "2.0.2"
403
403
  #: RFC-0001 SPANFORGE conformance profile label.
404
404
  from typing import Final as _Final
405
405
  CONFORMANCE_PROFILE: _Final[str] = "SPANFORGE-Enterprise-2.0"
@@ -586,12 +586,32 @@ _PII_PATTERNS: Final[dict[str, re.Pattern[str]]] = {
586
586
  r"\b[A-CEGHJ-PR-TW-Z]{2}\s?\d{2}\s?\d{2}\s?\d{2}\s?[A-D]\b",
587
587
  re.IGNORECASE,
588
588
  ),
589
- # Date of birth — MM/DD/YYYY, MM-DD-YYYY, YYYY-MM-DD, YYYY/MM/DD
590
- # _is_valid_date() provides secondary calendar correctness check.
589
+ # Date of birth — numeric (/, -, .) and written-month forms covering
590
+ # ISO/YMD, US MDY, day-first DMY (Europe/Asia/Australia/etc.), and
591
+ # long/short written-month variants. Years restricted to 19xx–20xx to
592
+ # limit false positives. _is_valid_date() provides secondary calendar-
593
+ # correctness check (leap-year rules, month lengths, etc.).
591
594
  "date_of_birth": re.compile(
592
- r"\b(?:0?[1-9]|1[0-2])[/\-](?:0?[1-9]|[12]\d|3[01])[/\-](?:19|20)\d{2}\b"
595
+ # ISO / YMD: YYYY-MM-DD, YYYY/MM/DD, YYYY.MM.DD
596
+ r"\b(?:19|20)\d{2}[-/.](?:0?[1-9]|1[0-2])[-/.](?:0?[1-9]|[12]\d|3[01])\b"
593
597
  r"|"
594
- r"\b(?:19|20)\d{2}[/\-](?:0?[1-9]|1[0-2])[/\-](?:0?[1-9]|[12]\d|3[01])\b"
598
+ # US MDY: MM/DD/YYYY, MM-DD-YYYY, MM.DD.YYYY
599
+ r"\b(?:0?[1-9]|1[0-2])[-/.](?:0?[1-9]|[12]\d|3[01])[-/.](?:19|20)\d{2}\b"
600
+ r"|"
601
+ # Day-first DMY: DD/MM/YYYY, DD-MM-YYYY, DD.MM.YYYY (UK, EU, Asia, etc.)
602
+ r"\b(?:0?[1-9]|[12]\d|3[01])[-/.](?:0?[1-9]|1[0-2])[-/.](?:19|20)\d{2}\b"
603
+ r"|"
604
+ # Written DMY: "15 Jan 2000", "15-Jan-2000", "15 January 2000"
605
+ r"\b(?:0?[1-9]|[12]\d|3[01])[\s\-]"
606
+ r"(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?"
607
+ r"|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)"
608
+ r"[\s\-](?:19|20)\d{2}\b"
609
+ r"|"
610
+ # Written MDY: "Jan 15, 2000", "January 15 2000"
611
+ r"\b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?"
612
+ r"|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)"
613
+ r"\s+(?:0?[1-9]|[12]\d|3[01]),?\s+(?:19|20)\d{2}\b",
614
+ re.IGNORECASE,
595
615
  ),
596
616
  # Street address — house number + street name + recognised suffix
597
617
  "address": re.compile(
@@ -757,23 +777,44 @@ def _is_valid_ssn(ssn_str: str) -> bool:
757
777
  def _is_valid_date(date_str: str) -> bool:
758
778
  """Return ``True`` if *date_str* is a valid calendar date.
759
779
 
760
- Accepts the four formats produced by the ``"date_of_birth"`` regex in
761
- :data:`_PII_PATTERNS`:
780
+ Accepts all numeric and written-month formats produced by the
781
+ ``"date_of_birth"`` regex in :data:`_PII_PATTERNS`.
762
782
 
763
- * ``MM/DD/YYYY`` and ``MM-DD-YYYY``
764
- * ``YYYY/MM/DD`` and ``YYYY-MM-DD``
783
+ Numeric formats (separators ``/``, ``-``, ``.``):
784
+
785
+ * ``YYYY/MM/DD``, ``YYYY-MM-DD``, ``YYYY.MM.DD`` — ISO / year-first
786
+ * ``MM/DD/YYYY``, ``MM-DD-YYYY``, ``MM.DD.YYYY`` — US month-first
787
+ * ``DD/MM/YYYY``, ``DD-MM-YYYY``, ``DD.MM.YYYY`` — day-first (Europe,
788
+ Asia, Australia, Latin America, etc.)
789
+
790
+ Written-month formats:
791
+
792
+ * ``DD Mon YYYY``, ``DD-Mon-YYYY``, ``DD Month YYYY`` (e.g. 15 Jan 2000)
793
+ * ``Mon DD, YYYY``, ``Mon DD YYYY``, ``Month DD, YYYY`` (e.g. Jan 15, 2000)
765
794
 
766
795
  Delegates to :func:`datetime.datetime.strptime` so leap-year rules and
767
- month-length limits are enforced (e.g. ``02/30/2000`` is rejected).
796
+ month-length limits are enforced (e.g. ``31/04/1990`` is rejected).
768
797
 
769
798
  Args:
770
799
  date_str: Raw match string from the ``"date_of_birth"`` regex.
771
800
 
772
801
  Returns:
773
- ``True`` if the string represents a real calendar date; ``False``
774
- if no known format matches or the date is not calendar-valid.
802
+ ``True`` if the string represents a real calendar date in any of the
803
+ recognised formats; ``False`` otherwise.
775
804
  """
776
- for fmt in ("%m/%d/%Y", "%m-%d-%Y", "%Y/%m/%d", "%Y-%m-%d"):
805
+ _FORMATS = (
806
+ # ISO / YMD
807
+ "%Y/%m/%d", "%Y-%m-%d", "%Y.%m.%d",
808
+ # US MDY
809
+ "%m/%d/%Y", "%m-%d-%Y", "%m.%d.%Y",
810
+ # Day-first DMY (Europe, Asia, Australia, Latin America, etc.)
811
+ "%d/%m/%Y", "%d-%m-%Y", "%d.%m.%Y",
812
+ # Written DMY: "15 Jan 2000", "15-Jan-2000", "15 January 2000"
813
+ "%d %b %Y", "%d-%b-%Y", "%d %B %Y", "%d-%B-%Y",
814
+ # Written MDY: "Jan 15, 2000", "Jan 15 2000", "January 15, 2000"
815
+ "%b %d, %Y", "%b %d %Y", "%B %d, %Y", "%B %d %Y",
816
+ )
817
+ for fmt in _FORMATS:
777
818
  try:
778
819
  datetime.datetime.strptime(date_str.strip(), fmt)
779
820
  return True
@@ -252,4 +252,4 @@ class TestConfigureIntegration:
252
252
 
253
253
  def test_version_is_1_0_0(self):
254
254
  """spanforge.__version__ must match the current release."""
255
- assert spanforge.__version__ == "2.0.0"
255
+ assert spanforge.__version__ == "2.0.2"