# DDEX Workbench Python SDK
[](https://pypi.org/project/ddex-workbench/)
[](https://pypi.org/project/ddex-workbench/)
[](https://opensource.org/licenses/MIT)
[](https://ddex-workbench.org/docs)
Official Python SDK for [DDEX Workbench](https://ddex-workbench.org) - Open-source DDEX validation and processing tools for the music industry.
## Features
- 🚀 **Simple API** - Intuitive methods for all DDEX operations
- 🔧 **Type Safety** - Full type hints and dataclass models
- 🌐 **Async Support** - Built-in connection pooling and retry logic
- 📊 **Batch Processing** - Validate multiple files efficiently
- 🎯 **Auto-detection** - Automatic ERN version detection
- 📈 **Detailed Reports** - Comprehensive validation reports in multiple formats
- 🔑 **API Key Management** - Built-in authentication handling
## Installation
```bash
pip install ddex-workbench
```
For development:
```bash
pip install ddex-workbench[dev]
```
## Quick Start
```python
from ddex_workbench import DDEXClient
# Initialize client (API key optional for higher rate limits)
client = DDEXClient(api_key="ddex_your-api-key")
# Validate ERN XML
with open("release.xml", "r") as f:
xml_content = f.read()
result = client.validate(xml_content, version="4.3", profile="AudioAlbum")
if result.valid:
print("✅ Validation passed!")
else:
print(f"❌ Found {len(result.errors)} errors:")
for error in result.errors[:5]:
print(f" Line {error.line}: {error.message}")
```
## Usage Examples
### Basic Validation
```python
from ddex_workbench import DDEXClient
client = DDEXClient()
# Validate with specific version
result = client.validate(xml_content, version="4.3")
# Validate with profile
result = client.validate(xml_content, version="4.3", profile="AudioAlbum")
# Validate file directly
result = client.validate_file("path/to/release.xml", version="4.3")
# Validate from URL
result = client.validate_url("https://example.com/release.xml", version="4.3")
```
### Auto-detect Version
```python
# Automatically detect ERN version
result = client.validator.validate_auto(xml_content)
print(f"Detected version: {result.metadata.schema_version}")
```
### Batch Processing
```python
from pathlib import Path
# Validate all XML files in a directory
xml_files = Path("releases").glob("*.xml")
for xml_file in xml_files:
result = client.validate_file(xml_file, version="4.3")
status = "✅ Valid" if result.valid else f"❌ {len(result.errors)} errors"
print(f"{xml_file.name}: {status}")
```
### Parallel Batch Validation
```python
# Validate multiple files in parallel
items = [
(xml1_content, "4.3", "AudioAlbum"),
(xml2_content, "4.3", "AudioSingle"),
(xml3_content, "4.2", None)
]
results = client.validator.validate_batch(items, max_workers=5)
for i, result in enumerate(results):
print(f"File {i+1}: {'Valid' if result.valid else 'Invalid'}")
```
### Directory Validation
```python
from pathlib import Path
# Validate entire directory
results = client.validator.validate_directory(
Path("releases"),
version="4.3",
pattern="*.xml",
recursive=True
)
# Generate summary
valid_count = sum(1 for r in results.values() if r.valid)
print(f"Valid: {valid_count}/{len(results)}")
```
### Error Analysis
```python
# Group errors by severity
errors_by_severity = result.get_errors_by_severity()
for severity, errors in errors_by_severity.items():
print(f"{severity}: {len(errors)} errors")
# Group errors by line
errors_by_line = result.get_errors_by_line()
for line, errors in errors_by_line.items():
print(f"Line {line}: {len(errors)} errors")
# Filter specific errors
from ddex_workbench.utils import filter_errors
critical_errors = filter_errors(
result.errors,
severity="error",
rule_pattern="ERN.*"
)
```
### Generate Reports
```python
from ddex_workbench.utils import format_validation_report
# Text report
text_report = format_validation_report(result, format_type="text")
print(text_report)
# JSON report
json_report = format_validation_report(result, format_type="json")
with open("report.json", "w") as f:
f.write(json_report)
# CSV report
csv_report = format_validation_report(result, format_type="csv")
with open("report.csv", "w") as f:
f.write(csv_report)
```
### API Key Management
```python
# For authenticated endpoints (requires Firebase auth token)
auth_token = "your_firebase_auth_token"
# List API keys
keys = client.list_api_keys(auth_token)
for key in keys:
print(f"{key.name}: {key.request_count} requests")
# Create new API key
new_key = client.create_api_key("Production Key", auth_token)
print(f"New API key: {new_key.key}") # Save this! Only shown once
# Revoke API key
client.revoke_api_key(key_id, auth_token)
```
### Utility Functions
```python
from ddex_workbench.utils import (
detect_ern_version,
extract_message_id,
calculate_file_hash,
create_summary_statistics
)
# Detect version
version = detect_ern_version(xml_content)
print(f"Detected version: {version}")
# Extract message ID
message_id = extract_message_id(xml_content)
print(f"Message ID: {message_id}")
# Calculate file hash
file_hash = calculate_file_hash(Path("release.xml"))
print(f"SHA256: {file_hash}")
# Create summary statistics
results = [result1, result2, result3]
stats = create_summary_statistics(results)
print(f"Validity rate: {stats['validity_rate']:.1f}%")
```
## Command Line Interface
```bash
# Validate a file
ddex-validate release.xml --version 4.3 --profile AudioAlbum
# Validate directory
ddex-validate releases/ --version 4.3 --recursive
# Auto-detect version
ddex-validate release.xml --auto
# Generate report
ddex-validate release.xml --version 4.3 --report report.json --format json
```
## Configuration
```python
from ddex_workbench import DDEXClient
# Full configuration
client = DDEXClient(
api_key="ddex_your-api-key", # Optional API key
base_url="https://api.ddex-workbench.org/v1", # API endpoint
timeout=30, # Request timeout in seconds
max_retries=3, # Max retry attempts
retry_delay=1.0, # Initial retry delay
verify_ssl=True # SSL verification
)
# Update API key
client.set_api_key("new_api_key")
# Remove API key
client.clear_api_key()
```
## Error Handling
```python
from ddex_workbench.errors import (
DDEXError,
RateLimitError,
ValidationError,
AuthenticationError,
NotFoundError
)
try:
result = client.validate(xml_content, version="4.3")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
print(e.get_retry_message())
except AuthenticationError:
print("Invalid API key")
except ValidationError as e:
print(f"Validation error: {e.get_summary()}")
except DDEXError as e:
print(f"DDEX error: {e}")
```
## Advanced Features
### Context Manager
```python
# Automatic session cleanup
with DDEXClient(api_key="ddex_key") as client:
result = client.validate(xml_content, version="4.3")
# Session automatically closed after block
```
### Connection Pooling
The SDK automatically manages connection pooling for optimal performance:
```python
# Reuses connections for multiple requests
client = DDEXClient()
for xml_file in xml_files:
result = client.validate_file(xml_file, version="4.3")
```
### Retry Logic
Built-in exponential backoff retry for transient failures:
```python
# Automatically retries on 5xx errors
client = DDEXClient(max_retries=3, retry_delay=1.0)
```
## Supported Versions
- **ERN 4.3** (Recommended)
- **ERN 4.2**
- **ERN 3.8.2**
## Supported Profiles
- AudioAlbum
- AudioSingle
- Video
- Mixed
- Classical
- Ringtone
- DJ
- ReleaseByRelease (ERN 3.8.2 only)
## Requirements
- Python 3.7+
- requests 2.28+
## Development
```bash
# Clone repository
git clone https://github.com/daddykev/ddex-workbench.git
cd ddex-workbench/packages/python-sdk
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run tests with coverage
pytest --cov=ddex_workbench
# Run linting
flake8 ddex_workbench
black --check ddex_workbench
mypy ddex_workbench
# Format code
black ddex_workbench
isort ddex_workbench
# Run all checks with tox
tox
```
## Testing
```bash
# Run all tests
pytest
# Run specific test file
pytest tests/test_client.py
# Run with coverage
pytest --cov=ddex_workbench --cov-report=html
# Run integration tests
pytest -m integration
# Run tests in parallel
pytest -n auto
```
## Documentation
Full documentation available at [https://ddex-workbench.org/docs](https://ddex-workbench.org/docs)
## Contributing
We welcome contributions! Please see our [Contributing Guide](https://github.com/daddykev/ddex-workbench/blob/main/CONTRIBUTING.md) for details.
## Support
- 📚 [Documentation](https://ddex-workbench.org/docs)
- 💬 [GitHub Issues](https://github.com/daddykev/ddex-workbench/issues)
- 📧 [Email Support](mailto:support@ddex-workbench.org)
- 🌐 [Website](https://ddex-workbench.org)
## License
MIT License - see [LICENSE](LICENSE) for details.
## Related Projects
- [DDEX Workbench](https://ddex-workbench.org) - Web application
- [@ddex-workbench/sdk](https://www.npmjs.com/package/@ddex-workbench/sdk) - JavaScript/TypeScript SDK
- [DDEX Knowledge Base](https://kb.ddex.net) - Official DDEX documentation
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for version history.
---
Built with ❤️ for the music industry by the DDEX Workbench team.
Raw data
{
"_id": null,
"home_page": "https://github.com/daddykev/ddex-workbench",
"name": "ddex-workbench",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "ddex, ern, music, metadata, validation, xml, music-industry, sdk",
"author": "DDEX Workbench Contributors",
"author_email": "DDEX Workbench Contributors <support@ddex-workbench.org>",
"download_url": "https://files.pythonhosted.org/packages/23/06/24996780664045a55e14a5f32cd84f2b337b7580b852dd48cfd5dbd6e797/ddex_workbench-1.0.0.tar.gz",
"platform": null,
"description": "# DDEX Workbench Python SDK\n\n[](https://pypi.org/project/ddex-workbench/)\n[](https://pypi.org/project/ddex-workbench/)\n[](https://opensource.org/licenses/MIT)\n[](https://ddex-workbench.org/docs)\n\nOfficial Python SDK for [DDEX Workbench](https://ddex-workbench.org) - Open-source DDEX validation and processing tools for the music industry.\n\n## Features\n\n- \ud83d\ude80 **Simple API** - Intuitive methods for all DDEX operations\n- \ud83d\udd27 **Type Safety** - Full type hints and dataclass models\n- \ud83c\udf10 **Async Support** - Built-in connection pooling and retry logic\n- \ud83d\udcca **Batch Processing** - Validate multiple files efficiently\n- \ud83c\udfaf **Auto-detection** - Automatic ERN version detection\n- \ud83d\udcc8 **Detailed Reports** - Comprehensive validation reports in multiple formats\n- \ud83d\udd11 **API Key Management** - Built-in authentication handling\n\n## Installation\n\n```bash\npip install ddex-workbench\n```\n\nFor development:\n```bash\npip install ddex-workbench[dev]\n```\n\n## Quick Start\n\n```python\nfrom ddex_workbench import DDEXClient\n\n# Initialize client (API key optional for higher rate limits)\nclient = DDEXClient(api_key=\"ddex_your-api-key\")\n\n# Validate ERN XML\nwith open(\"release.xml\", \"r\") as f:\n xml_content = f.read()\n\nresult = client.validate(xml_content, version=\"4.3\", profile=\"AudioAlbum\")\n\nif result.valid:\n print(\"\u2705 Validation passed!\")\nelse:\n print(f\"\u274c Found {len(result.errors)} errors:\")\n for error in result.errors[:5]:\n print(f\" Line {error.line}: {error.message}\")\n```\n\n## Usage Examples\n\n### Basic Validation\n\n```python\nfrom ddex_workbench import DDEXClient\n\nclient = DDEXClient()\n\n# Validate with specific version\nresult = client.validate(xml_content, version=\"4.3\")\n\n# Validate with profile\nresult = client.validate(xml_content, version=\"4.3\", profile=\"AudioAlbum\")\n\n# Validate file directly\nresult = client.validate_file(\"path/to/release.xml\", version=\"4.3\")\n\n# Validate from URL\nresult = client.validate_url(\"https://example.com/release.xml\", version=\"4.3\")\n```\n\n### Auto-detect Version\n\n```python\n# Automatically detect ERN version\nresult = client.validator.validate_auto(xml_content)\nprint(f\"Detected version: {result.metadata.schema_version}\")\n```\n\n### Batch Processing\n\n```python\nfrom pathlib import Path\n\n# Validate all XML files in a directory\nxml_files = Path(\"releases\").glob(\"*.xml\")\n\nfor xml_file in xml_files:\n result = client.validate_file(xml_file, version=\"4.3\")\n status = \"\u2705 Valid\" if result.valid else f\"\u274c {len(result.errors)} errors\"\n print(f\"{xml_file.name}: {status}\")\n```\n\n### Parallel Batch Validation\n\n```python\n# Validate multiple files in parallel\nitems = [\n (xml1_content, \"4.3\", \"AudioAlbum\"),\n (xml2_content, \"4.3\", \"AudioSingle\"),\n (xml3_content, \"4.2\", None)\n]\n\nresults = client.validator.validate_batch(items, max_workers=5)\n\nfor i, result in enumerate(results):\n print(f\"File {i+1}: {'Valid' if result.valid else 'Invalid'}\")\n```\n\n### Directory Validation\n\n```python\nfrom pathlib import Path\n\n# Validate entire directory\nresults = client.validator.validate_directory(\n Path(\"releases\"),\n version=\"4.3\",\n pattern=\"*.xml\",\n recursive=True\n)\n\n# Generate summary\nvalid_count = sum(1 for r in results.values() if r.valid)\nprint(f\"Valid: {valid_count}/{len(results)}\")\n```\n\n### Error Analysis\n\n```python\n# Group errors by severity\nerrors_by_severity = result.get_errors_by_severity()\nfor severity, errors in errors_by_severity.items():\n print(f\"{severity}: {len(errors)} errors\")\n\n# Group errors by line\nerrors_by_line = result.get_errors_by_line()\nfor line, errors in errors_by_line.items():\n print(f\"Line {line}: {len(errors)} errors\")\n\n# Filter specific errors\nfrom ddex_workbench.utils import filter_errors\n\ncritical_errors = filter_errors(\n result.errors,\n severity=\"error\",\n rule_pattern=\"ERN.*\"\n)\n```\n\n### Generate Reports\n\n```python\nfrom ddex_workbench.utils import format_validation_report\n\n# Text report\ntext_report = format_validation_report(result, format_type=\"text\")\nprint(text_report)\n\n# JSON report\njson_report = format_validation_report(result, format_type=\"json\")\nwith open(\"report.json\", \"w\") as f:\n f.write(json_report)\n\n# CSV report\ncsv_report = format_validation_report(result, format_type=\"csv\")\nwith open(\"report.csv\", \"w\") as f:\n f.write(csv_report)\n```\n\n### API Key Management\n\n```python\n# For authenticated endpoints (requires Firebase auth token)\nauth_token = \"your_firebase_auth_token\"\n\n# List API keys\nkeys = client.list_api_keys(auth_token)\nfor key in keys:\n print(f\"{key.name}: {key.request_count} requests\")\n\n# Create new API key\nnew_key = client.create_api_key(\"Production Key\", auth_token)\nprint(f\"New API key: {new_key.key}\") # Save this! Only shown once\n\n# Revoke API key\nclient.revoke_api_key(key_id, auth_token)\n```\n\n### Utility Functions\n\n```python\nfrom ddex_workbench.utils import (\n detect_ern_version,\n extract_message_id,\n calculate_file_hash,\n create_summary_statistics\n)\n\n# Detect version\nversion = detect_ern_version(xml_content)\nprint(f\"Detected version: {version}\")\n\n# Extract message ID\nmessage_id = extract_message_id(xml_content)\nprint(f\"Message ID: {message_id}\")\n\n# Calculate file hash\nfile_hash = calculate_file_hash(Path(\"release.xml\"))\nprint(f\"SHA256: {file_hash}\")\n\n# Create summary statistics\nresults = [result1, result2, result3]\nstats = create_summary_statistics(results)\nprint(f\"Validity rate: {stats['validity_rate']:.1f}%\")\n```\n\n## Command Line Interface\n\n```bash\n# Validate a file\nddex-validate release.xml --version 4.3 --profile AudioAlbum\n\n# Validate directory\nddex-validate releases/ --version 4.3 --recursive\n\n# Auto-detect version\nddex-validate release.xml --auto\n\n# Generate report\nddex-validate release.xml --version 4.3 --report report.json --format json\n```\n\n## Configuration\n\n```python\nfrom ddex_workbench import DDEXClient\n\n# Full configuration\nclient = DDEXClient(\n api_key=\"ddex_your-api-key\", # Optional API key\n base_url=\"https://api.ddex-workbench.org/v1\", # API endpoint\n timeout=30, # Request timeout in seconds\n max_retries=3, # Max retry attempts\n retry_delay=1.0, # Initial retry delay\n verify_ssl=True # SSL verification\n)\n\n# Update API key\nclient.set_api_key(\"new_api_key\")\n\n# Remove API key\nclient.clear_api_key()\n```\n\n## Error Handling\n\n```python\nfrom ddex_workbench.errors import (\n DDEXError,\n RateLimitError,\n ValidationError,\n AuthenticationError,\n NotFoundError\n)\n\ntry:\n result = client.validate(xml_content, version=\"4.3\")\nexcept RateLimitError as e:\n print(f\"Rate limited. Retry after {e.retry_after} seconds\")\n print(e.get_retry_message())\nexcept AuthenticationError:\n print(\"Invalid API key\")\nexcept ValidationError as e:\n print(f\"Validation error: {e.get_summary()}\")\nexcept DDEXError as e:\n print(f\"DDEX error: {e}\")\n```\n\n## Advanced Features\n\n### Context Manager\n\n```python\n# Automatic session cleanup\nwith DDEXClient(api_key=\"ddex_key\") as client:\n result = client.validate(xml_content, version=\"4.3\")\n # Session automatically closed after block\n```\n\n### Connection Pooling\n\nThe SDK automatically manages connection pooling for optimal performance:\n\n```python\n# Reuses connections for multiple requests\nclient = DDEXClient()\nfor xml_file in xml_files:\n result = client.validate_file(xml_file, version=\"4.3\")\n```\n\n### Retry Logic\n\nBuilt-in exponential backoff retry for transient failures:\n\n```python\n# Automatically retries on 5xx errors\nclient = DDEXClient(max_retries=3, retry_delay=1.0)\n```\n\n## Supported Versions\n\n- **ERN 4.3** (Recommended)\n- **ERN 4.2**\n- **ERN 3.8.2**\n\n## Supported Profiles\n\n- AudioAlbum\n- AudioSingle\n- Video\n- Mixed\n- Classical\n- Ringtone\n- DJ\n- ReleaseByRelease (ERN 3.8.2 only)\n\n## Requirements\n\n- Python 3.7+\n- requests 2.28+\n\n## Development\n\n```bash\n# Clone repository\ngit clone https://github.com/daddykev/ddex-workbench.git\ncd ddex-workbench/packages/python-sdk\n\n# Install development dependencies\npip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Run tests with coverage\npytest --cov=ddex_workbench\n\n# Run linting\nflake8 ddex_workbench\nblack --check ddex_workbench\nmypy ddex_workbench\n\n# Format code\nblack ddex_workbench\nisort ddex_workbench\n\n# Run all checks with tox\ntox\n```\n\n## Testing\n\n```bash\n# Run all tests\npytest\n\n# Run specific test file\npytest tests/test_client.py\n\n# Run with coverage\npytest --cov=ddex_workbench --cov-report=html\n\n# Run integration tests\npytest -m integration\n\n# Run tests in parallel\npytest -n auto\n```\n\n## Documentation\n\nFull documentation available at [https://ddex-workbench.org/docs](https://ddex-workbench.org/docs)\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](https://github.com/daddykev/ddex-workbench/blob/main/CONTRIBUTING.md) for details.\n\n## Support\n\n- \ud83d\udcda [Documentation](https://ddex-workbench.org/docs)\n- \ud83d\udcac [GitHub Issues](https://github.com/daddykev/ddex-workbench/issues)\n- \ud83d\udce7 [Email Support](mailto:support@ddex-workbench.org)\n- \ud83c\udf10 [Website](https://ddex-workbench.org)\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n\n## Related Projects\n\n- [DDEX Workbench](https://ddex-workbench.org) - Web application\n- [@ddex-workbench/sdk](https://www.npmjs.com/package/@ddex-workbench/sdk) - JavaScript/TypeScript SDK\n- [DDEX Knowledge Base](https://kb.ddex.net) - Official DDEX documentation\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for version history.\n\n---\n\nBuilt with \u2764\ufe0f for the music industry by the DDEX Workbench team.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Official Python SDK for DDEX Workbench - Open-source DDEX validation tools",
"version": "1.0.0",
"project_urls": {
"Documentation": "https://ddex-workbench.org/docs",
"Homepage": "https://ddex-workbench.org",
"Issues": "https://github.com/daddykev/ddex-workbench/issues",
"Repository": "https://github.com/daddykev/ddex-workbench"
},
"split_keywords": [
"ddex",
" ern",
" music",
" metadata",
" validation",
" xml",
" music-industry",
" sdk"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "29f482b43bfe218586e41a85938520dca21d27d94ba9d6bf36798e342cccf6e9",
"md5": "0a0b325a2191208be475541588d26ca2",
"sha256": "da27fc0833b02539408b11c8139b2fae98b3292cdf1d26cc51b6ec69f1c04a3f"
},
"downloads": -1,
"filename": "ddex_workbench-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0a0b325a2191208be475541588d26ca2",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 21039,
"upload_time": "2025-08-10T14:05:07",
"upload_time_iso_8601": "2025-08-10T14:05:07.052246Z",
"url": "https://files.pythonhosted.org/packages/29/f4/82b43bfe218586e41a85938520dca21d27d94ba9d6bf36798e342cccf6e9/ddex_workbench-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "230624996780664045a55e14a5f32cd84f2b337b7580b852dd48cfd5dbd6e797",
"md5": "80fdd0f0fef0b17de4aa75b6df564d0a",
"sha256": "d9abe12207c1fe3a09bfd20fb117f417f82d760daf8b84199254fcc9ab77d61d"
},
"downloads": -1,
"filename": "ddex_workbench-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "80fdd0f0fef0b17de4aa75b6df564d0a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 32240,
"upload_time": "2025-08-10T14:05:08",
"upload_time_iso_8601": "2025-08-10T14:05:08.413990Z",
"url": "https://files.pythonhosted.org/packages/23/06/24996780664045a55e14a5f32cd84f2b337b7580b852dd48cfd5dbd6e797/ddex_workbench-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-10 14:05:08",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "daddykev",
"github_project": "ddex-workbench",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "ddex-workbench"
}