laga 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- laga-0.1.1/.github/ISSUE_TEMPLATE/bug_report.yml +148 -0
- laga-0.1.1/.github/ISSUE_TEMPLATE/config.yml +8 -0
- laga-0.1.1/.github/ISSUE_TEMPLATE/feature_request.yml +124 -0
- laga-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- laga-0.1.1/.github/workflows/ci.yml +47 -0
- laga-0.1.1/.github/workflows/release.yml +39 -0
- laga-0.1.1/.gitignore +13 -0
- laga-0.1.1/.pre-commit-config.yaml +25 -0
- laga-0.1.1/CHANGELOG.md +29 -0
- laga-0.1.1/CODE_OF_CONDUCT.md +23 -0
- laga-0.1.1/CONTRIBUTING.md +26 -0
- laga-0.1.1/LICENSE +21 -0
- laga-0.1.1/Makefile +20 -0
- laga-0.1.1/PKG-INFO +147 -0
- laga-0.1.1/README.md +79 -0
- laga-0.1.1/SECURITY.md +13 -0
- laga-0.1.1/benchmarks/benchmark_repair.py +31 -0
- laga-0.1.1/docs/api.md +25 -0
- laga-0.1.1/docs/contributing.md +10 -0
- laga-0.1.1/docs/index.md +25 -0
- laga-0.1.1/docs/mkdocs.yml +9 -0
- laga-0.1.1/docs/usage.md +25 -0
- laga-0.1.1/examples/cleanup_llm_output.py +21 -0
- laga-0.1.1/examples/config_repair.py +13 -0
- laga-0.1.1/pyproject.toml +120 -0
- laga-0.1.1/src/laga/__init__.py +8 -0
- laga-0.1.1/src/laga/_version.py +3 -0
- laga-0.1.1/src/laga/core.py +385 -0
- laga-0.1.1/src/laga/errors.py +18 -0
- laga-0.1.1/src/laga/py.typed +0 -0
- laga-0.1.1/src/laga/tokenizer.py +192 -0
- laga-0.1.1/tests/test_core.py +91 -0
- laga-0.1.1/tests/test_internal.py +270 -0
- laga-0.1.1/tests/test_property_based.py +32 -0
- laga-0.1.1/tests/test_regressions.py +47 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report a reproducible bug in laga with enough detail to diagnose and fix it.
|
|
3
|
+
title: "Bug: "
|
|
4
|
+
labels:
|
|
5
|
+
- bug
|
|
6
|
+
body:
|
|
7
|
+
- type: markdown
|
|
8
|
+
attributes:
|
|
9
|
+
value: |
|
|
10
|
+
Thanks for taking the time to report a bug.
|
|
11
|
+
|
|
12
|
+
Please provide a minimal, reproducible example and include the exact input that triggers the problem.
|
|
13
|
+
|
|
14
|
+
- type: dropdown
|
|
15
|
+
id: area
|
|
16
|
+
attributes:
|
|
17
|
+
label: Affected area
|
|
18
|
+
description: Pick the part of laga that seems broken.
|
|
19
|
+
options:
|
|
20
|
+
- Public API
|
|
21
|
+
- CLI
|
|
22
|
+
- Parser / repair behavior
|
|
23
|
+
- Tokenizer
|
|
24
|
+
- Documentation
|
|
25
|
+
- Packaging / release
|
|
26
|
+
- Tests / CI
|
|
27
|
+
- Other
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
|
|
31
|
+
- type: dropdown
|
|
32
|
+
id: severity
|
|
33
|
+
attributes:
|
|
34
|
+
label: Severity
|
|
35
|
+
description: How much does this affect your use case?
|
|
36
|
+
options:
|
|
37
|
+
- Blocking
|
|
38
|
+
- High
|
|
39
|
+
- Medium
|
|
40
|
+
- Low
|
|
41
|
+
- Cosmetic
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
|
|
45
|
+
- type: textarea
|
|
46
|
+
id: summary
|
|
47
|
+
attributes:
|
|
48
|
+
label: Summary
|
|
49
|
+
description: Describe the bug in one or two sentences.
|
|
50
|
+
placeholder: laga returns the wrong structure when ...
|
|
51
|
+
validations:
|
|
52
|
+
required: true
|
|
53
|
+
|
|
54
|
+
- type: textarea
|
|
55
|
+
id: input
|
|
56
|
+
attributes:
|
|
57
|
+
label: Input that triggers the bug
|
|
58
|
+
description: Paste the smallest possible text sample that reproduces the issue.
|
|
59
|
+
render: text
|
|
60
|
+
placeholder: |
|
|
61
|
+
{name: 'Ada', roles: ['admin',],}
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
|
|
65
|
+
- type: textarea
|
|
66
|
+
id: expected
|
|
67
|
+
attributes:
|
|
68
|
+
label: Expected result
|
|
69
|
+
description: What should laga have returned or done instead?
|
|
70
|
+
placeholder: The input should be repaired to valid JSON and parse to ...
|
|
71
|
+
validations:
|
|
72
|
+
required: true
|
|
73
|
+
|
|
74
|
+
- type: textarea
|
|
75
|
+
id: actual
|
|
76
|
+
attributes:
|
|
77
|
+
label: Actual result
|
|
78
|
+
description: What happened instead. Include the exact error message or unexpected output.
|
|
79
|
+
placeholder: laga raised LagaError: ...
|
|
80
|
+
validations:
|
|
81
|
+
required: true
|
|
82
|
+
|
|
83
|
+
- type: textarea
|
|
84
|
+
id: steps
|
|
85
|
+
attributes:
|
|
86
|
+
label: Steps to reproduce
|
|
87
|
+
description: List the exact steps so someone else can reproduce the issue.
|
|
88
|
+
placeholder: |
|
|
89
|
+
1. Install laga
|
|
90
|
+
2. Run laga.repair(...) with the sample above
|
|
91
|
+
3. Observe the failure
|
|
92
|
+
validations:
|
|
93
|
+
required: true
|
|
94
|
+
|
|
95
|
+
- type: textarea
|
|
96
|
+
id: environment
|
|
97
|
+
attributes:
|
|
98
|
+
label: Environment
|
|
99
|
+
description: Share the runtime details that matter for reproduction.
|
|
100
|
+
placeholder: |
|
|
101
|
+
Python:
|
|
102
|
+
OS:
|
|
103
|
+
laga version:
|
|
104
|
+
Installation method:
|
|
105
|
+
Shell or editor:
|
|
106
|
+
validations:
|
|
107
|
+
required: true
|
|
108
|
+
|
|
109
|
+
- type: dropdown
|
|
110
|
+
id: reproducibility
|
|
111
|
+
attributes:
|
|
112
|
+
label: Reproducibility
|
|
113
|
+
description: How often does this happen?
|
|
114
|
+
options:
|
|
115
|
+
- Always
|
|
116
|
+
- Sometimes
|
|
117
|
+
- Rarely
|
|
118
|
+
- Only once
|
|
119
|
+
validations:
|
|
120
|
+
required: true
|
|
121
|
+
|
|
122
|
+
- type: textarea
|
|
123
|
+
id: workaround
|
|
124
|
+
attributes:
|
|
125
|
+
label: Workaround
|
|
126
|
+
description: If you found a workaround, describe it here.
|
|
127
|
+
placeholder: Using strict=False avoids the failure, but ...
|
|
128
|
+
|
|
129
|
+
- type: textarea
|
|
130
|
+
id: extra
|
|
131
|
+
attributes:
|
|
132
|
+
label: Additional context
|
|
133
|
+
description: Add logs, stack traces, screenshots, or notes that may help.
|
|
134
|
+
placeholder: Any extra detail that could narrow down the root cause.
|
|
135
|
+
|
|
136
|
+
- type: checkboxes
|
|
137
|
+
id: checklist
|
|
138
|
+
attributes:
|
|
139
|
+
label: Confirmation checklist
|
|
140
|
+
options:
|
|
141
|
+
- label: I have searched existing issues and did not find a duplicate.
|
|
142
|
+
required: true
|
|
143
|
+
- label: I have reduced the example to the smallest reproducible input I could.
|
|
144
|
+
required: true
|
|
145
|
+
- label: I am using the latest released version or I can explain why I am not.
|
|
146
|
+
required: true
|
|
147
|
+
- label: I am comfortable sharing the sample input publicly in this issue.
|
|
148
|
+
required: true
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: Security reporting
|
|
4
|
+
url: https://github.com/olaflaitinen/laga/security/advisories
|
|
5
|
+
about: Use this for private security reports only.
|
|
6
|
+
- name: Project repository
|
|
7
|
+
url: https://github.com/olaflaitinen/laga
|
|
8
|
+
about: Review the README, docs, and existing issues before opening a new ticket.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest an improvement, capability, or workflow enhancement for laga.
|
|
3
|
+
title: "Feature: "
|
|
4
|
+
labels:
|
|
5
|
+
- enhancement
|
|
6
|
+
body:
|
|
7
|
+
- type: markdown
|
|
8
|
+
attributes:
|
|
9
|
+
value: |
|
|
10
|
+
Thanks for suggesting an improvement.
|
|
11
|
+
|
|
12
|
+
The most useful requests explain the current limitation, the user impact, and the exact behavior you want.
|
|
13
|
+
|
|
14
|
+
- type: dropdown
|
|
15
|
+
id: area
|
|
16
|
+
attributes:
|
|
17
|
+
label: Area
|
|
18
|
+
description: Which part of laga would this affect?
|
|
19
|
+
options:
|
|
20
|
+
- Public API
|
|
21
|
+
- CLI
|
|
22
|
+
- Parser / repair behavior
|
|
23
|
+
- Tokenizer
|
|
24
|
+
- Documentation
|
|
25
|
+
- Packaging / release
|
|
26
|
+
- Tests / CI
|
|
27
|
+
- New capability
|
|
28
|
+
- Other
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
31
|
+
|
|
32
|
+
- type: dropdown
|
|
33
|
+
id: priority
|
|
34
|
+
attributes:
|
|
35
|
+
label: Priority
|
|
36
|
+
description: How important is this request to you?
|
|
37
|
+
options:
|
|
38
|
+
- Critical
|
|
39
|
+
- High
|
|
40
|
+
- Medium
|
|
41
|
+
- Low
|
|
42
|
+
- Nice to have
|
|
43
|
+
validations:
|
|
44
|
+
required: true
|
|
45
|
+
|
|
46
|
+
- type: textarea
|
|
47
|
+
id: problem
|
|
48
|
+
attributes:
|
|
49
|
+
label: Problem statement
|
|
50
|
+
description: Describe the limitation or pain point you are trying to solve.
|
|
51
|
+
placeholder: Today I have to ... which causes ...
|
|
52
|
+
validations:
|
|
53
|
+
required: true
|
|
54
|
+
|
|
55
|
+
- type: textarea
|
|
56
|
+
id: goal
|
|
57
|
+
attributes:
|
|
58
|
+
label: Desired outcome
|
|
59
|
+
description: Describe the behavior, output, or workflow you want.
|
|
60
|
+
placeholder: laga should be able to ...
|
|
61
|
+
validations:
|
|
62
|
+
required: true
|
|
63
|
+
|
|
64
|
+
- type: textarea
|
|
65
|
+
id: user_story
|
|
66
|
+
attributes:
|
|
67
|
+
label: User story
|
|
68
|
+
description: Optional, but helpful if you can describe who needs this and why.
|
|
69
|
+
placeholder: As a ... I want ... so that ...
|
|
70
|
+
|
|
71
|
+
- type: textarea
|
|
72
|
+
id: examples
|
|
73
|
+
attributes:
|
|
74
|
+
label: Example input or API shape
|
|
75
|
+
description: Show a concrete example of the proposed behavior.
|
|
76
|
+
render: text
|
|
77
|
+
placeholder: |
|
|
78
|
+
laga.repair('{name: "Ada"}')
|
|
79
|
+
# could optionally return ...
|
|
80
|
+
|
|
81
|
+
- type: textarea
|
|
82
|
+
id: alternatives
|
|
83
|
+
attributes:
|
|
84
|
+
label: Alternatives considered
|
|
85
|
+
description: Describe other approaches you evaluated and why they were not enough.
|
|
86
|
+
placeholder: |
|
|
87
|
+
1. Use a post-processing step
|
|
88
|
+
2. Wrap laga in custom logic
|
|
89
|
+
3. Change upstream data generation
|
|
90
|
+
|
|
91
|
+
- type: textarea
|
|
92
|
+
id: tradeoffs
|
|
93
|
+
attributes:
|
|
94
|
+
label: Tradeoffs and constraints
|
|
95
|
+
description: Mention any compatibility, performance, or maintenance concerns we should keep in mind.
|
|
96
|
+
placeholder: This should remain backwards compatible with ...
|
|
97
|
+
|
|
98
|
+
- type: textarea
|
|
99
|
+
id: acceptance
|
|
100
|
+
attributes:
|
|
101
|
+
label: Acceptance criteria
|
|
102
|
+
description: What would make this feature request complete?
|
|
103
|
+
placeholder: |
|
|
104
|
+
- Works with ...
|
|
105
|
+
- Does not break ...
|
|
106
|
+
- Includes tests/docs ...
|
|
107
|
+
|
|
108
|
+
- type: textarea
|
|
109
|
+
id: context
|
|
110
|
+
attributes:
|
|
111
|
+
label: Additional context
|
|
112
|
+
description: Add links, screenshots, related issues, or any notes that help frame the request.
|
|
113
|
+
|
|
114
|
+
- type: checkboxes
|
|
115
|
+
id: checklist
|
|
116
|
+
attributes:
|
|
117
|
+
label: Confirmation checklist
|
|
118
|
+
options:
|
|
119
|
+
- label: I searched existing issues and discussions before opening this request.
|
|
120
|
+
required: true
|
|
121
|
+
- label: I explained the problem and not just the solution.
|
|
122
|
+
required: true
|
|
123
|
+
- label: I included a concrete example or user story.
|
|
124
|
+
required: true
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
Describe the change and why it is needed. Link any related issue or discussion.
|
|
4
|
+
|
|
5
|
+
## Testing
|
|
6
|
+
|
|
7
|
+
- [ ] `make lint`
|
|
8
|
+
- [ ] `make typecheck`
|
|
9
|
+
- [ ] `make test`
|
|
10
|
+
- [ ] `make build`
|
|
11
|
+
|
|
12
|
+
## Notes
|
|
13
|
+
|
|
14
|
+
Add any follow-up work, release notes, or migration notes here.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ${{ matrix.os }}
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout repository
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
cache: pip
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install --upgrade pip
|
|
29
|
+
python -m pip install -e ".[dev]"
|
|
30
|
+
|
|
31
|
+
- name: Lint
|
|
32
|
+
run: ruff check .
|
|
33
|
+
|
|
34
|
+
- name: Type check
|
|
35
|
+
run: mypy src/laga
|
|
36
|
+
|
|
37
|
+
- name: Test
|
|
38
|
+
run: pytest
|
|
39
|
+
|
|
40
|
+
- name: Upload coverage report
|
|
41
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
|
|
42
|
+
uses: actions/upload-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: coverage-report
|
|
45
|
+
path: |
|
|
46
|
+
coverage.xml
|
|
47
|
+
htmlcov
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
contents: read
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout repository
|
|
17
|
+
uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.13"
|
|
23
|
+
cache: pip
|
|
24
|
+
|
|
25
|
+
- name: Install build dependencies
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
python -m pip install build
|
|
29
|
+
|
|
30
|
+
- name: Build distributions
|
|
31
|
+
run: python -m build
|
|
32
|
+
|
|
33
|
+
- name: Verify artifacts
|
|
34
|
+
run: python -m pip install twine && twine check dist/*
|
|
35
|
+
|
|
36
|
+
- name: Publish to PyPI
|
|
37
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
38
|
+
with:
|
|
39
|
+
packages-dir: dist
|
laga-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
+
rev: v4.6.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: check-added-large-files
|
|
6
|
+
- id: check-ast
|
|
7
|
+
- id: check-byte-order-marker
|
|
8
|
+
- id: check-case-conflict
|
|
9
|
+
- id: check-merge-conflict
|
|
10
|
+
- id: check-symlinks
|
|
11
|
+
- id: end-of-file-fixer
|
|
12
|
+
- id: mixed-line-ending
|
|
13
|
+
- id: trailing-whitespace
|
|
14
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
15
|
+
rev: v0.6.9
|
|
16
|
+
hooks:
|
|
17
|
+
- id: ruff
|
|
18
|
+
args: [--fix]
|
|
19
|
+
- id: ruff-format
|
|
20
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
21
|
+
rev: v1.11.2
|
|
22
|
+
hooks:
|
|
23
|
+
- id: mypy
|
|
24
|
+
additional_dependencies: [hatchling]
|
|
25
|
+
files: ^src/laga/
|
laga-0.1.1/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.1] - 2026-07-24
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Repository cleanup, documentation refresh, and GitHub workflow improvements.
|
|
15
|
+
- Root ignore file for Python build and cache artifacts.
|
|
16
|
+
- Project ownership metadata updated for the `olaflaitinen` repository.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Dropped Python 3.9 support; laga 0.1.1 targets Python 3.10 through 3.13.
|
|
21
|
+
|
|
22
|
+
## [0.1.0] - 2026-07-24
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Fast path through `json.loads` for valid JSON.
|
|
27
|
+
- Recovery for comments, fences, prose, smart quotes, single quotes, missing commas, trailing commas, and truncated braces.
|
|
28
|
+
- `repair`, `repair_to_str`, and `loads` public entry points.
|
|
29
|
+
- Type information distributed through `py.typed`.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We commit to a respectful, inclusive, and professional community. We do not tolerate harassment, discrimination, or abuse of any kind.
|
|
6
|
+
|
|
7
|
+
## Expected Behavior
|
|
8
|
+
|
|
9
|
+
- Be considerate and constructive.
|
|
10
|
+
- Give feedback on ideas, not people.
|
|
11
|
+
- Assume good intent and communicate clearly.
|
|
12
|
+
|
|
13
|
+
## Unacceptable Behavior
|
|
14
|
+
|
|
15
|
+
- Harassment or threats.
|
|
16
|
+
- Hate speech or discriminatory language.
|
|
17
|
+
- Deliberate disruption of discussions or reviews.
|
|
18
|
+
|
|
19
|
+
## Enforcement
|
|
20
|
+
|
|
21
|
+
Maintainers may remove content, restrict access, or take other actions when needed to protect the community.
|
|
22
|
+
|
|
23
|
+
Reports may be sent to the maintainers listed in the repository or through private project contact channels.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
1. Create and activate a virtual environment.
|
|
6
|
+
2. Install development dependencies with `python -m pip install -e ".[dev]"`.
|
|
7
|
+
3. Install pre-commit hooks with `pre-commit install`.
|
|
8
|
+
|
|
9
|
+
## Local Checks
|
|
10
|
+
|
|
11
|
+
Run the full check set before sending a change:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
make lint
|
|
15
|
+
make typecheck
|
|
16
|
+
make test
|
|
17
|
+
make build
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Pull Requests
|
|
21
|
+
|
|
22
|
+
1. Keep changes focused and easy to review.
|
|
23
|
+
2. Add or update tests for behavior changes.
|
|
24
|
+
3. Update documentation when the public API changes.
|
|
25
|
+
4. Include screenshots only when the change is visual.
|
|
26
|
+
5. Make sure the CI workflow passes before requesting review.
|
laga-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gustav Olaf Yunus Laitinen-Fredriksson Lundström-Imanov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
laga-0.1.1/Makefile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
.PHONY: install lint typecheck test build docs
|
|
2
|
+
|
|
3
|
+
install:
|
|
4
|
+
python -m pip install -e ".[dev]"
|
|
5
|
+
|
|
6
|
+
lint:
|
|
7
|
+
ruff check .
|
|
8
|
+
ruff format --check .
|
|
9
|
+
|
|
10
|
+
typecheck:
|
|
11
|
+
mypy src/laga
|
|
12
|
+
|
|
13
|
+
test:
|
|
14
|
+
pytest
|
|
15
|
+
|
|
16
|
+
build:
|
|
17
|
+
python -m build
|
|
18
|
+
|
|
19
|
+
docs:
|
|
20
|
+
mkdocs build
|
laga-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: laga
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Repair malformed JSON from language models and hand-written config.
|
|
5
|
+
Project-URL: Homepage, https://github.com/olaflaitinen/laga
|
|
6
|
+
Project-URL: Documentation, https://github.com/olaflaitinen/laga/tree/main/docs
|
|
7
|
+
Project-URL: Source, https://github.com/olaflaitinen/laga
|
|
8
|
+
Project-URL: Issue Tracker, https://github.com/olaflaitinen/laga/issues
|
|
9
|
+
Author: Gustav Olaf Yunus Laitinen-Fredriksson Lundström-Imanov
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 Gustav Olaf Yunus Laitinen-Fredriksson Lundström-Imanov
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: data-cleanup,json,llm,parser,repair
|
|
33
|
+
Classifier: Development Status :: 3 - Alpha
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Operating System :: OS Independent
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
42
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
43
|
+
Classifier: Typing :: Typed
|
|
44
|
+
Requires-Python: <3.14,>=3.10
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
47
|
+
Requires-Dist: coverage[toml]>=7.6; extra == 'dev'
|
|
48
|
+
Requires-Dist: hypothesis>=6.108; extra == 'dev'
|
|
49
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'dev'
|
|
50
|
+
Requires-Dist: mkdocs>=1.6; extra == 'dev'
|
|
51
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
52
|
+
Requires-Dist: pre-commit>=3.8; extra == 'dev'
|
|
53
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
54
|
+
Requires-Dist: pytest>=8.3; extra == 'dev'
|
|
55
|
+
Requires-Dist: ruff>=0.6.9; extra == 'dev'
|
|
56
|
+
Provides-Extra: docs
|
|
57
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
58
|
+
Requires-Dist: mkdocs>=1.6; extra == 'docs'
|
|
59
|
+
Provides-Extra: lint
|
|
60
|
+
Requires-Dist: mypy>=1.11; extra == 'lint'
|
|
61
|
+
Requires-Dist: ruff>=0.6.9; extra == 'lint'
|
|
62
|
+
Provides-Extra: test
|
|
63
|
+
Requires-Dist: coverage[toml]>=7.6; extra == 'test'
|
|
64
|
+
Requires-Dist: hypothesis>=6.108; extra == 'test'
|
|
65
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'test'
|
|
66
|
+
Requires-Dist: pytest>=8.3; extra == 'test'
|
|
67
|
+
Description-Content-Type: text/markdown
|
|
68
|
+
|
|
69
|
+
# laga
|
|
70
|
+
|
|
71
|
+
`laga` repairs malformed JSON and returns Python objects.
|
|
72
|
+
|
|
73
|
+
## Why
|
|
74
|
+
|
|
75
|
+
Large language models and hand-written configuration often produce almost-JSON with trailing commas, missing commas, comments, code fences, single quotes, unquoted keys, or truncated containers. `laga` keeps the public surface small, tries `json.loads` first for valid input, and only enters the repair path when necessary.
|
|
76
|
+
|
|
77
|
+
## Install
|
|
78
|
+
|
|
79
|
+
`laga` 0.1.1 supports Python 3.10 through 3.13.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
python -m pip install -e ".[dev]"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Quickstart
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import laga
|
|
89
|
+
|
|
90
|
+
text = """Here is the result:
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
'name': 'Ada',
|
|
94
|
+
'active': True,
|
|
95
|
+
'roles': ['admin', 'writer',],
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
data = laga.repair(text)
|
|
101
|
+
print(data)
|
|
102
|
+
print(laga.repair_to_str(text))
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## API Reference
|
|
106
|
+
|
|
107
|
+
| Function | Returns | Description |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `laga.repair(text, strict=False)` | Python object | Repairs malformed JSON and returns Python data. |
|
|
110
|
+
| `laga.repair_to_str(text, strict=False)` | `str` | Repairs malformed JSON and returns normalized JSON text. |
|
|
111
|
+
| `laga.loads(text, strict=False)` | Python object | Alias for `laga.repair`. |
|
|
112
|
+
| `laga.LagaError` | Exception type | Raised when repair fails or input is unrecoverable. |
|
|
113
|
+
|
|
114
|
+
## Repair Rules
|
|
115
|
+
|
|
116
|
+
| Rule | Before | After |
|
|
117
|
+
| --- | --- | --- |
|
|
118
|
+
| Trailing comma | `{"a": 1,}` | `{"a":1}` |
|
|
119
|
+
| Missing comma | `{"a": 1 "b": 2}` | `{"a":1,"b":2}` |
|
|
120
|
+
| Single quotes | `{'a': 'b'}` | `{"a":"b"}` |
|
|
121
|
+
| Unquoted keys | `{name: "Ada"}` | `{"name":"Ada"}` |
|
|
122
|
+
| Python literals | `{"ok": True, "none": None}` | `{"ok":true,"none":null}` |
|
|
123
|
+
| Comments | `{"a": 1 // note\n}` | `{"a":1}` |
|
|
124
|
+
| Markdown fences | <code>```json\n{"a":1}\n```</code> | `{"a":1}` |
|
|
125
|
+
| Smart quotes | `“a”` | `"a"` |
|
|
126
|
+
| Prose around JSON | `Result: {"a":1}` | `{"a":1}` |
|
|
127
|
+
| Truncated structure | `{"a": [1, 2` | `{"a":[1,2]}` |
|
|
128
|
+
|
|
129
|
+
## Limitations
|
|
130
|
+
|
|
131
|
+
`laga` is intentionally conservative. It does not evaluate expressions, it does not guess at arbitrary JavaScript syntax, and it does not try to recover malformed numbers or deeply ambiguous text in strict mode. If you already control the producer and the input is valid JSON, the standard library remains the best choice because `json.loads` is faster and stricter.
|
|
132
|
+
|
|
133
|
+
When an object contains duplicate keys, the last value wins, matching Python dict behavior.
|
|
134
|
+
|
|
135
|
+
## When To Use The Standard Library
|
|
136
|
+
|
|
137
|
+
Use `json.loads` when you control the producer and know the input is valid JSON. Use `laga` when the input is noisy, user-facing, or generated by a model and you need a predictable repair step before parsing.
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
make install
|
|
143
|
+
make lint
|
|
144
|
+
make typecheck
|
|
145
|
+
make test
|
|
146
|
+
make build
|
|
147
|
+
```
|