moleg-api 0.1.0__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.
Files changed (30) hide show
  1. moleg_api-0.1.0/LICENSE +21 -0
  2. moleg_api-0.1.0/PKG-INFO +137 -0
  3. moleg_api-0.1.0/README.md +108 -0
  4. moleg_api-0.1.0/moleg_api/__init__.py +133 -0
  5. moleg_api-0.1.0/moleg_api/errors.py +49 -0
  6. moleg_api-0.1.0/moleg_api/laws.py +7030 -0
  7. moleg_api-0.1.0/moleg_api/models.py +740 -0
  8. moleg_api-0.1.0/moleg_api/normalization.py +1688 -0
  9. moleg_api-0.1.0/moleg_api/py.typed +1 -0
  10. moleg_api-0.1.0/moleg_api/source.py +271 -0
  11. moleg_api-0.1.0/moleg_api.egg-info/PKG-INFO +137 -0
  12. moleg_api-0.1.0/moleg_api.egg-info/SOURCES.txt +28 -0
  13. moleg_api-0.1.0/moleg_api.egg-info/dependency_links.txt +1 -0
  14. moleg_api-0.1.0/moleg_api.egg-info/requires.txt +7 -0
  15. moleg_api-0.1.0/moleg_api.egg-info/top_level.txt +1 -0
  16. moleg_api-0.1.0/pyproject.toml +60 -0
  17. moleg_api-0.1.0/setup.cfg +4 -0
  18. moleg_api-0.1.0/tests/test_congress_db_introspection.py +59 -0
  19. moleg_api-0.1.0/tests/test_fake_skill_tracer_bullet.py +63 -0
  20. moleg_api-0.1.0/tests/test_laws.py +9499 -0
  21. moleg_api-0.1.0/tests/test_laws_docstrings.py +379 -0
  22. moleg_api-0.1.0/tests/test_legislative_expert_answer_discipline.py +999 -0
  23. moleg_api-0.1.0/tests/test_legislative_expert_artifact_safety.py +1401 -0
  24. moleg_api-0.1.0/tests/test_legislative_expert_e2e_audit.py +1990 -0
  25. moleg_api-0.1.0/tests/test_legislative_expert_gate_crosswalk.py +940 -0
  26. moleg_api-0.1.0/tests/test_legislative_expert_prompt_dry_run.py +939 -0
  27. moleg_api-0.1.0/tests/test_live_e2e_scenarios.py +462 -0
  28. moleg_api-0.1.0/tests/test_live_smoke.py +186 -0
  29. moleg_api-0.1.0/tests/test_models.py +298 -0
  30. moleg_api-0.1.0/tests/test_source.py +299 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MOLEG-API maintainers
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.
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.4
2
+ Name: moleg-api
3
+ Version: 0.1.0
4
+ Summary: Task-level Python interface for loading Korean legal sources from law.go.kr
5
+ Author: MOLEG-API maintainers
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/tjdwls101010/MOLEG-API
8
+ Project-URL: Documentation, https://github.com/tjdwls101010/MOLEG-API/tree/main/docs
9
+ Project-URL: Repository, https://github.com/tjdwls101010/MOLEG-API
10
+ Project-URL: Issues, https://github.com/tjdwls101010/MOLEG-API/issues
11
+ Keywords: korea,law,legislation,moleg,law.go.kr
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: dev
24
+ Requires-Dist: psycopg[binary]<4,>=3.2; extra == "dev"
25
+ Requires-Dist: pytest<9,>=8; extra == "dev"
26
+ Provides-Extra: test
27
+ Requires-Dist: pytest<9,>=8; extra == "test"
28
+ Dynamic: license-file
29
+
30
+ # MOLEG-API
31
+
32
+ MOLEG-API is a task-level Python interface for loading Korean legal sources from
33
+ [law.go.kr](https://www.law.go.kr/). It is designed for applications and agent
34
+ systems that need normalized legal context without memorizing individual MOLEG
35
+ OpenAPI `target` values, identifier rules, or response-shape quirks.
36
+
37
+ The Python package name is `moleg-api`; import it as `moleg_api`.
38
+
39
+ This is not a complete wrapper around every law.go.kr endpoint. The public
40
+ interface is intentionally small and deep: search or plan first, then load the
41
+ selected legal source text, authority detail, delegated rule context, or
42
+ annex/form body.
43
+
44
+ ## Install
45
+
46
+ After the package is published:
47
+
48
+ ```bash
49
+ pip install moleg-api
50
+ ```
51
+
52
+ From a repository checkout:
53
+
54
+ ```bash
55
+ python -m pip install .
56
+ ```
57
+
58
+ Live law.go.kr calls require an OpenAPI credential in `MOLEG_OC`:
59
+
60
+ ```bash
61
+ export MOLEG_OC="your-law-go-kr-oc"
62
+ ```
63
+
64
+ ## Quick Example
65
+
66
+ ```python
67
+ from moleg_api import MolegApi
68
+
69
+ api = MolegApi()
70
+
71
+ hits = api.search_laws("자동차관리법", basis="effective", display=5)
72
+ selected = hits[0].identity
73
+
74
+ article = api.get_article(selected, "제26조", basis="effective")
75
+ print(article.text)
76
+ ```
77
+
78
+ For broader questions, use a staged bundle and inspect deferred follow-ups:
79
+
80
+ ```python
81
+ bundle = api.load_legal_context_bundle(
82
+ query="자동차 방치 처리 기준",
83
+ mode="question",
84
+ budget="standard",
85
+ )
86
+
87
+ for lookup in bundle.deferred:
88
+ if lookup.interface == "load_administrative_rule_context":
89
+ rule_context = api.load_followup(lookup)
90
+ break
91
+ ```
92
+
93
+ Public dataclasses serialize recursively:
94
+
95
+ ```python
96
+ payload = bundle.to_dict() # omits raw source payloads
97
+ debug_payload = bundle.to_dict(include_raw=True)
98
+ json_text = bundle.to_json_string()
99
+ ```
100
+
101
+ ## What It Covers
102
+
103
+ - Current and promulgated statutes
104
+ - Statute articles, including moved/deleted article status
105
+ - Supplementary provisions
106
+ - Law history and before/after text comparison
107
+ - Delegated rules and legal hierarchy
108
+ - Administrative rules, notices, directives, and established rules
109
+ - Law and administrative-rule annex/form body loading
110
+ - MOLEG official interpretations and ministry first-instance interpretations
111
+ - Ordinary court cases and Constitutional Court decisions
112
+ - Query expansion and comparable-mechanism discovery
113
+ - Staged context bundles with executable follow-up lookups
114
+
115
+ ## Documentation
116
+
117
+ - [Quickstart](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/quickstart.md)
118
+ - [API guide](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/api-guide.md)
119
+ - [Follow-up lookups](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/followups.md)
120
+ - [Source coverage and limits](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/source-coverage.md)
121
+ - [Documentation map](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/README.md)
122
+
123
+ Consumer-specific notes for a future legislative-expert skill remain in
124
+ [docs/SKILL-INTEGRATION.md](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/SKILL-INTEGRATION.md)
125
+ and
126
+ [docs/SKILL-AUTHOR-COOKBOOK.md](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/SKILL-AUTHOR-COOKBOOK.md).
127
+ They are examples of one integration, not the package's general-purpose
128
+ contract.
129
+
130
+ ## Status
131
+
132
+ The package is alpha (`0.1.x`). The interface is ready for package-level
133
+ experimentation, but law.go.kr live behavior can vary by source, credential, and
134
+ endpoint availability. Treat search results as candidates until selected detail
135
+ loaders have retrieved source text.
136
+
137
+ This package is a legal-source loader, not legal advice.
@@ -0,0 +1,108 @@
1
+ # MOLEG-API
2
+
3
+ MOLEG-API is a task-level Python interface for loading Korean legal sources from
4
+ [law.go.kr](https://www.law.go.kr/). It is designed for applications and agent
5
+ systems that need normalized legal context without memorizing individual MOLEG
6
+ OpenAPI `target` values, identifier rules, or response-shape quirks.
7
+
8
+ The Python package name is `moleg-api`; import it as `moleg_api`.
9
+
10
+ This is not a complete wrapper around every law.go.kr endpoint. The public
11
+ interface is intentionally small and deep: search or plan first, then load the
12
+ selected legal source text, authority detail, delegated rule context, or
13
+ annex/form body.
14
+
15
+ ## Install
16
+
17
+ After the package is published:
18
+
19
+ ```bash
20
+ pip install moleg-api
21
+ ```
22
+
23
+ From a repository checkout:
24
+
25
+ ```bash
26
+ python -m pip install .
27
+ ```
28
+
29
+ Live law.go.kr calls require an OpenAPI credential in `MOLEG_OC`:
30
+
31
+ ```bash
32
+ export MOLEG_OC="your-law-go-kr-oc"
33
+ ```
34
+
35
+ ## Quick Example
36
+
37
+ ```python
38
+ from moleg_api import MolegApi
39
+
40
+ api = MolegApi()
41
+
42
+ hits = api.search_laws("자동차관리법", basis="effective", display=5)
43
+ selected = hits[0].identity
44
+
45
+ article = api.get_article(selected, "제26조", basis="effective")
46
+ print(article.text)
47
+ ```
48
+
49
+ For broader questions, use a staged bundle and inspect deferred follow-ups:
50
+
51
+ ```python
52
+ bundle = api.load_legal_context_bundle(
53
+ query="자동차 방치 처리 기준",
54
+ mode="question",
55
+ budget="standard",
56
+ )
57
+
58
+ for lookup in bundle.deferred:
59
+ if lookup.interface == "load_administrative_rule_context":
60
+ rule_context = api.load_followup(lookup)
61
+ break
62
+ ```
63
+
64
+ Public dataclasses serialize recursively:
65
+
66
+ ```python
67
+ payload = bundle.to_dict() # omits raw source payloads
68
+ debug_payload = bundle.to_dict(include_raw=True)
69
+ json_text = bundle.to_json_string()
70
+ ```
71
+
72
+ ## What It Covers
73
+
74
+ - Current and promulgated statutes
75
+ - Statute articles, including moved/deleted article status
76
+ - Supplementary provisions
77
+ - Law history and before/after text comparison
78
+ - Delegated rules and legal hierarchy
79
+ - Administrative rules, notices, directives, and established rules
80
+ - Law and administrative-rule annex/form body loading
81
+ - MOLEG official interpretations and ministry first-instance interpretations
82
+ - Ordinary court cases and Constitutional Court decisions
83
+ - Query expansion and comparable-mechanism discovery
84
+ - Staged context bundles with executable follow-up lookups
85
+
86
+ ## Documentation
87
+
88
+ - [Quickstart](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/quickstart.md)
89
+ - [API guide](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/api-guide.md)
90
+ - [Follow-up lookups](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/followups.md)
91
+ - [Source coverage and limits](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/source-coverage.md)
92
+ - [Documentation map](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/README.md)
93
+
94
+ Consumer-specific notes for a future legislative-expert skill remain in
95
+ [docs/SKILL-INTEGRATION.md](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/SKILL-INTEGRATION.md)
96
+ and
97
+ [docs/SKILL-AUTHOR-COOKBOOK.md](https://github.com/tjdwls101010/MOLEG-API/blob/main/docs/SKILL-AUTHOR-COOKBOOK.md).
98
+ They are examples of one integration, not the package's general-purpose
99
+ contract.
100
+
101
+ ## Status
102
+
103
+ The package is alpha (`0.1.x`). The interface is ready for package-level
104
+ experimentation, but law.go.kr live behavior can vary by source, credential, and
105
+ endpoint availability. Treat search results as candidates until selected detail
106
+ loaders have retrieved source text.
107
+
108
+ This package is a legal-source loader, not legal advice.
@@ -0,0 +1,133 @@
1
+ """Public MOLEG-API interface."""
2
+
3
+ from .errors import (
4
+ AmbiguousLawError,
5
+ MolegApiError,
6
+ NoResultError,
7
+ ParseFailureError,
8
+ RateLimitError,
9
+ RetryExhaustedError,
10
+ SourceApiError,
11
+ UnsupportedFormatError,
12
+ )
13
+ from .laws import MolegApi
14
+ from .models import (
15
+ AdministrativeRuleArticleText,
16
+ AdministrativeRuleContext,
17
+ AdministrativeRuleHit,
18
+ AdministrativeRuleIdentity,
19
+ AdministrativeRuleText,
20
+ Ambiguity,
21
+ AnnexFormSource,
22
+ AnnexFormHit,
23
+ AnnexFormIdentity,
24
+ AnnexFormText,
25
+ AnnexSearchScope,
26
+ AnnexType,
27
+ ArticleContext,
28
+ ArticleReference,
29
+ ArticleText,
30
+ AuthorityContext,
31
+ Basis,
32
+ BundleBudget,
33
+ BundleMode,
34
+ BundleRequestMode,
35
+ BundleRequest,
36
+ CandidateContext,
37
+ CaseCourt,
38
+ ContextGap,
39
+ DeferredLookup,
40
+ DelegatedRule,
41
+ DelegationGraph,
42
+ HistoryEvent,
43
+ InterpretationHit,
44
+ InterpretationIdentity,
45
+ InterpretationSearchSource,
46
+ InterpretationText,
47
+ JudicialDecisionHit,
48
+ JudicialDecisionIdentity,
49
+ JudicialDecisionText,
50
+ FollowUpSearch,
51
+ LegalArticleCandidate,
52
+ LegalContextBundle,
53
+ LegalLawCandidate,
54
+ LegalQueryExpansion,
55
+ LegalTermCandidate,
56
+ LoadedContext,
57
+ LawDiff,
58
+ LawDiffChange,
59
+ LawHit,
60
+ LawHistory,
61
+ LawIdentity,
62
+ LawStructure,
63
+ LawStructureNode,
64
+ LawText,
65
+ SupplementaryProvision,
66
+ StructuredTableData,
67
+ )
68
+ from .source import LawGoKrClient
69
+
70
+ __all__ = [
71
+ "AmbiguousLawError",
72
+ "AdministrativeRuleArticleText",
73
+ "AdministrativeRuleContext",
74
+ "AdministrativeRuleHit",
75
+ "AdministrativeRuleIdentity",
76
+ "AdministrativeRuleText",
77
+ "Ambiguity",
78
+ "AnnexFormSource",
79
+ "AnnexFormHit",
80
+ "AnnexFormIdentity",
81
+ "AnnexFormText",
82
+ "AnnexSearchScope",
83
+ "AnnexType",
84
+ "ArticleContext",
85
+ "ArticleReference",
86
+ "ArticleText",
87
+ "AuthorityContext",
88
+ "Basis",
89
+ "BundleBudget",
90
+ "BundleMode",
91
+ "BundleRequestMode",
92
+ "BundleRequest",
93
+ "CandidateContext",
94
+ "CaseCourt",
95
+ "ContextGap",
96
+ "DeferredLookup",
97
+ "DelegatedRule",
98
+ "DelegationGraph",
99
+ "HistoryEvent",
100
+ "InterpretationHit",
101
+ "InterpretationIdentity",
102
+ "InterpretationSearchSource",
103
+ "InterpretationText",
104
+ "JudicialDecisionHit",
105
+ "JudicialDecisionIdentity",
106
+ "JudicialDecisionText",
107
+ "FollowUpSearch",
108
+ "LegalArticleCandidate",
109
+ "LegalContextBundle",
110
+ "LegalLawCandidate",
111
+ "LegalQueryExpansion",
112
+ "LegalTermCandidate",
113
+ "LoadedContext",
114
+ "LawGoKrClient",
115
+ "LawDiff",
116
+ "LawDiffChange",
117
+ "LawHit",
118
+ "LawHistory",
119
+ "LawIdentity",
120
+ "LawStructure",
121
+ "LawStructureNode",
122
+ "LawText",
123
+ "MolegApi",
124
+ "MolegApiError",
125
+ "NoResultError",
126
+ "ParseFailureError",
127
+ "RateLimitError",
128
+ "RetryExhaustedError",
129
+ "SourceApiError",
130
+ "SupplementaryProvision",
131
+ "StructuredTableData",
132
+ "UnsupportedFormatError",
133
+ ]
@@ -0,0 +1,49 @@
1
+ """MOLEG-API error model."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+
8
+ class MolegApiError(Exception):
9
+ """Base error for MOLEG-API public-interface failures."""
10
+
11
+
12
+ class NoResultError(MolegApiError):
13
+ """The source API returned no usable result for the requested legal task."""
14
+
15
+
16
+ class AmbiguousLawError(MolegApiError):
17
+ """The request matched multiple plausible law identities."""
18
+
19
+ def __init__(
20
+ self,
21
+ message: str,
22
+ *,
23
+ kind: str | None = None,
24
+ candidates: list[Any] | None = None,
25
+ ) -> None:
26
+ super().__init__(message)
27
+ self.message = message
28
+ self.kind = kind
29
+ self.candidates = list(candidates or [])
30
+
31
+
32
+ class UnsupportedFormatError(MolegApiError):
33
+ """The source endpoint cannot provide a supported response format."""
34
+
35
+
36
+ class SourceApiError(MolegApiError):
37
+ """The source law.go.kr API failed or returned an invalid response."""
38
+
39
+
40
+ class RateLimitError(SourceApiError):
41
+ """The source law.go.kr API rate limited the request."""
42
+
43
+
44
+ class RetryExhaustedError(SourceApiError):
45
+ """Retryable source failures continued through all allowed attempts."""
46
+
47
+
48
+ class ParseFailureError(MolegApiError):
49
+ """A source response could not be normalized into the public model."""