Skip to content

Commit 85a6aaa

Browse files
authored
Merge pull request #12 from farukalpay/claude/improve-lib-api-usability-011CV5rUL2swTFZeF59XpWCE
Refactor lib/ into clean, documented public API
2 parents 0cc0221 + ecb2fb7 commit 85a6aaa

File tree

8 files changed

+2141
-4
lines changed

8 files changed

+2141
-4
lines changed

README.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,190 @@ xml-lib pipeline <Tab> # Shows: run list dry-run
254254

255255
**Learn More:** [Interactive Guide](docs/INTERACTIVE_GUIDE.md) | [Examples](examples/interactive/)
256256

257+
## Programmatic Usage (Python API)
258+
259+
xml-lib provides a clean, well-documented Python API for integrating XML validation, linting, and publishing into your own applications and scripts.
260+
261+
### Quick Start
262+
263+
```python
264+
from xml_lib import quick_validate
265+
266+
# Validate a project with sensible defaults
267+
result = quick_validate("my-xml-project")
268+
269+
if result.is_valid:
270+
print(f"✓ All {len(result.validated_files)} files are valid!")
271+
else:
272+
print(f"✗ Found {len(result.errors)} errors:")
273+
for error in result.errors:
274+
print(f" {error.file}:{error.line} - {error.message}")
275+
```
276+
277+
### Common Patterns
278+
279+
**1. Basic Validation**
280+
281+
```python
282+
from xml_lib import validate_xml
283+
284+
result = validate_xml(
285+
"my-project",
286+
schemas_dir="schemas",
287+
guardrails_dir="lib/guardrails",
288+
enable_streaming=True, # Efficient for large files
289+
show_progress=True, # Show progress indicator
290+
)
291+
292+
print(f"Valid: {result.is_valid}")
293+
print(f"Files: {len(result.validated_files)}")
294+
print(f"Errors: {len(result.errors)}")
295+
```
296+
297+
**2. Batch Processing**
298+
299+
```python
300+
from xml_lib import create_validator
301+
from pathlib import Path
302+
303+
# Create validator once, reuse for multiple projects
304+
validator = create_validator(
305+
schemas_dir="schemas",
306+
guardrails_dir="lib/guardrails",
307+
)
308+
309+
# Validate multiple projects efficiently
310+
projects = [Path("project1"), Path("project2"), Path("project3")]
311+
for project in projects:
312+
result = validator.validate_project(project)
313+
print(f"{project}: {'' if result.is_valid else ''}")
314+
```
315+
316+
**3. Linting**
317+
318+
```python
319+
from xml_lib import lint_xml
320+
321+
# Lint for formatting and security issues
322+
result = lint_xml(
323+
"my-project",
324+
check_indentation=True,
325+
check_external_entities=True, # Check for XXE vulnerabilities
326+
indent_size=2,
327+
)
328+
329+
print(f"Checked {result.files_checked} files")
330+
print(f"Errors: {result.error_count}, Warnings: {result.warning_count}")
331+
332+
for issue in result.issues:
333+
print(issue.format_text())
334+
```
335+
336+
**4. Custom Workflows**
337+
338+
```python
339+
from xml_lib import lint_xml, validate_xml
340+
341+
# Stage 1: Lint files
342+
lint_result = lint_xml("project")
343+
if lint_result.has_errors:
344+
print("✗ Linting failed!")
345+
exit(1)
346+
347+
# Stage 2: Validate against schemas
348+
validation_result = validate_xml("project", enable_streaming=True)
349+
if not validation_result.is_valid:
350+
print("✗ Validation failed!")
351+
exit(1)
352+
353+
# Stage 3: Generate artifacts (only if validation passed)
354+
print("✓ All checks passed - generating artifacts...")
355+
```
356+
357+
### API Reference
358+
359+
The public API includes:
360+
361+
**High-level functions** (recommended for most users):
362+
- `quick_validate()` - Validate with automatic discovery and defaults
363+
- `validate_xml()` - Full control over validation options
364+
- `create_validator()` - Create reusable validator instances
365+
- `lint_xml()` - Lint files for formatting and security
366+
- `publish_html()` - Publish XML to HTML (requires XSLT templates)
367+
368+
**Core classes** (for advanced usage):
369+
- `Validator` - Main validation engine
370+
- `ValidationResult` - Validation results with errors/warnings
371+
- `XMLLinter` - XML linting engine
372+
- `LintResult` - Linting results
373+
- `Publisher` - HTML publishing engine
374+
375+
**For detailed documentation:**
376+
377+
```python
378+
import xml_lib
379+
help(xml_lib) # Package overview
380+
help(xml_lib.quick_validate) # Function details
381+
help(xml_lib.Validator) # Class documentation
382+
```
383+
384+
### Examples
385+
386+
See [`examples/programmatic/`](examples/programmatic/) for complete, runnable examples:
387+
388+
1. **[Basic Validation](examples/programmatic/01_basic_validation.py)** - Getting started, error handling, progress indicators
389+
2. **[Batch Processing](examples/programmatic/02_batch_processing.py)** - Validating multiple projects, generating reports
390+
3. **[Custom Workflow](examples/programmatic/03_custom_workflow.py)** - Multi-stage pipeline with conditional logic
391+
392+
Run any example:
393+
394+
```bash
395+
python examples/programmatic/01_basic_validation.py
396+
```
397+
398+
### Installation
399+
400+
```bash
401+
# From PyPI (when published)
402+
pip install xml-lib
403+
404+
# From source
405+
git clone https://github.com/farukalpay/xml-lib.git
406+
cd xml-lib
407+
pip install -e .
408+
```
409+
410+
### Integration Examples
411+
412+
**Pre-commit Hook:**
413+
414+
```python
415+
#!/usr/bin/env python3
416+
from xml_lib import quick_validate
417+
import sys
418+
419+
result = quick_validate(".")
420+
sys.exit(0 if result.is_valid else 1)
421+
```
422+
423+
**pytest Integration:**
424+
425+
```python
426+
def test_xml_files_are_valid():
427+
from xml_lib import quick_validate
428+
result = quick_validate(".")
429+
assert result.is_valid, f"Found {len(result.errors)} errors"
430+
```
431+
432+
**GitHub Actions:**
433+
434+
```yaml
435+
- name: Validate XML
436+
run: |
437+
pip install xml-lib
438+
python -c "from xml_lib import quick_validate; import sys; sys.exit(0 if quick_validate('.').is_valid else 1)"
439+
```
440+
257441
## New Features
258442
259443
### 🚀 Streaming Validation (for Large Files)
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python3
2+
"""Basic XML Validation Example - Getting Started with xml-lib
3+
4+
This example demonstrates the simplest way to use xml-lib programmatically
5+
to validate XML files in your Python projects.
6+
7+
Use Cases:
8+
- Quick validation checks in development scripts
9+
- Pre-commit hooks for XML files
10+
- CI/CD integration for XML validation
11+
- Simple command-line tools
12+
13+
Requirements:
14+
- pip install xml-lib
15+
"""
16+
17+
from pathlib import Path
18+
19+
from xml_lib import quick_validate
20+
21+
22+
def main() -> None:
23+
"""Run a basic validation example."""
24+
print("=" * 70)
25+
print("XML-Lib: Basic Validation Example")
26+
print("=" * 70)
27+
print()
28+
29+
# Example 1: Quick validation with defaults
30+
print("Example 1: Quick validation with sensible defaults")
31+
print("-" * 70)
32+
33+
# This assumes your project has:
34+
# - schemas/ directory with .rng and .sch files
35+
# - lib/guardrails/ directory (can be empty)
36+
# - XML files to validate
37+
38+
project_path = Path(".") # Current directory
39+
40+
print(f"Validating project: {project_path.absolute()}")
41+
print()
42+
43+
result = quick_validate(project_path)
44+
45+
# Check validation results
46+
if result.is_valid:
47+
print("✓ Validation successful!")
48+
print(f" - Validated {len(result.validated_files)} files")
49+
print(f" - Generated {len(result.checksums)} checksums")
50+
51+
if result.validated_files:
52+
print(f"\nValidated files:")
53+
for file in result.validated_files[:5]: # Show first 5
54+
print(f" - {file}")
55+
if len(result.validated_files) > 5:
56+
print(f" ... and {len(result.validated_files) - 5} more")
57+
58+
else:
59+
print("✗ Validation failed!")
60+
print(f" - Found {len(result.errors)} errors")
61+
print(f" - Found {len(result.warnings)} warnings")
62+
63+
print("\nErrors:")
64+
for error in result.errors[:5]: # Show first 5 errors
65+
print(f" {error.file}:{error.line or '?'}")
66+
print(f" {error.message}")
67+
print(f" [Rule: {error.rule}]")
68+
print()
69+
70+
if len(result.errors) > 5:
71+
print(f" ... and {len(result.errors) - 5} more errors")
72+
73+
# Example 2: With progress indicator for large projects
74+
print()
75+
print("Example 2: Validation with progress indicator")
76+
print("-" * 70)
77+
78+
result = quick_validate(project_path, show_progress=True)
79+
80+
print(f"Result: {'✓ Valid' if result.is_valid else '✗ Invalid'}")
81+
82+
# Example 3: Accessing validation metadata
83+
print()
84+
print("Example 3: Accessing validation metadata")
85+
print("-" * 70)
86+
87+
print(f"Timestamp: {result.timestamp}")
88+
print(f"Used streaming: {result.used_streaming}")
89+
90+
if result.checksums:
91+
print(f"\nFile checksums (SHA-256):")
92+
for file, checksum in list(result.checksums.items())[:3]:
93+
print(f" {Path(file).name}: {checksum[:16]}...")
94+
95+
print()
96+
print("=" * 70)
97+
print("Done! See examples/programmatic/02_batch_processing.py for more.")
98+
print("=" * 70)
99+
100+
101+
if __name__ == "__main__":
102+
main()

0 commit comments

Comments
 (0)