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.
- {spanforge-2.0.1 → spanforge-2.0.2}/PKG-INFO +1 -1
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/redact.md +5 -5
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/changelog.md +14 -6
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/cli.md +2 -1
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/quickstart.md +6 -3
- {spanforge-2.0.1 → spanforge-2.0.2}/pyproject.toml +1 -1
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/__init__.py +1 -1
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/redact.py +53 -12
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase11_security.py +1 -1
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_redact.py +274 -197
- {spanforge-2.0.1 → spanforge-2.0.2}/.gitattributes +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/CODEOWNERS +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/ISSUE_TEMPLATE/rfc.yml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/pull_request_template.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/workflows/ci.yml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.github/workflows/release.yml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/.gitignore +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/CNAME +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/CODE_OF_CONDUCT.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/CONFORMANCE.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/LICENSE +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/MAINTAINERS.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/PRICING.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/README.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/README.md.bak +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/RELEASE.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/SECURITY.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/Makefile +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/_static/.gitkeep +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/auto.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/cache.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/compliance.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/consumer.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/debug.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/deprecations.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/event.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/exceptions.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/export.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/governance.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/hooks.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/index.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/integrations.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/lint.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/metrics.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/migrate.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/models.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/normalizer.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/signing.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/store.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/stream.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/testing.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/trace.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/types.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/ulid.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/api/validate.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/conf.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/configuration.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/contributing.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/deployment/air-gapped.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/deployment/kubernetes.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/index.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/installation.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/integrations/crewai.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/make.bat +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/migrations/from-langfuse.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/migrations/from-langsmith.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/migrations/from-openllmetry.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/audit.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/cache.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/consent.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/cost.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/diff.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/eval.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/explanation.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/fence.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/guard.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/hitl.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/index.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/model_registry.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/prompt.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/redact_ns.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/template.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/namespaces/trace.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/rfc/rfc-0001.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/runbook.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/README.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/envelope.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/agent-run.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/agent-step.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/audit.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/cache.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/consent.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/cost.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/diff.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/eval.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/explanation.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/fence.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/guard.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/hitl.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/model-registry.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/prompt.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/redact.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/span.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/payloads/template.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema/types/common.schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/schema-versioning.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/cache.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/compliance.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/custom_exporters.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/debugging.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/events.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/export.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/governance.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/index.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/linting.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/metrics.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/migration.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/redaction.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/signing.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/docs/user_guide/tracing.md +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/agent_workflow.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/budget_alert.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/docker/Dockerfile +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/docker/docker-compose.yml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/docker/otel-config.yaml +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/langchain_chain.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/multi_agent_rag.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/multi_tenant.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/openai_chat.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/otlp_grafana.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/production_multi_agent.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/secure_pipeline.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/examples/streaming_response.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/sonar-project.properties +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_batch_exporter.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_cli.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_hooks.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_server.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_span.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_store.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_stream.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_trace.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/_tracer.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/actor.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/alerts.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/auto.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/baseline.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/config.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/consent.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/consumer.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/core/__init__.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/core/compliance_mapping.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/cost.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/debug.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/drift.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/egress.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/eval.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/event.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exceptions.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/explain.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/__init__.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/append_only.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/cloud.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/datadog.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/grafana.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/jsonl.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/otel_bridge.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/otlp.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/otlp_bridge.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/redis_backend.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/export/webhook.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exporters/__init__.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exporters/console.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/exporters/jsonl.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/hitl.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/inspect.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/__init__.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/_pricing.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/anthropic.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/bedrock.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/crewai.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/gemini.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/groq.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/langchain.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/llamaindex.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/ollama.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/openai.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/integrations/together.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/metrics.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/metrics_export.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/migrate.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/model_registry.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/models.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/__init__.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/audit.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/cache.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/chain.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/confidence.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/consent.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/cost.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/decision.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/diff.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/drift.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/eval_.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/fence.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/guard.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/hitl.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/latency.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/prompt.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/redact.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/template.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/tool_call.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/namespaces/trace.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/normalizer.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/presidio_backend.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/processor.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/prompt_registry.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/py.typed +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/sampling.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/schemas/v1.0/schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/schemas/v2.0/schema.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/signing.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/stream.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/testing.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/trace.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/types.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/ulid.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/src/spanforge/validate.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/test_agent.jsonl +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/test_events.jsonl +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/__init__.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/__init__.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/chain.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/compliance.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/key_security.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/migration.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/pii.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures/signing.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/fixtures.json +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/run_conformance.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conformance/test_conformance.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/conftest.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_actor.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_alerts.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_auto.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_baseline.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_benchmarks.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_budget_alert.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_cli.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_compliance_mapping.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_consent.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_consumer.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_cost_event_emission.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_cost_tracker.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_costguard_gaps.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_drift.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_event.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_exceptions.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_explain.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_cloud.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_datadog.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_grafana.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_jsonl.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_otel_bridge.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_otlp.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_redis_backend.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_export_webhook.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_hitl.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_inspect.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_integration.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_integrations.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_migrate.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_model_registry.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_models.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_namespaces.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_otlp_bridge.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase10_features.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase1_context_trace.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase2_observability.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase3_debug_sampling.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase4_agent_instrumentation.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase4_metrics_store.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase5_console_exporter.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase5_coverage.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase5_hooks_crewai.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_phase6_openai_integration.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_processor_coverage.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_properties.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_rfc_namespaces.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sampling_coverage.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_config.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_coverage_boost.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_exporters.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_final_coverage.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_gap_filler.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_openai_integration.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_phase7_integrations.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_precision_coverage.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_span.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_stream.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_tracer.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sdk_validation_coverage.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_server.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf11.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf12.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf13.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf14.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf15.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_sf16.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_signing.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_stream.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_trace_decorator.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_trace_pytest_fixtures.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_types.py +0 -0
- {spanforge-2.0.1 → spanforge-2.0.2}/tests/test_ulid.py +0 -0
- {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.
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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.
|
|
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
|
|
112
|
-
|
|
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`, `
|
|
115
|
-
- **`address` pattern** — detects
|
|
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.
|
|
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
|
|
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
|
-
|
|
185
|
-
(
|
|
186
|
-
|
|
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.
|
|
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.
|
|
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 —
|
|
590
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
764
|
-
|
|
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. ``
|
|
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
|
|
774
|
-
|
|
802
|
+
``True`` if the string represents a real calendar date in any of the
|
|
803
|
+
recognised formats; ``False`` otherwise.
|
|
775
804
|
"""
|
|
776
|
-
|
|
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
|