hubuum-client 0.0.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.
Files changed (55) hide show
  1. hubuum_client-0.0.1/.github/dependabot.yml +31 -0
  2. hubuum_client-0.0.1/.github/pull_request_template.md +23 -0
  3. hubuum_client-0.0.1/.github/workflows/ci.yml +95 -0
  4. hubuum_client-0.0.1/.github/workflows/release.yml +58 -0
  5. hubuum_client-0.0.1/.gitignore +12 -0
  6. hubuum_client-0.0.1/.python-version +1 -0
  7. hubuum_client-0.0.1/AGENTS.md +86 -0
  8. hubuum_client-0.0.1/CHANGELOG.md +84 -0
  9. hubuum_client-0.0.1/CONTRIBUTING.md +45 -0
  10. hubuum_client-0.0.1/LICENSE +21 -0
  11. hubuum_client-0.0.1/PKG-INFO +238 -0
  12. hubuum_client-0.0.1/README.md +193 -0
  13. hubuum_client-0.0.1/SECURITY.md +19 -0
  14. hubuum_client-0.0.1/docs/advanced.md +163 -0
  15. hubuum_client-0.0.1/docs/api.md +93 -0
  16. hubuum_client-0.0.1/docs/changelog.md +4 -0
  17. hubuum_client-0.0.1/docs/client.md +156 -0
  18. hubuum_client-0.0.1/docs/compatibility.md +75 -0
  19. hubuum_client-0.0.1/docs/e2e.md +74 -0
  20. hubuum_client-0.0.1/docs/index.md +57 -0
  21. hubuum_client-0.0.1/docs/querying.md +176 -0
  22. hubuum_client-0.0.1/docs/releasing.md +55 -0
  23. hubuum_client-0.0.1/mkdocs.yml +66 -0
  24. hubuum_client-0.0.1/pyproject.toml +97 -0
  25. hubuum_client-0.0.1/scripts/check-openapi-contract.py +185 -0
  26. hubuum_client-0.0.1/scripts/configure-github-repository.sh +230 -0
  27. hubuum_client-0.0.1/scripts/run-e2e-tests.sh +180 -0
  28. hubuum_client-0.0.1/src/hubuum_client/__init__.py +130 -0
  29. hubuum_client-0.0.1/src/hubuum_client/_constants.py +8 -0
  30. hubuum_client-0.0.1/src/hubuum_client/_operations.py +915 -0
  31. hubuum_client-0.0.1/src/hubuum_client/_transport.py +386 -0
  32. hubuum_client-0.0.1/src/hubuum_client/async_client.py +299 -0
  33. hubuum_client-0.0.1/src/hubuum_client/async_services.py +708 -0
  34. hubuum_client-0.0.1/src/hubuum_client/client.py +302 -0
  35. hubuum_client-0.0.1/src/hubuum_client/errors.py +89 -0
  36. hubuum_client-0.0.1/src/hubuum_client/models.py +321 -0
  37. hubuum_client-0.0.1/src/hubuum_client/openapi.py +225 -0
  38. hubuum_client-0.0.1/src/hubuum_client/options.py +47 -0
  39. hubuum_client-0.0.1/src/hubuum_client/py.typed +1 -0
  40. hubuum_client-0.0.1/src/hubuum_client/query.py +302 -0
  41. hubuum_client-0.0.1/src/hubuum_client/services.py +686 -0
  42. hubuum_client-0.0.1/src/hubuum_client/streaming.py +59 -0
  43. hubuum_client-0.0.1/src/hubuum_client/types.py +115 -0
  44. hubuum_client-0.0.1/tests/e2e/conftest.py +42 -0
  45. hubuum_client-0.0.1/tests/e2e/test_core.py +500 -0
  46. hubuum_client-0.0.1/tests/unit/conftest.py +45 -0
  47. hubuum_client-0.0.1/tests/unit/test_async_client.py +285 -0
  48. hubuum_client-0.0.1/tests/unit/test_client.py +630 -0
  49. hubuum_client-0.0.1/tests/unit/test_contract_script.py +23 -0
  50. hubuum_client-0.0.1/tests/unit/test_models.py +124 -0
  51. hubuum_client-0.0.1/tests/unit/test_named_services.py +289 -0
  52. hubuum_client-0.0.1/tests/unit/test_openapi.py +371 -0
  53. hubuum_client-0.0.1/tests/unit/test_query.py +139 -0
  54. hubuum_client-0.0.1/tests/unit/test_services.py +680 -0
  55. hubuum_client-0.0.1/uv.lock +1330 -0
@@ -0,0 +1,31 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: uv
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ day: monday
8
+ time: "06:00"
9
+ timezone: Europe/Oslo
10
+ cooldown:
11
+ default-days: 7
12
+ groups:
13
+ python-dependencies:
14
+ patterns:
15
+ - "*"
16
+ open-pull-requests-limit: 5
17
+
18
+ - package-ecosystem: github-actions
19
+ directory: /
20
+ schedule:
21
+ interval: weekly
22
+ day: monday
23
+ time: "06:00"
24
+ timezone: Europe/Oslo
25
+ cooldown:
26
+ default-days: 7
27
+ groups:
28
+ github-actions:
29
+ patterns:
30
+ - "*"
31
+ open-pull-requests-limit: 5
@@ -0,0 +1,23 @@
1
+ ## Summary
2
+
3
+ <!-- What changed, and why? -->
4
+
5
+ ## User impact
6
+
7
+ <!-- Describe public API, compatibility, security, or operational impact. -->
8
+
9
+ ## Validation
10
+
11
+ - [ ] Ruff formatting and linting
12
+ - [ ] mypy
13
+ - [ ] Unit tests with coverage
14
+ - [ ] Strict documentation build
15
+ - [ ] Package build
16
+ - [ ] Pinned-server e2e tests, when server behavior is affected
17
+
18
+ ## Checklist
19
+
20
+ - [ ] Tests cover the change, including sync/async parity where relevant
21
+ - [ ] Documentation is updated
22
+ - [ ] `[Unreleased]` in `CHANGELOG.md` is updated for user-visible changes
23
+ - [ ] No credentials, tokens, production data, or generated artifacts are included
@@ -0,0 +1,95 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ packages: read
12
+
13
+ env:
14
+ UV_FROZEN: "1"
15
+ HUBUUM_TARGET_SERVER_VERSION: "0.0.3"
16
+ HUBUUM_TARGET_SERVER_IMAGE: ghcr.io/hubuum/hubuum-server:v0.0.3@sha256:f1f57a991f69005ee81f24e77533e61f75b5586949d98cccf1c40fc4329eb186
17
+
18
+ jobs:
19
+ quality:
20
+ name: Lint, types, docs, and package
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
24
+ with:
25
+ persist-credentials: false
26
+ - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
27
+ with:
28
+ python-version: "3.11"
29
+ - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
30
+ with:
31
+ enable-cache: true
32
+ - run: uv sync --extra dev
33
+ - run: uv run ruff format --check .
34
+ - run: uv run ruff check .
35
+ - run: uv run mypy
36
+ - run: uv run bandit -q -r src scripts
37
+ - run: uv run zizmor .
38
+ - run: uv run mkdocs build --strict
39
+ - run: uv build
40
+
41
+ test:
42
+ name: Python ${{ matrix.python }}
43
+ runs-on: ubuntu-latest
44
+ strategy:
45
+ fail-fast: false
46
+ matrix:
47
+ python: ["3.11", "3.12", "3.13", "3.14"]
48
+ steps:
49
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
50
+ with:
51
+ persist-credentials: false
52
+ - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
53
+ with:
54
+ python-version: ${{ matrix.python }}
55
+ - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
56
+ with:
57
+ enable-cache: true
58
+ - run: uv sync --extra test
59
+ - run: uv run pytest --cov=hubuum_client
60
+
61
+ server-contract:
62
+ name: Hubuum v0.0.3 OpenAPI contract
63
+ runs-on: ubuntu-latest
64
+ steps:
65
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
66
+ with:
67
+ persist-credentials: false
68
+ - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
69
+ with:
70
+ python-version: "3.11"
71
+ - run: python scripts/check-openapi-contract.py
72
+
73
+ e2e:
74
+ name: Pinned Hubuum v0.0.3 e2e
75
+ runs-on: ubuntu-latest
76
+ needs: [quality, test, server-contract]
77
+ steps:
78
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
79
+ with:
80
+ persist-credentials: false
81
+ - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
82
+ with:
83
+ python-version: "3.11"
84
+ - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
85
+ with:
86
+ enable-cache: true
87
+ - uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
88
+ with:
89
+ registry: ghcr.io
90
+ username: ${{ github.actor }}
91
+ password: ${{ secrets.GITHUB_TOKEN }}
92
+ - name: Build wheel and run pinned live-server suite
93
+ run: ./scripts/run-e2e-tests.sh
94
+ env:
95
+ HUBUUM_E2E_SERVER_IMAGE: ${{ env.HUBUUM_TARGET_SERVER_IMAGE }}
@@ -0,0 +1,58 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: release-${{ github.ref }}
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ build:
17
+ name: Build release distributions
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
21
+ with:
22
+ persist-credentials: false
23
+ - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
24
+ with:
25
+ python-version: "3.11"
26
+ - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
27
+ with:
28
+ enable-cache: false
29
+ - name: Verify release tag
30
+ if: github.ref_type == 'tag'
31
+ run: test "${GITHUB_REF_NAME}" = "v$(uv version --short)"
32
+ - name: Build distributions
33
+ run: uv build
34
+ - name: Validate distributions
35
+ run: uvx --from twine==6.2.0 twine check --strict dist/*
36
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
37
+ with:
38
+ name: python-package-distributions
39
+ path: dist/
40
+ if-no-files-found: error
41
+
42
+ publish-pypi:
43
+ name: Publish to PyPI
44
+ if: github.event_name == 'push' && vars.PYPI_PUBLISH_ENABLED == 'true'
45
+ needs: build
46
+ runs-on: ubuntu-latest
47
+ environment:
48
+ name: pypi
49
+ url: https://pypi.org/p/hubuum-client
50
+ permissions:
51
+ id-token: write
52
+ steps:
53
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
54
+ with:
55
+ name: python-package-distributions
56
+ path: dist/
57
+ - name: Publish distributions
58
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .coverage
5
+ .mypy_cache/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .venv/
9
+ build/
10
+ dist/
11
+ htmlcov/
12
+ site/
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,86 @@
1
+ # Repository Guidelines
2
+
3
+ These instructions apply to the entire repository.
4
+
5
+ ## Sources of truth
6
+
7
+ - `pyproject.toml` defines the package version, supported Python versions,
8
+ dependencies, and verification configuration.
9
+ - `src/hubuum_client/_constants.py` defines the target Hubuum server version and
10
+ immutable test image. Keep those values synchronized with `README.md`,
11
+ `CHANGELOG.md`, `docs/compatibility.md`, the e2e script, and CI.
12
+ - Hubuum server `v0.0.3` and its committed `docs/openapi.json` are the
13
+ authoritative API contract. Do not infer wire fields from Python naming
14
+ preferences when the contract says otherwise.
15
+ - Maintain sync/async capability parity unless a runtime constraint is
16
+ documented explicitly.
17
+
18
+ ## Architecture
19
+
20
+ - Put response and request types in `models.py`, small ID and secret values in
21
+ `types.py`, and immutable list controls in `query.py`.
22
+ - Keep shared URL validation, decoding, and error mapping in `_transport.py`.
23
+ - Synchronous HTTP behavior belongs in `client.py` and `services.py`; matching
24
+ asynchronous behavior belongs in `async_client.py` and `async_services.py`.
25
+ - Typed resource services are the preferred public API. Keep `request()` as a
26
+ constrained extension point for authenticated relative routes.
27
+ - Never retain or expose bearer tokens, passwords, authorization headers, or
28
+ secret-bearing request bodies in exceptions, representations, or logs.
29
+
30
+ ## Verification
31
+
32
+ Run all non-container checks before considering a change complete:
33
+
34
+ ```bash
35
+ uv sync --extra dev
36
+ uv run ruff format --check .
37
+ uv run ruff check .
38
+ uv run mypy
39
+ uv run bandit -q -r src scripts
40
+ uv run zizmor .
41
+ uv run pytest --cov
42
+ uv run mkdocs build --strict
43
+ uv build
44
+ ```
45
+
46
+ Focused tests are useful while iterating but do not replace the full unit suite.
47
+ Every behavior change needs regression coverage for both sync and async paths
48
+ when they could diverge.
49
+
50
+ ## Docker-backed end-to-end tests
51
+
52
+ Run the complete live-server suite with:
53
+
54
+ ```bash
55
+ ./scripts/run-e2e-tests.sh
56
+ ```
57
+
58
+ The wrapper starts PostgreSQL and the immutable Hubuum v0.0.3 server image,
59
+ waits for readiness, obtains the generated administrator password, runs the
60
+ tests under `tests/e2e`, and removes its containers and network. Docker and
61
+ Podman are both supported.
62
+
63
+ Useful environment variables:
64
+
65
+ - `HUBUUM_E2E_SERVER_IMAGE`: server image override; compatibility evidence must
66
+ use the pinned default.
67
+ - `HUBUUM_E2E_POSTGRES_IMAGE`: PostgreSQL image override.
68
+ - `HUBUUM_E2E_BASE_URL` and `HUBUUM_E2E_ADMIN_PASSWORD`: run against a
69
+ caller-managed server instead of provisioning containers.
70
+ - `HUBUUM_E2E_CONTAINER_RUNTIME`: select `docker` or `podman`.
71
+ - `HUBUUM_E2E_KEEP=1`: retain resources for diagnosis.
72
+ - `HUBUUM_E2E_TIMEOUT`: stack startup timeout in seconds.
73
+
74
+ Live tests must use unique resource names, avoid assumptions about global IDs,
75
+ and clean up resources when doing so does not hide the primary failure. Do not
76
+ describe unit tests or an unpinned live run as v0.0.3 compatibility evidence.
77
+
78
+ ## Change discipline
79
+
80
+ - Preserve unrelated user changes and keep the worktree scoped.
81
+ - Add user-visible changes to `[Unreleased]` in `CHANGELOG.md`.
82
+ - Update documentation when public behavior, requirements, compatibility, or
83
+ the e2e workflow changes.
84
+ - Prefer clear, idiomatic Python and explicit types over clever abstractions.
85
+ - Do not suppress Ruff or mypy broadly; fix the type or isolate a justified,
86
+ narrow exception.
@@ -0,0 +1,84 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases follow
5
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.0.1] - 2026-07-25
10
+
11
+ ### Added
12
+
13
+ - Initial typed Python client targeting Hubuum server v0.0.3.
14
+ - Synchronous and asynchronous clients with equivalent resource services.
15
+ - Typed Pydantic models and distinct ID types for core Hubuum resources.
16
+ - Collection, class, object, user, group, relation, and task workflows.
17
+ - Immutable filtering, cursor pages, bounded automatic pagination, and task polling.
18
+ - Structured transport, decoding, authentication, permission, not-found,
19
+ conflict, and rate-limit exceptions.
20
+ - Redacted credentials and access tokens plus origin-locked raw requests.
21
+ - Unit, typing, documentation, and Docker-backed e2e test infrastructure.
22
+ - GitHub CI, dependency update automation, contribution guidance, and an
23
+ explicitly gated PyPI trusted-publishing workflow.
24
+ - Added an immutable fluent interface for nested object `data` filtering,
25
+ covering scalar, range, array, object-key, null, and IP/network operators,
26
+ with pinned-server end-to-end coverage.
27
+ - Added a contract-checked operation interface covering all 196 Hubuum v0.0.3
28
+ OpenAPI endpoints, including authenticated/public policy, JSON/text/binary
29
+ response decoding, and incremental SSE consumption.
30
+ - Added the complete class/object `by-name` surface and validated atomic RFC
31
+ 6902 object-data patch operations, covering the API workflows used by
32
+ `hubuum-import-miami`.
33
+ - Added `classes.by_id(id)` as the numeric counterpart to `classes.by_name(name)`,
34
+ with synchronous and asynchronous class operations and nested `.objects`
35
+ access.
36
+
37
+ ### Changed
38
+
39
+ - Raised the branch-aware unit coverage gate from 90% to 95% after adding
40
+ request-construction coverage for every pinned OpenAPI operation and focused
41
+ transport, streaming, decoding, pagination, and sync/async failure tests.
42
+ - Strengthened pinned-server compatibility evidence with forced multi-page
43
+ cursor traversal, a complete async resource lifecycle, non-administrator
44
+ permission boundaries, and live `400`, `401`, `403`, `404`, and `409` error
45
+ mapping; the e2e wrapper now tests the built wheel in an isolated environment.
46
+ - Changed PyPI trusted publishing to run from protected `v*` tag pushes, with a
47
+ manually approved GitHub environment and an exact package-version check.
48
+ - Added an evidence-linked client/server compatibility matrix and identified
49
+ the pinned e2e server image by both its `v0.0.3` tag and immutable digest.
50
+ - Updated every GitHub Action to its latest immutable release commit and
51
+ corrected invalid checkout and Python setup action versions; release artifact
52
+ validation now uses an explicit Twine version.
53
+ - Disabled persisted checkout credentials and release-job caching, added a
54
+ dependency update cooldown, bounded contract downloads to HTTPS sources, and
55
+ added Bandit and zizmor security gates to CI.
56
+ - Aligned synchronous and asynchronous task polling on the same
57
+ `timeout_seconds` keyword, validated polling and pagination bounds before
58
+ doing work, and prevented poll sleeps from exceeding the remaining timeout.
59
+ - Fixed the end-to-end wrapper on Bash 3.2 when invoked without additional
60
+ pytest arguments.
61
+ - Replaced long client and raw-request parameter lists with shared typed
62
+ `ClientOptions` and `RequestOptions` values and re-enabled Ruff's argument
63
+ count rule.
64
+ - Updated examples to prefer explicit nested class selectors and documented
65
+ application-lifetime client reuse, HTTP connection pooling, and shutdown.
66
+ - Returned group memberships as contract-validated `PrincipalMember` values
67
+ and added cursor-aware membership page and collection helpers.
68
+ - Parsed both standard `Retry-After` forms into safe, non-negative rate-limit
69
+ delays and ignored malformed or non-finite values.
70
+ - Cached lazily created resource-service accessors per client while keeping
71
+ class-scoped object services on demand.
72
+
73
+ ### Security
74
+
75
+ - Hardened origin-locked requests against nested URL traversal, ambiguous path
76
+ characters, and caller-supplied `Host` headers.
77
+ - Made bearer-header replacement case-insensitive and redact request secrets
78
+ from transport, API, and decoding exception details.
79
+ - Redacted values under sensitive query parameter names from API and transport
80
+ error diagnostics.
81
+ - Redacted login tokens from model representations.
82
+
83
+ [Unreleased]: https://github.com/hubuum/hubuum-client-python/compare/v0.0.1...HEAD
84
+ [0.0.1]: https://github.com/hubuum/hubuum-client-python/releases/tag/v0.0.1
@@ -0,0 +1,45 @@
1
+ # Contributing
2
+
3
+ Thank you for helping improve the Hubuum Python client.
4
+
5
+ ## Development setup
6
+
7
+ Install [uv](https://docs.astral.sh/uv/), clone the repository, and create the
8
+ development environment:
9
+
10
+ ```bash
11
+ uv sync --extra dev
12
+ ```
13
+
14
+ Before opening a pull request, run the same non-container checks as CI:
15
+
16
+ ```bash
17
+ uv run ruff format --check .
18
+ uv run ruff check .
19
+ uv run mypy
20
+ uv run bandit -q -r src scripts
21
+ uv run zizmor .
22
+ uv run pytest --cov
23
+ uv run mkdocs build --strict
24
+ uv build
25
+ ```
26
+
27
+ Changes that affect server behavior should also pass the pinned live-server
28
+ suite:
29
+
30
+ ```bash
31
+ ./scripts/run-e2e-tests.sh
32
+ ```
33
+
34
+ ## Pull requests
35
+
36
+ - Keep each pull request focused and explain its user-visible effect.
37
+ - Add tests for behavior changes, including sync and async paths when they can
38
+ diverge.
39
+ - Update documentation and the `[Unreleased]` changelog section when public
40
+ behavior, compatibility, or requirements change.
41
+ - Do not include credentials, bearer tokens, server data, or generated build
42
+ artifacts.
43
+
44
+ By contributing, you agree that your contribution is licensed under the
45
+ repository's MIT License.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hubuum contributors
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.