Skip to content

Commit 775fa2f

Browse files
committed
feat: Refactor and polish xml-lib for production readiness
This comprehensive refactoring makes xml-lib feel like a complete, polished Python library with significantly improved robustness, testability, and developer experience. ## Public API Improvements - **Define clear public API**: Added explicit `__all__` exports to xml_lib/__init__.py - **Comprehensive API documentation**: Created docs/api.md with detailed function signatures, parameters, return types, examples, and usage patterns - **Unified type definitions**: Made validator.ValidationResult the canonical type, improved ValidationError documentation, removed duplication ## Testing Enhancements - **API tests**: New tests/test_api.py with comprehensive coverage of public API functions (quick_validate, validate_xml, create_validator, lint_xml, publish_html) - **CLI integration tests**: New tests/test_cli_integration.py using CliRunner to test validate, publish, lint, diff, roundtrip, render-pptx, and phpify commands - **Streaming equivalence tests**: New tests/test_streaming_equivalence.py ensuring streaming and non-streaming modes produce identical ValidationResult - **Property-based tests**: Expanded Hypothesis tests for cross-file ID uniqueness, temporal/phase ordering invariants, schema validation, and guardrail policies - **Type stability tests**: Added tests ensuring public API types remain stable ## Testing Infrastructure - **Pytest markers**: Added 'property' marker to pytest.ini (aligned with README_NEW.md) - **Test markers**: Applied pytest.mark.property and pytest.mark.integration markers to appropriate test modules for better test organization - **Mutation testing**: Added .mutmut_config.py for mutation testing of core modules (validator.py, sanitize.py, linter.py, publisher.py, schema.py) ## Exception Hierarchy - **Coherent exceptions**: New xml_lib/exceptions.py with XMLLibError base class - **Specific exception types**: XMLConfigurationError, XMLFileNotFoundError, XMLParseError, XMLValidationError, XMLPublishingError, XMLTelemetryError - **Clear error handling**: Exceptions for "cannot start" conditions, result objects (ValidationResult, LintResult) for per-file issues - **Exported exceptions**: Added exceptions to xml_lib.__all__ for public use ## Documentation & Developer Experience - **CONTRIBUTING.md**: Comprehensive contributor guide with development setup, quality gates, testing guidelines, code style, and PR process - **Issue templates**: GitHub issue templates (bug_report.yml, feature_request.yml) with structured fields for better issue reporting - **API stability**: Documentation and tests ensuring types remain stable across versions ## Code Quality - **Enhanced docstrings**: Improved documentation for ValidationResult, ValidationError - **Type annotations**: Maintained strict typing discipline throughout - **Import organization**: Clean exports and re-exports for better API surface This refactoring addresses all requested improvements while maintaining backward compatibility and existing code style. The library now feels stable, predictable, and ready for production use. Resolves: #[issue-number-if-any]
1 parent 85a6aaa commit 775fa2f

File tree

15 files changed

+2912
-10
lines changed

15 files changed

+2912
-10
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Bug Report
2+
description: Report a bug or unexpected behavior
3+
title: "[Bug]: "
4+
labels: ["bug"]
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: |
9+
Thanks for taking the time to report a bug! Please fill out the information below.
10+
11+
- type: textarea
12+
id: description
13+
attributes:
14+
label: Bug Description
15+
description: A clear and concise description of the bug
16+
placeholder: What happened?
17+
validations:
18+
required: true
19+
20+
- type: textarea
21+
id: reproduce
22+
attributes:
23+
label: Steps to Reproduce
24+
description: Steps to reproduce the behavior
25+
placeholder: |
26+
1. Run command '...'
27+
2. With input file '...'
28+
3. See error
29+
validations:
30+
required: true
31+
32+
- type: textarea
33+
id: expected
34+
attributes:
35+
label: Expected Behavior
36+
description: What did you expect to happen?
37+
placeholder: Expected output or behavior
38+
validations:
39+
required: true
40+
41+
- type: textarea
42+
id: actual
43+
attributes:
44+
label: Actual Behavior
45+
description: What actually happened?
46+
placeholder: Actual output or error message
47+
validations:
48+
required: true
49+
50+
- type: textarea
51+
id: environment
52+
attributes:
53+
label: Environment
54+
description: Please provide information about your environment
55+
value: |
56+
- OS: [e.g., Ubuntu 22.04, macOS 13, Windows 11]
57+
- Python version: [e.g., 3.11.5]
58+
- xml-lib version: [e.g., 0.1.0]
59+
- Installation method: [e.g., pip, poetry]
60+
validations:
61+
required: true
62+
63+
- type: textarea
64+
id: logs
65+
attributes:
66+
label: Relevant Logs
67+
description: Please paste any relevant log output
68+
render: shell
69+
placeholder: Paste logs here
70+
71+
- type: textarea
72+
id: additional
73+
attributes:
74+
label: Additional Context
75+
description: Add any other context about the problem
76+
placeholder: Screenshots, sample files, etc.

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
blank_issues_enabled: true
2+
contact_links:
3+
- name: Question or Discussion
4+
url: https://github.com/farukalpay/xml-lib/discussions
5+
about: Ask questions or discuss ideas with the community
6+
- name: Documentation
7+
url: https://github.com/farukalpay/xml-lib/blob/main/README.md
8+
about: Read the documentation
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Feature Request
2+
description: Suggest a new feature or enhancement
3+
title: "[Feature]: "
4+
labels: ["enhancement"]
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: |
9+
Thanks for suggesting a feature! Please provide details below.
10+
11+
- type: textarea
12+
id: problem
13+
attributes:
14+
label: Problem Statement
15+
description: Is your feature request related to a problem? Please describe.
16+
placeholder: I'm frustrated when...
17+
validations:
18+
required: true
19+
20+
- type: textarea
21+
id: solution
22+
attributes:
23+
label: Proposed Solution
24+
description: Describe the solution you'd like
25+
placeholder: I would like xml-lib to...
26+
validations:
27+
required: true
28+
29+
- type: textarea
30+
id: alternatives
31+
attributes:
32+
label: Alternatives Considered
33+
description: Describe any alternative solutions or features you've considered
34+
placeholder: Alternative approaches...
35+
36+
- type: textarea
37+
id: use-case
38+
attributes:
39+
label: Use Case
40+
description: Describe your use case for this feature
41+
placeholder: |
42+
I need this feature because...
43+
Example workflow:
44+
1. ...
45+
2. ...
46+
validations:
47+
required: true
48+
49+
- type: textarea
50+
id: example
51+
attributes:
52+
label: Example Usage
53+
description: Show how you would use this feature
54+
render: python
55+
placeholder: |
56+
from xml_lib import new_feature
57+
58+
result = new_feature(...)
59+
60+
- type: checkboxes
61+
id: contribution
62+
attributes:
63+
label: Would you like to contribute this feature?
64+
description: Are you willing to submit a PR for this feature?
65+
options:
66+
- label: Yes, I'm willing to contribute this feature
67+
- label: I need help implementing this
68+
- label: I'm suggesting this for someone else to implement
69+
70+
- type: textarea
71+
id: additional
72+
attributes:
73+
label: Additional Context
74+
description: Add any other context, screenshots, or examples
75+
placeholder: Links to similar features in other libraries, etc.

.mutmut_config.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""Configuration for mutmut mutation testing.
2+
3+
Run mutation tests with:
4+
mutmut run --paths-to-mutate=xml_lib/
5+
6+
View results with:
7+
mutmut results
8+
mutmut html
9+
10+
Apply a specific mutation to see what changed:
11+
mutmut apply <id>
12+
"""
13+
14+
15+
def pre_mutation(context):
16+
"""Filter which files and lines to mutate.
17+
18+
Args:
19+
context: Mutation context with line, filename, etc.
20+
21+
Returns:
22+
True to allow mutation, False to skip
23+
"""
24+
# Skip test files
25+
if "test_" in context.filename or "/tests/" in context.filename:
26+
return False
27+
28+
# Skip __init__.py files (mostly imports)
29+
if context.filename.endswith("__init__.py"):
30+
return False
31+
32+
# Skip CLI files (hard to mutation test CLIs effectively)
33+
if "cli.py" in context.filename or "cli_new.py" in context.filename:
34+
return False
35+
36+
# Skip generated or vendored code
37+
if "/vendor/" in context.filename or "/generated/" in context.filename:
38+
return False
39+
40+
# Allow mutation for core modules
41+
return True
42+
43+
44+
# Paths to mutate (can also specify on command line)
45+
paths_to_mutate = [
46+
"xml_lib/validator.py",
47+
"xml_lib/sanitize.py",
48+
"xml_lib/linter.py",
49+
"xml_lib/publisher.py",
50+
"xml_lib/schema.py",
51+
"xml_lib/lifecycle.py",
52+
"xml_lib/guardrails.py",
53+
]
54+
55+
# Test command (pytest)
56+
runner = "pytest -x --tb=short -q"
57+
58+
# Directories to exclude
59+
exclude_patterns = [
60+
"tests/",
61+
"docs/",
62+
".venv/",
63+
"build/",
64+
"dist/",
65+
]

0 commit comments

Comments
 (0)