apcore-toolkit 0.4.2__tar.gz → 0.6.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.
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/.gitignore +4 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/CHANGELOG.md +57 -0
- apcore_toolkit-0.6.0/LICENSE +185 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/PKG-INFO +9 -10
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/README.md +2 -6
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/pyproject.toml +5 -4
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/__init__.py +40 -4
- apcore_toolkit-0.6.0/src/apcore_toolkit/_type_mapping.py +19 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/ai_enhancer.py +85 -40
- apcore_toolkit-0.6.0/src/apcore_toolkit/binding_loader.py +387 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/convention_scanner.py +69 -33
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/display/resolver.py +38 -5
- apcore_toolkit-0.6.0/src/apcore_toolkit/formatting/__init__.py +17 -0
- apcore_toolkit-0.6.0/src/apcore_toolkit/formatting/surface.py +336 -0
- apcore_toolkit-0.6.0/src/apcore_toolkit/http_verb_map.py +165 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/openapi.py +82 -13
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/output/__init__.py +13 -2
- apcore_toolkit-0.6.0/src/apcore_toolkit/output/errors.py +35 -0
- apcore_toolkit-0.6.0/src/apcore_toolkit/output/http_proxy_writer.py +274 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/output/python_writer.py +9 -9
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/output/registry_writer.py +36 -4
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/output/types.py +1 -1
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/output/verifiers.py +32 -10
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/output/yaml_writer.py +87 -22
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/pydantic_utils.py +32 -24
- apcore_toolkit-0.6.0/src/apcore_toolkit/resolve_target.py +82 -0
- apcore_toolkit-0.6.0/src/apcore_toolkit/scanner.py +213 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/serializers.py +2 -0
- apcore_toolkit-0.6.0/src/apcore_toolkit/types.py +83 -0
- apcore_toolkit-0.6.0/tests/fixtures/scanner_verb_map.json +100 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_ai_enhancer.py +97 -0
- apcore_toolkit-0.6.0/tests/test_binding_loader.py +485 -0
- apcore_toolkit-0.6.0/tests/test_convention_scanner.py +319 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_display_resolver.py +203 -0
- apcore_toolkit-0.6.0/tests/test_format_surface.py +279 -0
- apcore_toolkit-0.6.0/tests/test_http_proxy_writer.py +487 -0
- apcore_toolkit-0.6.0/tests/test_http_verb_map.py +246 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_openapi.py +166 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_output_factory.py +23 -0
- apcore_toolkit-0.6.0/tests/test_pydantic_utils.py +267 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_python_writer.py +26 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_registry_writer.py +29 -1
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_scanner.py +157 -5
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_serializers.py +19 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_types.py +72 -2
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_verifiers.py +91 -4
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_write_error.py +14 -9
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_yaml_writer.py +134 -0
- apcore_toolkit-0.4.2/src/apcore_toolkit/formatting/__init__.py +0 -7
- apcore_toolkit-0.4.2/src/apcore_toolkit/output/errors.py +0 -17
- apcore_toolkit-0.4.2/src/apcore_toolkit/output/http_proxy_writer.py +0 -187
- apcore_toolkit-0.4.2/src/apcore_toolkit/scanner.py +0 -134
- apcore_toolkit-0.4.2/src/apcore_toolkit/types.py +0 -46
- apcore_toolkit-0.4.2/tests/test_convention_scanner.py +0 -118
- apcore_toolkit-0.4.2/tests/test_http_proxy_writer.py +0 -204
- apcore_toolkit-0.4.2/tests/test_pydantic_utils.py +0 -120
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/.github/CODEOWNERS +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/.github/copilot-ignore +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/.github/workflows/ci.yml +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/.gitmessage +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/.pre-commit-config.yaml +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/display/__init__.py +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/formatting/markdown.py +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/src/apcore_toolkit/schema_utils.py +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/conftest.py +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_markdown.py +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_schema_utils.py +0 -0
- {apcore_toolkit-0.4.2 → apcore_toolkit-0.6.0}/tests/test_write_result.py +0 -0
|
@@ -2,6 +2,63 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## [0.6.0] - 2026-05-07
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **`apcore` minimum version bumped from 0.20.0 to 0.21.0** — `pyproject.toml` `dependencies` now requires `apcore>=0.21.0`. Toolkit only imports stable apcore surface (`ModuleAnnotations`, `DEFAULT_ANNOTATIONS`, `ModuleExample`, `Registry`, `ErrorCodes`, `parse_docstring`, `errors.ModuleError`); the 0.21.0 additions (`discoverable` field on `ModuleAnnotations`, `PreviewResult`, `Change`, `ephemeral.*` namespace) are automatically handled — `ModuleAnnotations.from_dict()` picks up `discoverable` transparently, and `dataclasses.asdict()` / `dataclasses.replace()` propagate the new field without code changes. `AIEnhancer` derives its field set from `dataclasses.fields(ModuleAnnotations)` at import time, so it also picks up `discoverable` automatically. Full pytest suite verified against apcore 0.21.0.
|
|
11
|
+
- **`apcore` minimum version bumped from 0.19.0 to 0.20.0** — `pyproject.toml` `dependencies` now requires `apcore>=0.20.0`. Toolkit only imports stable apcore surface (`ModuleAnnotations`, `DEFAULT_ANNOTATIONS`, `ModuleExample`, `Registry`, `ErrorCodes`, `parse_docstring`, `errors.ModuleError`); none of these were affected by 0.20.0 changes. Full pytest suite (585 passed) verified against apcore 0.20.0.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Surface-aware formatters** (refs aiperceivable/apcore-toolkit#13) — `format_module`, `format_schema`, `format_modules` for rendering `ScannedModule` and JSON Schema for specific consumer surfaces. Four styles for `format_module`: `markdown` (LLM context), `skill` (drop-in `.claude/skills/<id>/SKILL.md` or `.gemini/skills/<id>/SKILL.md` body with minimal `name` + `description` frontmatter — no vendor-specific extensions), `table-row` (CLI listing), `json` (programmatic). `format_schema` styles: `prose`, `table`, `json`. `format_modules` adds optional `group_by="tag" | "prefix"`. `display=True` (default) prefers the `ScannedModule.display` overlay over raw fields. Lives in `apcore_toolkit.formatting.surface`; re-exported at the top-level package.
|
|
16
|
+
- **Annotation-table cross-SDK alignment** — `format_module(style="markdown" | "skill")` `## Behavior` table now emits only fields that differ from `ModuleAnnotations()` defaults, sorts rows alphabetically by snake_case key, and renders bool values as lowercase `true`/`false`. The section is omitted entirely when every annotation field matches its default. Closes the byte-equality gap with the TypeScript and Rust SDKs.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`infer_annotations_from_method` canonical mapping** (refs aiperceivable/apcore-toolkit#11) — `HEAD` and `OPTIONS` now map to `readonly=true` (without `cacheable=true`), matching the canonical mapping declared in `apcore-toolkit/docs/features/scanning.md` and aligning with the existing Rust SDK. Previously these methods returned default annotations.
|
|
21
|
+
|
|
22
|
+
## [0.5.0] - 2026-04-21
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **`BindingLoader`** (`apcore_toolkit.binding_loader`) — parses `.binding.yaml` files back into `ScannedModule` objects, the inverse of `YAMLWriter`. Unlike `apcore.BindingLoader`, this is pure data: no target import, no Registry mutation. Enables verification, merging, diffing, and round-trip workflows.
|
|
27
|
+
- `load(path, *, strict=False)` — single file or directory of `*.binding.yaml`.
|
|
28
|
+
- `load_data(data, *, strict=False)` — pre-parsed YAML dict.
|
|
29
|
+
- Loose mode (default): only `module_id + target` required; missing fields use defaults.
|
|
30
|
+
- Strict mode: additionally requires `input_schema + output_schema`.
|
|
31
|
+
- `spec_version` validated; missing/unsupported versions WARN but do not fail.
|
|
32
|
+
- `annotations` parsed via `ModuleAnnotations.from_dict`; malformed values degrade to `None` with WARN.
|
|
33
|
+
- `examples` entries validated individually; malformed ones skipped with WARN.
|
|
34
|
+
- `BindingLoadError` exception carries `file_path`, `module_id`, `missing_fields`, `reason`.
|
|
35
|
+
- **`ScannedModule.display`** — new top-level optional field (`dict | None`) holding the sparse display overlay for binding YAML persistence. Distinct from `metadata["display"]` (resolved form produced by `DisplayResolver`).
|
|
36
|
+
- **New feature doc**: `docs/features/binding-loader.md`; `display-overlay.md` and `output-writers.md` updated.
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- **`YAMLWriter._build_binding`** — emits top-level `display:` key only when `ScannedModule.display is not None` (skip when None keeps output clean).
|
|
41
|
+
- **`serializers.module_to_dict`** — includes `display` key in output.
|
|
42
|
+
- **`AIEnhancer._build_prompt`** — confidence template is now built dynamically from `gaps`. When `annotations` is in gaps, the prompt requests per-field confidence for every `_ANNOTATION_FIELD_VALIDATORS` field (`annotations.readonly`, `annotations.streaming`, `annotations.cache_ttl`, ...). Previously the template hard-coded `{"description": 0.0, "documentation": 0.0}` only, causing all annotation-field confidence lookups to fall back to `0.0` and fail the threshold check — annotation enhancement silently never took effect. Fixes symmetry with `_enhance_module`'s `ann_conf.get(f"annotations.{field_name}", ...)` read path.
|
|
43
|
+
|
|
44
|
+
### Dependencies
|
|
45
|
+
|
|
46
|
+
- **`apcore >= 0.19.0`** — picks up the expanded `ModuleAnnotations` (12 fields incl. `streaming`, `cacheable`, `cache_ttl`, `cache_key_fields`, `paginated`, `pagination_style`, `extra`). No toolkit code changes were needed for the type itself — `_build_annotation_field_validators` reflects the updated dataclass automatically.
|
|
47
|
+
|
|
48
|
+
### Tests
|
|
49
|
+
|
|
50
|
+
- +34 new tests: 24 for `BindingLoader` (parsing, strict/loose modes, spec_version, file & directory loading, round-trip with `YAMLWriter`), 5 for the prompt confidence block, and 5 hardening tests (display deep-copy, malformed-shape warn, recursive glob, UTF-8 encoding, null-field error wording).
|
|
51
|
+
- Updated `test_field_count` (13 → 14) and `test_all_expected_keys` for the new `display` field.
|
|
52
|
+
- Total suite: 440 tests.
|
|
53
|
+
|
|
54
|
+
### Hardening (post-review)
|
|
55
|
+
|
|
56
|
+
- **`BindingLoader`**: warns (rather than silently drops) malformed `display` values that are not a mapping; `load()` gained a `recursive: bool = False` kwarg for nested binding layouts; `read_text` now forces UTF-8 decoding so non-ASCII aliases round-trip on non-UTF-8 locales; required-field validation now rejects wrong-type scalars (e.g. `module_id: 42`, `target: true`) and empty strings in addition to absent/null, matching the Rust loader's contract — error wording is "missing or invalid required fields"; nested `input_schema`/`output_schema`/`metadata` are now deep-copied via `copy.deepcopy` so caller mutation does not leak back into the parsed YAML source graph.
|
|
57
|
+
- **`YAMLWriter`**: `display` is now deep-copied into the emitted binding (defensive parity with the TypeScript/Rust writers) so post-write mutation of `ScannedModule.display` cannot leak into the file. File writes are now atomic: the payload is written to `<name>.<pid>.tmp`, `fsync`ed, then `os.replace`d onto the final path (matches the TypeScript `tmp + rename` and Rust `tmp + sync_all + rename` writers). A process crash mid-write no longer leaves a partial YAML file that `BindingLoader` would fail to parse. A pre-write check refuses to overwrite a symlink at the target path (defence-in-depth against TOCTOU).
|
|
58
|
+
- **`BaseScanner.deduplicate_ids`**: pre-scans all input `module_id`s so generated `_N` suffixes never collide with an ID already present in the input. Input `[a, a, a_2]` now yields `[a, a_3, a_2]` instead of the previous buggy `[a, a_2, a_2]`. Matches the TypeScript and Rust implementations.
|
|
59
|
+
- **`resolve_target` / `RegistryWriter.write`**: new `allowed_prefixes: list[str] | None` kwarg (forwarded from `RegistryWriter.write` through `_to_function_module` to `resolve_target`). When set, `resolve_target` rejects any module path outside the listed prefixes **before** calling `importlib.import_module`, raising `PermissionError`. Mitigates arbitrary-code-execution via forged binding files (e.g. a malicious `target: "os:system"` injected into untrusted YAML). Parity with the TypeScript SDK's `allowedPrefixes` option, adapted to Python's module-name import model. Boundary-aware: `"myapp"` permits `myapp.views` but NOT `myappx.foo`. Rust does not need this because `resolve_target` is parse-only and the `HandlerFactory` is the security boundary.
|
|
60
|
+
- **`ScannedModule.display`**: moved to the END of the dataclass so existing positional `ScannedModule(...)` callers are not broken by the new field.
|
|
61
|
+
|
|
5
62
|
## [0.4.1] - 2026-03-25
|
|
6
63
|
|
|
7
64
|
### Added
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship made available under
|
|
36
|
+
the License, as indicated by a copyright notice that is included in
|
|
37
|
+
or attached to the work (an example is provided in the Appendix below).
|
|
38
|
+
|
|
39
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
40
|
+
form, that is based on (or derived from) the Work and for which the
|
|
41
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
42
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
43
|
+
of this License, Derivative Works shall not include works that remain
|
|
44
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
45
|
+
the Work and Derivative Works thereof.
|
|
46
|
+
|
|
47
|
+
"Contribution" shall mean, as defined in Section 5, any work of authorship,
|
|
48
|
+
including the original version of the Work and any modifications or
|
|
49
|
+
additions to that Work or Derivative Works of the Work, that is
|
|
50
|
+
intentionally submitted to the Licensor for inclusion in the Work by the
|
|
51
|
+
copyright owner or by an individual or Legal Entity authorized to submit
|
|
52
|
+
on behalf of the copyright owner. For the purposes of this definition,
|
|
53
|
+
"submitted" means any form of electronic, verbal, or written communication
|
|
54
|
+
sent to the Licensor or its representatives, including but not limited to
|
|
55
|
+
communication on electronic mailing lists, source code control systems,
|
|
56
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
57
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
58
|
+
excluding communication that is conspicuously marked or otherwise
|
|
59
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
60
|
+
|
|
61
|
+
"Contributor" shall mean Licensor and any Legal Entity on behalf of
|
|
62
|
+
whom a Contribution has been received by the Licensor and subsequently
|
|
63
|
+
incorporated within the Work.
|
|
64
|
+
|
|
65
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
66
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
67
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
68
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
69
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
70
|
+
Work and such Derivative Works in Source or Object form.
|
|
71
|
+
|
|
72
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
73
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
74
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
75
|
+
(except as stated in this section) patent license to make, have made,
|
|
76
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
77
|
+
where such license applies only to those patent claims licensable
|
|
78
|
+
by such Contributor that are necessarily infringed by their
|
|
79
|
+
Contribution(s) alone or by the combination of their Contribution(s)
|
|
80
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
81
|
+
institute patent litigation against any entity (including a cross-claim
|
|
82
|
+
or counterclaim in a lawsuit) alleging that the Work or any Contribution
|
|
83
|
+
incorporated within the Work constitutes direct or contributory patent
|
|
84
|
+
infringement, then any patent licenses granted to You under this License
|
|
85
|
+
for that Work shall terminate as of the date such litigation is filed.
|
|
86
|
+
|
|
87
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
88
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
89
|
+
modifications, and in Source or Object form, provided that You
|
|
90
|
+
meet the following conditions:
|
|
91
|
+
|
|
92
|
+
(a) You must give any other recipients of the Work or Derivative
|
|
93
|
+
Works a copy of this License; and
|
|
94
|
+
|
|
95
|
+
(b) You must cause any modified files to carry prominent notices
|
|
96
|
+
stating that You changed the files; and
|
|
97
|
+
|
|
98
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
99
|
+
that You distribute, all copyright, patent, trademark, and
|
|
100
|
+
attribution notices from the Source form of the Work,
|
|
101
|
+
excluding those notices that do not pertain to any part of
|
|
102
|
+
the Derivative Works; and
|
|
103
|
+
|
|
104
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
105
|
+
distribution, You must include a readable copy of the
|
|
106
|
+
attribution notices contained within such NOTICE file, in
|
|
107
|
+
at least one of the following places: within a NOTICE text
|
|
108
|
+
file distributed as part of the Derivative Works; within
|
|
109
|
+
the Source form or documentation, if provided along with the
|
|
110
|
+
Derivative Works; or, within a display generated by the
|
|
111
|
+
Derivative Works, if and wherever such third-party notices
|
|
112
|
+
normally appear. The contents of the NOTICE file are for
|
|
113
|
+
informational purposes only and do not modify the License.
|
|
114
|
+
You may add Your own attribution notices within Derivative
|
|
115
|
+
Works that You distribute, alongside or as an addendum to
|
|
116
|
+
the NOTICE text from the Work, provided that such additional
|
|
117
|
+
attribution notices cannot be construed as modifying the License.
|
|
118
|
+
|
|
119
|
+
You may add Your own license statement for Your modifications and
|
|
120
|
+
may provide additional grant of rights to use, copy, modify, merge,
|
|
121
|
+
publish, distribute, sublicense, and/or sell copies of the Work and
|
|
122
|
+
Derivative Works, subject to the conditions of this License.
|
|
123
|
+
|
|
124
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
125
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
126
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
127
|
+
this License, without any additional terms or conditions.
|
|
128
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
129
|
+
the terms of any separate license agreement you may have executed
|
|
130
|
+
with Licensor regarding such Contributions.
|
|
131
|
+
|
|
132
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
133
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
134
|
+
except as required for reasonable and customary use in describing the
|
|
135
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
136
|
+
|
|
137
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
138
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
139
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
140
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
141
|
+
implied, including, without limitation, any warranties or conditions
|
|
142
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
143
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
144
|
+
appropriateness of using or reproducing the Work and assume any
|
|
145
|
+
risks associated with Your exercise of permissions under this License.
|
|
146
|
+
|
|
147
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
148
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
149
|
+
unless required by applicable law (such as deliberate and grossly
|
|
150
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
151
|
+
liable to You for damages, including any direct, indirect, special,
|
|
152
|
+
incidental, or exemplary damages of any character arising as a
|
|
153
|
+
result of this License or out of the use or inability to use the
|
|
154
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
155
|
+
work stoppage, computer failure or malfunction, or all other
|
|
156
|
+
commercial damages or losses), even if such Contributor has been
|
|
157
|
+
advised of the possibility of such damages.
|
|
158
|
+
|
|
159
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
160
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
161
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
162
|
+
or other liability obligations and/or rights consistent with this
|
|
163
|
+
License. However, in accepting such obligations, You may offer
|
|
164
|
+
such conditions only on Your own behalf and on Your sole
|
|
165
|
+
responsibility, not on behalf of any other Contributor, and only
|
|
166
|
+
if You agree to indemnify, defend, and hold each Contributor
|
|
167
|
+
harmless for any liability incurred by, or claims asserted against,
|
|
168
|
+
such Contributor by reason of your accepting any such warranty or
|
|
169
|
+
additional liability.
|
|
170
|
+
|
|
171
|
+
END OF TERMS AND CONDITIONS
|
|
172
|
+
|
|
173
|
+
Copyright 2024 aiperceivable
|
|
174
|
+
|
|
175
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
176
|
+
you may not use this file except in compliance with the License.
|
|
177
|
+
You may obtain a copy of the License at
|
|
178
|
+
|
|
179
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
180
|
+
|
|
181
|
+
Unless required by applicable law or agreed to in writing, software
|
|
182
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
183
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
184
|
+
See the License for the specific language governing permissions and
|
|
185
|
+
limitations under the License.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: apcore-toolkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Shared scanner, schema extraction, and output toolkit for apcore framework adapters
|
|
5
5
|
Project-URL: Homepage, https://aiperceivable.com
|
|
6
6
|
Project-URL: Repository, https://github.com/aiperceivable/apcore-toolkit-python
|
|
@@ -8,9 +8,10 @@ Project-URL: Documentation, https://github.com/aiperceivable/apcore-toolkit-pyth
|
|
|
8
8
|
Project-URL: Issues, https://github.com/aiperceivable/apcore-toolkit-python/issues
|
|
9
9
|
Author-email: aiperceivable <tercel.yi@gmail.com>
|
|
10
10
|
License-Expression: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
11
12
|
Keywords: apcore,mcp,openapi,pydantic,scanner,schema,toolkit,yaml
|
|
12
13
|
Requires-Python: >=3.11
|
|
13
|
-
Requires-Dist: apcore>=0.
|
|
14
|
+
Requires-Dist: apcore>=0.21.0
|
|
14
15
|
Requires-Dist: pydantic>=2.0
|
|
15
16
|
Requires-Dist: pyyaml>=6.0
|
|
16
17
|
Provides-Extra: dev
|
|
@@ -18,10 +19,12 @@ Requires-Dist: apdev[dev]>=0.2.1; extra == 'dev'
|
|
|
18
19
|
Requires-Dist: httpx>=0.24; extra == 'dev'
|
|
19
20
|
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
20
21
|
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
21
|
-
Requires-Dist: pytest>=
|
|
22
|
-
Requires-Dist: ruff>=0.
|
|
22
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff>=0.9; extra == 'dev'
|
|
23
24
|
Provides-Extra: http-proxy
|
|
24
25
|
Requires-Dist: httpx>=0.24; extra == 'http-proxy'
|
|
26
|
+
Provides-Extra: json-schema
|
|
27
|
+
Requires-Dist: jsonschema>=4.0; extra == 'json-schema'
|
|
25
28
|
Description-Content-Type: text/markdown
|
|
26
29
|
|
|
27
30
|
<div align="center">
|
|
@@ -48,6 +51,8 @@ pip install apcore-toolkit
|
|
|
48
51
|
| `ScannedModule` | Canonical dataclass representing a scanned endpoint |
|
|
49
52
|
| `BaseScanner` | Abstract base class for framework scanners with filtering and deduplication |
|
|
50
53
|
| `YAMLWriter` | Generates `.binding.yaml` files for `apcore.BindingLoader` |
|
|
54
|
+
| `BindingLoader` | Parses `.binding.yaml` files back into `ScannedModule` objects (pure-data inverse of `YAMLWriter`, with loose/strict modes) |
|
|
55
|
+
| `BindingLoadError` | Exception raised when binding parsing fails; carries `file_path`, `module_id`, `missing_fields`, `reason` |
|
|
51
56
|
| `PythonWriter` | Generates `@module`-decorated Python wrapper files |
|
|
52
57
|
| `RegistryWriter` | Registers modules directly into an `apcore.Registry` |
|
|
53
58
|
| `HTTPProxyRegistryWriter` | Registers HTTP proxy modules that forward requests to a running API |
|
|
@@ -246,12 +251,6 @@ def deploy(env: str, tag: str = "latest") -> dict:
|
|
|
246
251
|
|
|
247
252
|
Input and output schemas are inferred from PEP 484 type annotations. Use `include` / `exclude` regex filters to control which module IDs are registered.
|
|
248
253
|
|
|
249
|
-
## Requirements
|
|
250
|
-
|
|
251
|
-
- Python >= 3.11
|
|
252
|
-
- apcore >= 0.14.0
|
|
253
|
-
- pydantic >= 2.0
|
|
254
|
-
- PyYAML >= 6.0
|
|
255
254
|
|
|
256
255
|
## Documentation
|
|
257
256
|
|
|
@@ -22,6 +22,8 @@ pip install apcore-toolkit
|
|
|
22
22
|
| `ScannedModule` | Canonical dataclass representing a scanned endpoint |
|
|
23
23
|
| `BaseScanner` | Abstract base class for framework scanners with filtering and deduplication |
|
|
24
24
|
| `YAMLWriter` | Generates `.binding.yaml` files for `apcore.BindingLoader` |
|
|
25
|
+
| `BindingLoader` | Parses `.binding.yaml` files back into `ScannedModule` objects (pure-data inverse of `YAMLWriter`, with loose/strict modes) |
|
|
26
|
+
| `BindingLoadError` | Exception raised when binding parsing fails; carries `file_path`, `module_id`, `missing_fields`, `reason` |
|
|
25
27
|
| `PythonWriter` | Generates `@module`-decorated Python wrapper files |
|
|
26
28
|
| `RegistryWriter` | Registers modules directly into an `apcore.Registry` |
|
|
27
29
|
| `HTTPProxyRegistryWriter` | Registers HTTP proxy modules that forward requests to a running API |
|
|
@@ -220,12 +222,6 @@ def deploy(env: str, tag: str = "latest") -> dict:
|
|
|
220
222
|
|
|
221
223
|
Input and output schemas are inferred from PEP 484 type annotations. Use `include` / `exclude` regex filters to control which module IDs are registered.
|
|
222
224
|
|
|
223
|
-
## Requirements
|
|
224
|
-
|
|
225
|
-
- Python >= 3.11
|
|
226
|
-
- apcore >= 0.14.0
|
|
227
|
-
- pydantic >= 2.0
|
|
228
|
-
- PyYAML >= 6.0
|
|
229
225
|
|
|
230
226
|
## Documentation
|
|
231
227
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "apcore-toolkit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.0"
|
|
8
8
|
description = "Shared scanner, schema extraction, and output toolkit for apcore framework adapters"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
readme = "README.md"
|
|
@@ -23,17 +23,18 @@ keywords = [
|
|
|
23
23
|
"toolkit",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
|
-
"apcore>=0.
|
|
26
|
+
"apcore>=0.21.0",
|
|
27
27
|
"pydantic>=2.0",
|
|
28
28
|
"PyYAML>=6.0",
|
|
29
29
|
]
|
|
30
30
|
|
|
31
31
|
[project.optional-dependencies]
|
|
32
32
|
http-proxy = ["httpx>=0.24"]
|
|
33
|
+
json-schema = ["jsonschema>=4.0"]
|
|
33
34
|
dev = [
|
|
34
|
-
"pytest>=
|
|
35
|
+
"pytest>=8.0",
|
|
35
36
|
"pytest-cov>=4.0",
|
|
36
|
-
"ruff>=0.
|
|
37
|
+
"ruff>=0.9",
|
|
37
38
|
"mypy>=1.0",
|
|
38
39
|
"apdev[dev]>=0.2.1",
|
|
39
40
|
"httpx>=0.24",
|
|
@@ -6,8 +6,14 @@ Public API re-exports for convenient access to core types and utilities.
|
|
|
6
6
|
from importlib.metadata import PackageNotFoundError
|
|
7
7
|
from importlib.metadata import version as _get_version
|
|
8
8
|
from apcore_toolkit.ai_enhancer import AIEnhancer, Enhancer
|
|
9
|
+
from apcore_toolkit.binding_loader import BindingLoader, BindingLoadError
|
|
9
10
|
from apcore_toolkit.display import DisplayResolver
|
|
10
|
-
from apcore_toolkit.formatting import
|
|
11
|
+
from apcore_toolkit.formatting import (
|
|
12
|
+
format_module,
|
|
13
|
+
format_modules,
|
|
14
|
+
format_schema,
|
|
15
|
+
to_markdown,
|
|
16
|
+
)
|
|
11
17
|
from apcore_toolkit.openapi import (
|
|
12
18
|
deep_resolve_refs,
|
|
13
19
|
extract_input_schema,
|
|
@@ -16,7 +22,7 @@ from apcore_toolkit.openapi import (
|
|
|
16
22
|
resolve_schema,
|
|
17
23
|
)
|
|
18
24
|
from apcore_toolkit.output import get_writer
|
|
19
|
-
from apcore_toolkit.output.errors import WriteError
|
|
25
|
+
from apcore_toolkit.output.errors import InvalidFormatError, WriteError
|
|
20
26
|
from apcore_toolkit.output.python_writer import PythonWriter
|
|
21
27
|
from apcore_toolkit.output.http_proxy_writer import HTTPProxyRegistryWriter
|
|
22
28
|
from apcore_toolkit.output.registry_writer import RegistryWriter
|
|
@@ -32,10 +38,23 @@ from apcore_toolkit.output.verifiers import (
|
|
|
32
38
|
from apcore_toolkit.output.yaml_writer import YAMLWriter
|
|
33
39
|
from apcore_toolkit.pydantic_utils import flatten_pydantic_params, resolve_target
|
|
34
40
|
from apcore_toolkit.convention_scanner import ConventionScanner
|
|
35
|
-
from apcore_toolkit.
|
|
41
|
+
from apcore_toolkit.http_verb_map import (
|
|
42
|
+
SCANNER_VERB_MAP,
|
|
43
|
+
extract_path_param_names,
|
|
44
|
+
generate_suggested_alias,
|
|
45
|
+
has_path_params,
|
|
46
|
+
resolve_http_verb,
|
|
47
|
+
substitute_path_params,
|
|
48
|
+
)
|
|
49
|
+
from apcore_toolkit.scanner import (
|
|
50
|
+
BaseScanner,
|
|
51
|
+
deduplicate_ids,
|
|
52
|
+
filter_modules,
|
|
53
|
+
infer_annotations_from_method,
|
|
54
|
+
)
|
|
36
55
|
from apcore_toolkit.schema_utils import enrich_schema_descriptions
|
|
37
56
|
from apcore_toolkit.serializers import annotations_to_dict, module_to_dict, modules_to_dicts
|
|
38
|
-
from apcore_toolkit.types import ScannedModule
|
|
57
|
+
from apcore_toolkit.types import ScannedModule, clone_module, create_scanned_module
|
|
39
58
|
|
|
40
59
|
try:
|
|
41
60
|
__version__ = _get_version("apcore-toolkit")
|
|
@@ -44,16 +63,20 @@ except PackageNotFoundError:
|
|
|
44
63
|
|
|
45
64
|
__all__ = [
|
|
46
65
|
"AIEnhancer",
|
|
66
|
+
"BindingLoadError",
|
|
67
|
+
"BindingLoader",
|
|
47
68
|
"DisplayResolver",
|
|
48
69
|
"BaseScanner",
|
|
49
70
|
"ConventionScanner",
|
|
50
71
|
"HTTPProxyRegistryWriter",
|
|
51
72
|
"Enhancer",
|
|
73
|
+
"InvalidFormatError",
|
|
52
74
|
"JSONVerifier",
|
|
53
75
|
"MagicBytesVerifier",
|
|
54
76
|
"PythonWriter",
|
|
55
77
|
"RegistryVerifier",
|
|
56
78
|
"RegistryWriter",
|
|
79
|
+
"SCANNER_VERB_MAP",
|
|
57
80
|
"ScannedModule",
|
|
58
81
|
"SyntaxVerifier",
|
|
59
82
|
"Verifier",
|
|
@@ -63,17 +86,30 @@ __all__ = [
|
|
|
63
86
|
"YAMLVerifier",
|
|
64
87
|
"YAMLWriter",
|
|
65
88
|
"annotations_to_dict",
|
|
89
|
+
"clone_module",
|
|
90
|
+
"create_scanned_module",
|
|
91
|
+
"deduplicate_ids",
|
|
66
92
|
"deep_resolve_refs",
|
|
67
93
|
"enrich_schema_descriptions",
|
|
68
94
|
"extract_input_schema",
|
|
69
95
|
"extract_output_schema",
|
|
96
|
+
"extract_path_param_names",
|
|
97
|
+
"filter_modules",
|
|
70
98
|
"flatten_pydantic_params",
|
|
99
|
+
"format_module",
|
|
100
|
+
"format_modules",
|
|
101
|
+
"format_schema",
|
|
102
|
+
"generate_suggested_alias",
|
|
71
103
|
"get_writer",
|
|
104
|
+
"has_path_params",
|
|
105
|
+
"infer_annotations_from_method",
|
|
72
106
|
"module_to_dict",
|
|
73
107
|
"modules_to_dicts",
|
|
108
|
+
"resolve_http_verb",
|
|
74
109
|
"resolve_ref",
|
|
75
110
|
"resolve_schema",
|
|
76
111
|
"resolve_target",
|
|
77
112
|
"run_verifier_chain",
|
|
113
|
+
"substitute_path_params",
|
|
78
114
|
"to_markdown",
|
|
79
115
|
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Shared Python ↔ JSON Schema type vocabulary.
|
|
2
|
+
|
|
3
|
+
Single source of truth for the 6-type mapping used by ConventionScanner
|
|
4
|
+
(Python→JSON Schema) and PythonWriter (JSON Schema→Python). Adding a new
|
|
5
|
+
type here propagates to both automatically.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
PYTHON_TO_JSON_SCHEMA: dict[str, str] = {
|
|
11
|
+
"str": "string",
|
|
12
|
+
"int": "integer",
|
|
13
|
+
"float": "number",
|
|
14
|
+
"bool": "boolean",
|
|
15
|
+
"list": "array",
|
|
16
|
+
"dict": "object",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
JSON_SCHEMA_TO_PYTHON: dict[str, str] = {v: k for k, v in PYTHON_TO_JSON_SCHEMA.items()}
|