json_partial 0.2.1

Json fixing parser for imperfect json given by LLMs
Documentation
# README Improvement Plan

## Current Analysis
The current README has good content but needs better organization and visual hierarchy.

## Planned Improvements

[X] 1. Header Section
   - Added prominent title and description
   - Improved introduction with clear bullet points

[X] 2. Features Section
   - Converted to concise, structured format
   - Grouped features logically

[X] 3. Installation & Usage
   - Moved to Quick Start section
   - Added concise, practical examples
   - Improved code formatting

[ ] 4. API Documentation
   - Create a clearer structure for API docs
   - Add more descriptive headers
   - Improve code example formatting

[ ] 5. Error Handling Section
   - Add a new section about error recovery
   - Include practical examples
   - Show common error scenarios

[ ] 6. Contributing & License
   - Standardize these sections
   - Add clear contribution guidelines
   - Format license section properly

[ ] 7. Acknowledgments
   - Move to a proper section at the end
   - Format links consistently

## Visual Improvements
- Use consistent heading levels
- Add horizontal rules for section separation
- Use tables for structured information
- Add code block language hints
- Ensure consistent spacing

## Note
Keep existing content but reorganize for better flow and readability.


<src/lib.rs>
L1: use pyo3::prelude::*;
L2: use pyo3::exceptions::PyTypeError;
L3: 
L4: #[pyfunction]
L5: fn to_json_string(json: String) -> PyResult<String> {
L6:     let jsonish_value: json_partial::jsonish::Value =
L7:         json_partial::jsonish::parse(&json, json_partial::jsonish::ParseOptions::default())
L8:             .map_err(|e| {
L9:                 make_py_err(
L10:                     &json,
L11:                     format!("Failed to parse input into jsonish::Value: {}", e),
L12:                 )
L13:             })?;
L14: 
L15:     json_partial::jsonish::to_json_string(&jsonish_value).map_err(|e| make_py_err(&json, e))
L16: }
L17: 
L18: #[pyfunction]
L19: fn to_json_string_pretty(json: String) -> PyResult<String> {
L20:     let jsonish_value: json_partial::jsonish::Value =
L21:         json_partial::jsonish::parse(&json, json_partial::jsonish::ParseOptions::default())
L22:             .map_err(|e| {
L23:                 make_py_err(
L24:                     &json,
L25:                     format!("Failed to parse input into jsonish::Value: {}", e),
L26:                 )
L27:             })?;
L28: 
L29:     json_partial::jsonish::to_json_string_pretty(&jsonish_value).map_err(|e| make_py_err(&json, e))
L30: }
L31: 
L32: /// Unified helper function to convert errors into a PyTypeError.
L33: /// The function takes the original JSON string and an error message.
L34: fn make_py_err<E: std::fmt::Display>(json: &str, err: E) -> PyErr {
L35:     PyErr::new::<PyTypeError, _>(format!("original_string: {} , error: {}", json, err))
L36: }
L37: 
L38: /// Json Partial Module
L39: #[pymodule]
L40: pub fn jsonish(m: &Bound<'_, PyModule>) -> PyResult<()> {
L41:     m.add_function(wrap_pyfunction!(to_json_string, m)?)?;
L42:     m.add_function(wrap_pyfunction!(to_json_string_pretty, m)?)?;
L43:     m.add("__version__", env!("CARGO_PKG_VERSION"))?;
L44:     Ok(())
L45: }
L46: 
</src/lib.rs>

<tests/test_json_partial_py_pydantic.py>
L2: from pydantic import BaseModel
L3: # from json_partial_py import to_json_string, to_json_string_pretty
L4: # from json_partial_py.jsonish import to_json_string, to_json_string_pretty
L5: from jsonish import to_json_string, to_json_string_pretty
L6: 
L7: # Define a simple Pydantic model that matches the expected JSON structure.
L8: class Person(BaseModel):
L9:     name: str
L10:     age: int
L11: 
L12: # Example input: A malformed JSON wrapped in Markdown fences.
L13: MALFORMED_JSON = r"""
L14: ```json
L15: {"name": "Bob", "age": 25}
L16: ```
L17: """
L18: 
L19: # Example input: Valid JSON string.
L20: VALID_JSON = '{"name": "Alice", "age": 30}'
L21: 
L22: def test_pydantic_parsing_from_malformed_json():
L23:     """
L24:     Ensure that the JSON string returned by to_json_string from a malformed input
L25:     can be successfully parsed into a Pydantic model.
L26:     """
L27:     json_str = to_json_string(MALFORMED_JSON)
L28:     try:
L29:         # Use model_validate_json instead of parse_raw in Pydantic V2.
L30:         person = Person.model_validate_json(json_str)
L31:     except Exception as e:
L32:         pytest.fail(f"Pydantic failed to parse the JSON string from malformed input: {e}")
L33: 
L34:     assert person.name == "Bob"
L35:     assert person.age == 25
L36: 
L37: def test_pydantic_parsing_from_valid_json():
L38:     """
L39:     Ensure that valid JSON input processed by to_json_string can be parsed by Pydantic.
L40:     """
L41:     json_str = to_json_string(VALID_JSON)
L42:     try:
L43:         # Use model_validate_json instead of parse_raw in Pydantic V2.
L44:         person = Person.model_validate_json(json_str)
L45:     except Exception as e:
L46:         pytest.fail(f"Pydantic failed to parse the JSON string from valid input: {e}")
L47: 
L48:     assert person.name == "Alice"
L49:     assert person.age == 30
</tests/test_json_partial_py_pydantic.py>


<Cargo.toml>
L1: [package]
L2: name = "json_partial-python"
L3: version = "0.1.0"
L4: edition = "2021"
L5: authors = ["Abhishek Tripathi <abhishek.tripathi456@gmail.com"]
L6: 
L7: 
L8: # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
L9: [lib]
L10: name = "json_partial"
L11: crate-type = ["cdylib"]
L12: 
L13: [dependencies]
L14: pyo3 = { version = "0.23", features = ["auto-initialize"] }
L15: json_partial = {path = "../../"}
L16: 
</Cargo.toml>


<pyproject.toml>
L1: [build-system]
L2: requires = ["maturin>=1.8,<2.0"]
L3: build-backend = "maturin"
L4: 
L5: [project]
L6: name = "json_partial"
L7: requires-python = ">=3.8"
L8: classifiers = [
L9:   "Intended Audience :: Developers",
L10:   "Programming Language :: Python :: 3.10",
L11:   "Topic :: Scientific/Engineering :: Artificial Intelligence",
L12: ]
L13: keywords = ["structured outputs", "agents", "llm"]
L14: dynamic = ["version"]
L15: 
L16: [project.urls]
L17: Homepage = "https://github.com/TwistingTwists/json_partial"
L18: Source = "https://github.com/TwistingTwists/json_partial"
L19: 
L20: 
L21: # [project.optional-dependencies]
L22: # testing = ["pytest","pydantic"]
L23: 
L24: [tool.maturin]
L25: # python-source = "py_src"
L26: features = ["pyo3/extension-module"]
L27: module-name = "json_partial.jsonish"
L28: # module-name = "json_partial.jsonish"
L29: 
L30: # [tool.uv.config-settings]
L31: # # Faster feedback on Rust builds
L32: # build-args = ["--profile=dev"]
L33: 
L34: [tool.uv]
L35: cache-keys = ["pyproject.toml", "Cargo.toml", "src/*.rs"]
L36: 
L37: [dependency-groups]
L38: dev = [
L39:     "pydantic>=2.10.6",
L40:     "pytest>=8.3.4",
L41: ]
L42: 
L43: # [tool.uv.sources]
L44: # setup = { workspace = true }
L45: 
L46: # [tool.uv.workspace]
L47: # members = ["json_partial_py"]
L48: 
</pyproject.toml>