codingest 0.1.0__cp310-abi3-win_amd64.whl

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.
codingest/__init__.py ADDED
@@ -0,0 +1,46 @@
1
+ """codingest — parse polyglot codebases into kglite knowledge graphs.
2
+
3
+ import codingest
4
+
5
+ g = codingest.build(".") # -> kglite.KnowledgeGraph
6
+ g.cypher("MATCH (f:Function) RETURN f.name LIMIT 10")
7
+
8
+ `build()` parses the tree with codingest's native tree-sitter builder (grammars
9
+ bundled — nothing else to install), serializes the result to a `.kgl`, and hands
10
+ off to the separately installed `kglite` wheel: the returned object is a real
11
+ `kglite.KnowledgeGraph`, so every downstream kglite API works unchanged. This
12
+ restores the builder surface that kglite 0.14 removed (`kglite.code_tree`).
13
+
14
+ Entry points:
15
+ build - parse a directory (with optional git `rev`/`revs`).
16
+ repo_tree - clone a GitHub repo and build.
17
+ read_manifest - extract project metadata from a manifest file.
18
+ language_for_path- map a path to its parser language, or None.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ from importlib import metadata as _metadata
24
+
25
+ # The native extension registers `build` / `repo_tree` / `read_manifest` /
26
+ # `language_for_path`. Renamed to `codingest.codingest` by maturin's
27
+ # `module-name`; this pulls its public functions up to the package root.
28
+ from .codingest import ( # noqa: F401
29
+ build,
30
+ language_for_path,
31
+ read_manifest,
32
+ repo_tree,
33
+ )
34
+
35
+ try:
36
+ __version__ = _metadata.version("codingest")
37
+ except _metadata.PackageNotFoundError: # pragma: no cover - source checkout
38
+ from .codingest import __version__ as __version__
39
+
40
+ __all__ = [
41
+ "build",
42
+ "repo_tree",
43
+ "read_manifest",
44
+ "language_for_path",
45
+ "__version__",
46
+ ]
codingest/__init__.pyi ADDED
@@ -0,0 +1,131 @@
1
+ """Type stubs for the codingest wheel.
2
+
3
+ `build()` / `repo_tree()` return a `kglite.KnowledgeGraph` — the object the
4
+ installed `kglite` wheel produces, reached through the `.kgl`-bytes handoff
5
+ (build native → serialize → `kglite.load`). Every downstream kglite API
6
+ (`.cypher()`, `.describe()`, …) is available on the returned value.
7
+ """
8
+
9
+ from typing import Any, Optional
10
+
11
+ from kglite import KnowledgeGraph
12
+
13
+ __version__: str
14
+
15
+ def build(
16
+ src_dir: str,
17
+ *,
18
+ save_to: Optional[str] = None,
19
+ verbose: bool = False,
20
+ include_tests: bool = True,
21
+ max_loc_per_file: Optional[int] = None,
22
+ include_docs: bool = False,
23
+ rev: Optional[str] = None,
24
+ revs: Optional[list[str]] = None,
25
+ repo_root: Optional[str] = None,
26
+ ) -> KnowledgeGraph:
27
+ """Parse a codebase at ``src_dir`` into a :class:`kglite.KnowledgeGraph`.
28
+
29
+ The stable, public entry point for code-graph building (tree-sitter grammars
30
+ are bundled in the native extension — nothing else to install). codingest
31
+ builds the graph with its own native builder, serializes it to a ``.kgl``,
32
+ and loads it back through the installed ``kglite`` wheel, so the returned
33
+ object is a real ``kglite.KnowledgeGraph``.
34
+
35
+ Pass ``include_docs=True`` to also ingest the repo's markdown as ``:Doc``
36
+ nodes linked to the code they mention
37
+ (``(:Doc)-[:MENTIONS]->(:Function|:Class|…)`` and
38
+ ``(:Doc)-[:DOCUMENTS]->(:Doc|:File)``). Off by default (code-only graph).
39
+
40
+ Pass ``rev=<tag|branch|sha>`` to build the codebase as it existed at that git
41
+ revision instead of the working tree. The revision's tracked files are
42
+ materialized into a tempdir via ``git archive`` — ``HEAD`` and the working
43
+ tree are never touched, and uncommitted changes are excluded. The git root
44
+ is auto-resolved from ``src_dir`` (override with ``repo_root``); a bad rev or
45
+ non-git directory raises a clear error. The built graph's ``describe()``
46
+ records the revision it represents.
47
+
48
+ Pass ``revs=[<rev>, ...]`` (oldest → newest, mutually exclusive with
49
+ ``rev``) to merge N revisions into ONE multi-rev graph: one node per entity
50
+ across revs, each node carrying native list props ``revs: [str]`` (revisions
51
+ it appears in) + ``rev_fp: [int]`` (a per-rev shape fingerprint), and each
52
+ edge carrying ``revs: [str]``. Unchanged entities are stored once, so the
53
+ graph is ≈ base + deltas. Ordinary properties (``signature``,
54
+ ``value_preview``, …) report the NEWEST rev an entity appears in
55
+ (newest-wins). Because one graph holds every rev, an **unscoped**
56
+ ``MATCH (n:Function) RETURN count(n)`` over-counts across revs — scope a
57
+ query to one rev with membership::
58
+
59
+ MATCH (n:Function) WHERE 'v2' IN n.revs RETURN n.name
60
+
61
+ and use ``CALL rev_diff({from: 'v1', to: 'v2'})`` for added / removed /
62
+ changed deltas between two revs. ``describe()`` lists the loaded revs and
63
+ teaches this scoping idiom.
64
+
65
+ Args:
66
+ src_dir: Path to the directory (or manifest-rooted project) to parse.
67
+ save_to: If given, also write the built graph to this ``.kgl`` path
68
+ (the loaded graph is still returned).
69
+ verbose: Emit build progress to stderr.
70
+ include_tests: Include test files/dirs in the graph (default True).
71
+ max_loc_per_file: Skip files longer than this many lines (None = no cap).
72
+ include_docs: Ingest markdown as ``:Doc`` nodes (see above).
73
+ rev: A single git revspec to build (mutually exclusive with ``revs``).
74
+ revs: A list of git revspecs to merge into a multi-rev graph.
75
+ repo_root: Override the auto-resolved git root for ``rev``/``revs``.
76
+
77
+ Returns:
78
+ A :class:`kglite.KnowledgeGraph` of the parsed codebase.
79
+ """
80
+ ...
81
+
82
+ def repo_tree(
83
+ repo: str,
84
+ *,
85
+ save_to: Optional[str] = None,
86
+ clone_to: Optional[str] = None,
87
+ branch: Optional[str] = None,
88
+ token: Optional[str] = None,
89
+ verbose: bool = False,
90
+ include_tests: bool = True,
91
+ max_loc_per_file: Optional[int] = None,
92
+ include_docs: bool = False,
93
+ ) -> KnowledgeGraph:
94
+ """Clone a GitHub repository and build its code knowledge graph.
95
+
96
+ Shallow-clones ``repo`` (shelling out to ``git``) into a tempdir (or
97
+ ``clone_to``) and builds it, returning a :class:`kglite.KnowledgeGraph`.
98
+ Set ``include_docs=True`` to also ingest the repo's markdown as ``:Doc``
99
+ nodes linked to the code they mention (see :func:`build`).
100
+
101
+ Args:
102
+ repo: ``owner/name`` or a full clone URL.
103
+ save_to: If given, also write the built graph to this ``.kgl`` path.
104
+ clone_to: Directory to clone into (default: a tempdir, removed after).
105
+ branch: Branch / tag / ref to check out (default: the repo default).
106
+ token: Auth token for private repos.
107
+ verbose: Emit build progress to stderr.
108
+ include_tests: Include test files/dirs in the graph (default True).
109
+ max_loc_per_file: Skip files longer than this many lines.
110
+ include_docs: Ingest markdown as ``:Doc`` nodes (see :func:`build`).
111
+
112
+ Returns:
113
+ A :class:`kglite.KnowledgeGraph` of the cloned repository.
114
+ """
115
+ ...
116
+
117
+ def read_manifest(path: str) -> Optional[dict[str, Any]]:
118
+ """Read a project manifest and return a dict of project metadata.
119
+
120
+ Recognises ``pyproject.toml`` / ``Cargo.toml`` (and more). Returns ``None``
121
+ when no manifest is found at ``path``. The dict carries ``name``,
122
+ ``version``, ``description``, ``languages``, ``authors``, ``license``,
123
+ ``repository_url``, ``manifest_path``, ``build_system``, ``source_roots``,
124
+ and ``test_roots`` (the last two as lists of directory paths).
125
+ """
126
+ ...
127
+
128
+ def language_for_path(path: str) -> Optional[str]:
129
+ """Map a file path to its codingest parser language, or ``None`` if no
130
+ parser handles the file (e.g. ``"src/app.py"`` → ``"python"``)."""
131
+ ...
codingest/cli.py ADDED
@@ -0,0 +1,31 @@
1
+ """Console-script shim for the Rust ``codingest`` CLI bundled in the wheel.
2
+
3
+ The CLI implementation lives in the ``codingest-cli`` Rust library and is linked
4
+ into this wheel's existing extension alongside the code-graph builder. This
5
+ module only forwards argv and formats a top-level error; command parsing and
6
+ behavior are shared with the standalone ``codingest-cli`` binary distribution
7
+ (``cargo install codingest-cli``).
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import sys
13
+
14
+
15
+ def main(argv: list[str] | None = None) -> int:
16
+ """Run the bundled Rust CLI with ``argv`` or ``sys.argv[1:]``."""
17
+ from codingest.codingest import _run_cli
18
+
19
+ args = list(sys.argv[1:] if argv is None else argv)
20
+ try:
21
+ _run_cli(args)
22
+ except KeyboardInterrupt:
23
+ return 130
24
+ except RuntimeError as exc:
25
+ print(f"codingest: {exc}", file=sys.stderr)
26
+ return 1
27
+ return 0
28
+
29
+
30
+ if __name__ == "__main__":
31
+ raise SystemExit(main())
Binary file
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.4
2
+ Name: codingest
3
+ Version: 0.1.0
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Programming Language :: Rust
8
+ Classifier: Topic :: Software Development
9
+ Classifier: Topic :: Software Development :: Libraries
10
+ Requires-Dist: kglite>=0.13
11
+ License-File: LICENSE
12
+ Summary: Parse polyglot codebases into queryable kglite knowledge graphs — `import codingest; g = codingest.build('.')` returns a real kglite.KnowledgeGraph.
13
+ Keywords: knowledge-graph,code-analysis,tree-sitter,cypher,kglite,ast
14
+ Author-email: Kristian dF Kollsgård <kkollsg@gmail.com>
15
+ License-Expression: MIT
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
18
+
19
+ # codingest
20
+
21
+ [![CI](https://github.com/kkollsga/codingest/actions/workflows/ci.yml/badge.svg)](https://github.com/kkollsga/codingest/actions/workflows/ci.yml)
22
+ [![crates.io](https://img.shields.io/crates/v/codingest.svg)](https://crates.io/crates/codingest)
23
+ [![PyPI](https://img.shields.io/pypi/v/codingest.svg)](https://pypi.org/project/codingest/)
24
+ [![Docs](https://readthedocs.org/projects/codingest/badge/?version=latest)](https://codingest.readthedocs.io)
25
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
26
+
27
+ Parse polyglot codebases into queryable
28
+ [kglite](https://github.com/kkollsga/kglite) knowledge graphs — tree-sitter
29
+ parsers for 14 languages, call / type / inheritance / route edges, an optional
30
+ markdown-docs pass, and multi-git-revision merged graphs.
31
+
32
+ codingest is the standalone home of KGLite's former in-tree `code_tree`
33
+ component. The graph engine (storage backends, the Cypher pipeline, `.kgl`
34
+ persistence) and the MCP protocol server are **imported from kglite as cargo
35
+ libraries** — this repo owns only the code-tree component itself. Four surfaces
36
+ ship from one workspace: a **CLI**, an **MCP server**, a **Python wheel**, and a
37
+ **Rust crate**.
38
+
39
+ Documentation: **[codingest.readthedocs.io](https://codingest.readthedocs.io)**
40
+
41
+ ## Requirements — kglite ≥ 0.14
42
+
43
+ codingest builds against 0.14-only engine APIs (`kglite::api::code_entities`,
44
+ `kglite_mcp_server::run_with_code_tree_hooks`) that KGLite added when it removed
45
+ its in-tree builder. **These are not in any 0.13.x release.**
46
+
47
+ - **Rust / crates.io:** codingest cannot be published, and a checkout without a
48
+ sibling `../KGLite` cannot build, until **kglite 0.14.0 is on crates.io**.
49
+ Local development uses a path dependency on the sister checkout (see
50
+ [Dependency policy](#dependency-policy)).
51
+ - **Python wheel:** `pip install codingest` pulls `kglite>=0.13` for the
52
+ loader half of the handoff, but the *builder* half needs a kglite that
53
+ understands 0.14 graphs. Install **`kglite>=0.14`** alongside it.
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install codingest # Python wheel (grammars bundled) — ALSO installs the `codingest` CLI
59
+ cargo install codingest-cli # pure-Rust `codingest` builder CLI (no Python)
60
+ cargo install codingest-mcp # the code-graph MCP server
61
+ ```
62
+
63
+ The Python wheel bundles the `codingest` terminal command (the `codingest-cli`
64
+ Rust library is linked into the wheel's extension), so `pip install codingest`
65
+ alone gives you both `import codingest` and `codingest build`/`status` — the
66
+ `cargo install codingest-cli` route is only needed for a pure-Rust install.
67
+ This makes the pip-only flow `pip install kglite codingest && kglite skill
68
+ install` self-sufficient (the installed code-review skill shells out to
69
+ `codingest build`/`status`).
70
+
71
+ (All become available once kglite 0.14.0 is published — see
72
+ [Requirements](#requirements--kglite--014).)
73
+
74
+ ## Quick start
75
+
76
+ ### CLI
77
+
78
+ ```bash
79
+ # Build a code graph from a checkout
80
+ codingest build /path/to/repo
81
+ # → /path/to/repo/.kglite/code-review.kgl
82
+
83
+ # Build committed content at specific revisions (multi-rev merged graph)
84
+ codingest build /path/to/repo --revs v1.0 v2.0
85
+
86
+ # Check whether an existing graph is stale relative to the tree
87
+ codingest status /path/to/repo
88
+ ```
89
+
90
+ Then query or describe the `.kgl` with kglite (`kglite.load(...)`, the `kglite`
91
+ shell, or any MCP/Bolt client).
92
+
93
+ ### MCP server
94
+
95
+ ```bash
96
+ # Serve a live code-graph workbench over stdio for an MCP client / agent
97
+ codingest-mcp --root-dir /path/to/repo
98
+ ```
99
+
100
+ `codingest-mcp` embeds the `kglite-mcp-server` tool surface (`set_root_dir`,
101
+ `graph_overview`, `cypher_query`, `read_code_source`, …) and injects the
102
+ codingest builder, so `set_root_dir` builds a graph. Running plain
103
+ `kglite-mcp-server` against a workspace **refuses to build** — it has no
104
+ in-tree builder anymore. See the [MCP docs](https://codingest.readthedocs.io).
105
+
106
+ ### Python wheel
107
+
108
+ ```python
109
+ import codingest
110
+
111
+ g = codingest.build(".") # returns a real kglite.KnowledgeGraph
112
+ g.cypher("MATCH (f:Function) RETURN f.name LIMIT 10")
113
+ codingest.build(".", save_to="code.kgl") # also persist the .kgl
114
+ codingest.build(".", rev="v1.0") # build a git revision (or revs=[...])
115
+ codingest.repo_tree("owner/name") # clone a GitHub repo and build
116
+ ```
117
+
118
+ **The `.kgl`-bytes handoff.** The `codingest` and `kglite` wheels are two
119
+ separate compiled extensions and can't share live Rust objects, so `build()`
120
+ constructs the graph with codingest's native builder, serializes it to a `.kgl`,
121
+ then calls the *installed* `kglite` wheel's `load()` and returns **that** object
122
+ — a genuine `kglite.KnowledgeGraph`, so every downstream kglite API works.
123
+
124
+ **Bundled CLI.** The same wheel also provides the `codingest` terminal command
125
+ (a `codingest/cli.py` console-script shim forwarding into the linked
126
+ `codingest-cli` library), so `codingest build`/`status` works straight after
127
+ `pip install codingest` — identical semantics to `cargo install codingest-cli`.
128
+
129
+ ### Rust crate
130
+
131
+ ```toml
132
+ [dependencies]
133
+ codingest = "0.1" # needs kglite 0.14 on crates.io (see Requirements)
134
+ kglite = "0.14"
135
+ ```
136
+
137
+ ```rust
138
+ use codingest::build_code_tree; // = builder::run_with_options
139
+ let graph = build_code_tree(dir, /*verbose=*/false, /*include_tests=*/true,
140
+ /*save_to=*/None, /*max_loc=*/None, /*include_docs=*/false)?;
141
+ // Query with kglite's Cypher pipeline, persist with kglite::api::io, …
142
+ ```
143
+
144
+ ## Workspace layout
145
+
146
+ | Crate | What it is |
147
+ |---|---|
148
+ | `crates/codingest` | The component library (`codingest`): builder, parsers, manifest reader, docs pass, multi-rev merge, cross-language edges. Extracted from the former `KGLite/crates/kglite/src/code_tree/` (removed upstream 2026-07-16) and re-targeted at the public `kglite::api` facade. Ships the `codingest_stats` + `codingest_bench` binaries. |
149
+ | `crates/codingest-cli` | `codingest` binary — `build` a checkout or git revision(s) into a `.kgl` graph, `status` to check staleness. |
150
+ | `crates/codingest-mcp` | `codingest-mcp` binary — the full MCP tool surface imported from the `kglite-mcp-server` library, with the codingest builder injected. |
151
+ | `crates/codingest-py` | PyO3 wrapper built by maturin into the `codingest` wheel (`pip install codingest`). Python package source is `codingest/`; `pyproject.toml` drives the maturin build. Not published to crates.io (`publish = false`). |
152
+
153
+ ## CI-equivalent local gate: `make gate`
154
+
155
+ `make gate` is the single-entry-point local gate that mirrors CI (`cargo fmt
156
+ --check`, `cargo clippy --workspace --all-targets -- -D warnings`, workspace
157
+ build + test incl. the golden oracle) and adds codingest-specific checks
158
+ (determinism reproducer, `codingest_bench` parity smoke, the wheel build + the
159
+ `tests/python` acceptance suite). Run it before pushing. Individual steps are
160
+ also targets (`make clippy`, `make determinism`, …); `make fmt` auto-formats.
161
+
162
+ ### The golden-digest oracle
163
+
164
+ KGLite deleted its in-tree `code_tree` builder on 2026-07-16, so the old
165
+ two-builder parity sweep is gone. The authority it enforced was **frozen** while
166
+ the builders were still verified identical, into per-corpus SHA-256 digests
167
+ under `crates/codingest/tests/goldens/` (committed fixtures — no network). The
168
+ `golden_parity` test builds each corpus with only the codingest builder, digests
169
+ a canonical exhaustive graph rendering, and compares to the frozen golden. The
170
+ multi-rev fixture is guarded instead by `rev_self_consistency`. Regenerate
171
+ goldens only for deliberate builder-behavior changes:
172
+ `cargo test -p codingest --test parity -- --ignored capture_goldens` (details in
173
+ `crates/codingest/tests/goldens/README.md`).
174
+
175
+ ## Dependency policy
176
+
177
+ `kglite` and `kglite-mcp-server` are path dependencies on the sister checkout
178
+ `../KGLite` with a `version = "0.13"` crates.io fallback. The fallback is kept
179
+ at `0.13` (not `0.14`) **only** because the local sister checkout is still
180
+ versioned 0.13.4 while carrying the 0.14 APIs — a path dep's version requirement
181
+ must be satisfiable by the path crate, so `0.14` would break the local build
182
+ today. When kglite 0.14.0 ships, the maintainer bumps both fallbacks to `0.14`
183
+ and flips the `CODINGEST_KGLITE_READY` CI variable (see the workspace
184
+ `Cargo.toml` note and `.github/workflows/ci.yml`).
185
+
186
+ ## Parity with the (now-removed) in-tree component
187
+
188
+ codingest was extracted to be feature- and performance-identical to kglite's
189
+ in-tree `code_tree`. KGLite removed that module on 2026-07-16, so parity is now
190
+ enforced against a **frozen record** of its last-known-good output rather than
191
+ live cross-comparison. See `PARITY.md` (stats-diff + timing), `BENCHMARKS.md`
192
+ (build-time + Cypher benchmarks), `crates/codingest/tests/parity.rs` (the golden
193
+ oracle), and `docs/mcp-parity.md` (the MCP↔builder coupling and the hook).
194
+
195
+ `tests/python-legacy/` preserves KGLite's full 47-file `kglite.code_tree`
196
+ behavioral suite verbatim as the dormant behavioral spec — the source of truth
197
+ for what the Python builder guaranteed (see its README).
198
+
199
+ ## License
200
+
201
+ MIT © Kristian dF Kollsgård. codingest is an independent project; it depends on
202
+ `kglite` at runtime but is not otherwise affiliated with it.
203
+
@@ -0,0 +1,10 @@
1
+ codingest/__init__.py,sha256=ZWRR1wNYROPOD6Wlyne23irAB20SsapFUY5eJB3Lc9U,1649
2
+ codingest/__init__.pyi,sha256=69KtINplfVD-BWJGf1mqxsmmuHyQ0xHwHknsjLaTP5s,6015
3
+ codingest/cli.py,sha256=bACzbAfoRCtUJtp-3Txxdhf8zlee5EKt-2Z3sk0PXLY,982
4
+ codingest/codingest.pyd,sha256=11D0FkhgTogxDM11m5O--GFlARxQOCSkuqj4OfQWU7c,29216256
5
+ codingest-0.1.0.dist-info/METADATA,sha256=7NVAX4e8h3ZdLXYI38vb6HFjWjnuVZgUg-0gWcql93c,10125
6
+ codingest-0.1.0.dist-info/WHEEL,sha256=_qjkWZs5yrFgc7wGyX42BWq6PiACrY0XI82VSrZ_57E,96
7
+ codingest-0.1.0.dist-info/entry_points.txt,sha256=z4H1v0B9AYriCtsIjJqVJj3910Gc-EYi0TYLtJyp5hQ,47
8
+ codingest-0.1.0.dist-info/licenses/LICENSE,sha256=q0gXpC0K7UDWntzOORLPFJ1qRsJneOljj9IE_TBHX0I,1100
9
+ codingest-0.1.0.dist-info/sboms/codingest-py.cyclonedx.json,sha256=TmZZ2GuWnISXL-OkUX-HlTDO4uw0y8kwM7XiYmYIr_4,209914
10
+ codingest-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.14.1)
3
+ Root-Is-Purelib: false
4
+ Tag: cp310-abi3-win_amd64
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ codingest=codingest.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Kristian dF Kollsgård
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.