Metadata-Version: 2.4
Name: dtl-parser
Version: 1.3.1
Summary: DTL (Domain Transport Language) Parser - A type-safe data format with enum validation, autofix, and multi-format export
Author-email: Padam Sundar Kafle <padam@alifzetta.com>
Maintainer-email: Padam Sundar Kafle <padam@alifzetta.com>
License: MIT
Project-URL: Homepage, https://dtlaz.org
Project-URL: Documentation, https://dtlaz.org/docs.html
Project-URL: Repository, https://github.com/AlifZetta/dtl-parser-python
Project-URL: Changelog, https://github.com/AlifZetta/dtl-parser-python/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/AlifZetta/dtl-parser-python/issues
Keywords: dtl,parser,data-format,domain-transport-language,enum,validation,autofix,json,csv,healthcare,finance,web3,alifzetta
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup
Classifier: Topic :: File Formats
Classifier: Typing :: Typed
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Dynamic: license-file

# 🧬 DTL Parser

**Domain Transport Language SDK for Python**

[![PyPI version](https://badge.fury.io/py/dtl-parser.svg)](https://badge.fury.io/py/dtl-parser)
[![Python](https://img.shields.io/pypi/pyversions/dtl-parser.svg)](https://pypi.org/project/dtl-parser/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

🇦🇪 **Product of Dubai, Made in Emirates**

---

## ✨ Features

- **Full DTL Parsing** - Parse DTL files and strings with complete type support
- **Enum Validation** - Exact-match validation with up to 10 values per field
- **Autofix / Magic Corrections** - Automatically fix common errors
- **Fuzzy Matching** - Smart typo suggestions using Levenshtein distance
- **JSON/CSV Export** - Convert tables to JSON or CSV format
- **Programmatic Creation** - Create tables and documents in code
- **Type-Safe** - Full type hints for IDE support

---

## 📦 Installation

```bash
pip install dtl-parser
```

---

## 🚀 Quick Start

### Parse a DTL File

```python
from dtl_parser import DTLParser

parser = DTLParser()
doc = parser.parse_file("data.dtl")

# Access tables
for table in doc.tables:
    print(f"Table: {table.name}, Rows: {len(table.rows)}")
    for row in table.rows:
        print(row)
```

### Parse a DTL String

```python
from dtl_parser import DTLParser

dtl_content = """
@dtlv1.0^dtWEB^pMyApp^c0^s0^w0^hash
@sec^none^0x0^none^0

USERS|id:s,name:s,role:e(admin,user,guest),status:e(active,inactive)|2|S0|W0|C0
U001|Alice|admin|active
U002|Bob|user|active
"""

parser = DTLParser()
doc = parser.parse(dtl_content)

users = doc.get_table("USERS")
for row in users.rows:
    print(f"{row['name']} is a {row['role']}")
```

---

## ✅ Validation

```python
from dtl_parser import DTLParser

parser = DTLParser()
doc = parser.parse_file("data.dtl")

# Validate and get errors
errors = doc.validate()

for error in errors:
    print(f"[{error.severity.value}] Line {error.line}: {error.message}")
    if error.suggestion:
        print(f"  Suggestion: {error.suggestion}")
```

---

## 🔧 Autofix

Automatically fix common errors like typos, format issues, and row count mismatches:

```python
from dtl_parser import DTLParser

dtl_with_errors = """
@dtlv1.0^dtWEB^pDemo^c0^s0^w0^hash
@sec^none^0x0^none^0

users|id:s,status:e(active,inactive,pending)|2|S0|W0|C0
U001|actve
U002|pendng
U003|inactive
"""

parser = DTLParser()
doc = parser.parse(dtl_with_errors)

# Apply autofix
fixed_doc, changes = doc.autofix()

for change in changes:
    print(f"✨ {change}")

# Output:
# ✨ Fixed table name case: users → USERS
# ✨ Fixed row count in USERS: 2 → 3
# ✨ Fixed USERS[0].status: 'actve' → 'active'
# ✨ Fixed USERS[1].status: 'pendng' → 'pending'
```

### What Autofix Corrects

| Issue | Before | After |
|-------|--------|-------|
| Row count mismatch | `\|2\|` (actual: 3) | `\|3\|` |
| Table name case | `users` | `USERS` |
| Boolean values | `true`, `yes`, `on` | `1` |
| Boolean values | `false`, `no`, `off` | `0` |
| Enum typos | `pendng` | `pending` |
| Date format (US) | `01/15/2025` | `2025-01-15` |
| Date format (EU) | `15.01.2025` | `2025-01-15` |
| Timestamp format | `2025-01-15 10:30:00` | `2025-01-15T10:30:00Z` |

---

## 🏭 Create Tables Programmatically

```python
from dtl_parser import create_table, create_document

# Create a table with enum fields
orders = create_table("ORDERS", {
    "id": "s",
    "customer": "s",
    "status": "e(pending,confirmed,shipped,delivered)",
    "priority": "e(low,medium,high,urgent)",
    "total": "f",
    "created": "D"
})

# Add rows
orders.add_row({
    "id": "ORD-001",
    "customer": "Alice",
    "status": "pending",
    "priority": "high",
    "total": 99.99,
    "created": "2025-01-15"
})

orders.add_row({
    "id": "ORD-002",
    "customer": "Bob",
    "status": "shipped",
    "priority": "medium",
    "total": 149.50,
    "created": "2025-01-14"
})

# Create document and add table
doc = create_document(domain="dtWEB")
doc.add_table(orders)

# Export to DTL
print(doc.to_dtl())
```

---

## 📤 Export Formats

### To JSON

```python
# Table to JSON
json_data = table.to_json()
print(json.dumps(json_data, indent=2))

# Document to JSON
doc_json = doc.to_json()
```

### To CSV

```python
csv_data = table.to_csv()
print(csv_data)

# With custom delimiter
tsv_data = table.to_csv(delimiter="\t")
```

### Back to DTL

```python
dtl_string = doc.to_dtl()
print(dtl_string)
```

---

## 📊 DTL Data Types

| Type | Code | Description | Example |
|------|------|-------------|---------|
| String | `s` | Text value | `Hello World` |
| Integer | `i` | Whole number | `42` |
| Float | `f` | Decimal number | `3.14` |
| Boolean | `b` | 0 or 1 | `1` |
| Date | `D` | YYYY-MM-DD | `2025-01-15` |
| Timestamp | `T` | ISO 8601 | `2025-01-15T10:30:00Z` |
| UUID | `u` | Unique ID | `550e8400-e29b-...` |
| JSON | `j` | Embedded JSON | `{"key":"value"}` |
| Array | `a(x)` | List of type x | `a,b,c` |
| **Enum** | `e(...)` | Exact match | `e(low,medium,high)` |

---

## 🔍 Fuzzy Matching

The `find_closest_match` function uses Levenshtein distance to suggest corrections:

```python
from dtl_parser import find_closest_match

options = ["pending", "processing", "shipped", "delivered"]

# Find closest match
suggestion = find_closest_match("pendng", options)
print(suggestion)  # "pending"

suggestion = find_closest_match("shiped", options)
print(suggestion)  # "shipped"
```

---

## 🏥 Domain Examples

### Healthcare (dtHC)

```python
patients = create_table("PATIENTS", {
    "mrn": "s",
    "name": "s",
    "gender": "e(M,F,O)",
    "blood_type": "e(A+,A-,B+,B-,AB+,AB-,O+,O-)",
    "status": "e(active,discharged,deceased)"
}, security="S2")  # HIPAA compliant
```

### Finance (dtFN)

```python
transactions = create_table("TRANSACTIONS", {
    "id": "u",
    "type": "e(deposit,withdrawal,transfer)",
    "currency": "e(USD,EUR,GBP,AED)",
    "amount": "f",
    "status": "e(pending,completed,failed)"
}, web3="W1")  # With blockchain signature
```

---

## 📜 License

MIT License - see [LICENSE](LICENSE) file.

---

## 👤 Author

**Padam Sundar Kafle**  
Lead Architect, DTL & AlifZetta

---

## 🔗 Links

- **Website:** [dtlaz.org](https://dtlaz.org)
- **Documentation:** [dtlaz.org/docs](https://dtlaz.org/docs.html)
- **GitHub:** [github.com/AlifZetta/dtl-parser-python](https://github.com/AlifZetta/dtl-parser-python)

---

🇦🇪 **Product of Dubai, Made in Emirates**

*Born in Dubai, Built for the World*
