dot-inference 2.0.2__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 (49) hide show
  1. dot_inference-2.0.2/.env.template +49 -0
  2. dot_inference-2.0.2/.gitignore +58 -0
  3. dot_inference-2.0.2/.gitlab-ci.yml +180 -0
  4. dot_inference-2.0.2/.pre-commit-config.yaml +34 -0
  5. dot_inference-2.0.2/.python-version +1 -0
  6. dot_inference-2.0.2/AUTHORS.md +14 -0
  7. dot_inference-2.0.2/CHANGELOG.md +67 -0
  8. dot_inference-2.0.2/CONTRIBUTING.md +87 -0
  9. dot_inference-2.0.2/DCO +34 -0
  10. dot_inference-2.0.2/LICENSE.md +660 -0
  11. dot_inference-2.0.2/PKG-INFO +351 -0
  12. dot_inference-2.0.2/README.md +324 -0
  13. dot_inference-2.0.2/docs/ARCHITECTURE.md +293 -0
  14. dot_inference-2.0.2/docs/DEVELOPMENT.md +127 -0
  15. dot_inference-2.0.2/docs/PUBLISHING.md +115 -0
  16. dot_inference-2.0.2/docs/VERSIONING.md +120 -0
  17. dot_inference-2.0.2/examples/demo.py +486 -0
  18. dot_inference-2.0.2/examples/demo_streaming.py +233 -0
  19. dot_inference-2.0.2/examples/doc_stream.md +159 -0
  20. dot_inference-2.0.2/pyproject.toml +117 -0
  21. dot_inference-2.0.2/scripts/test_all_models.py +107 -0
  22. dot_inference-2.0.2/src/dot_inference/README.md +83 -0
  23. dot_inference-2.0.2/src/dot_inference/__init__.py +86 -0
  24. dot_inference-2.0.2/src/dot_inference/_client.py +520 -0
  25. dot_inference-2.0.2/src/dot_inference/_cost_tracker.py +71 -0
  26. dot_inference-2.0.2/src/dot_inference/_llm_registry.py +302 -0
  27. dot_inference-2.0.2/src/dot_inference/_local_check.py +76 -0
  28. dot_inference-2.0.2/src/dot_inference/_mistral_compat.py +530 -0
  29. dot_inference-2.0.2/src/dot_inference/_openai_compat.py +570 -0
  30. dot_inference-2.0.2/src/dot_inference/_rate_limit.py +64 -0
  31. dot_inference-2.0.2/src/dot_inference/_retry.py +66 -0
  32. dot_inference-2.0.2/src/dot_inference/_sync.py +49 -0
  33. dot_inference-2.0.2/src/dot_inference/_types.py +229 -0
  34. dot_inference-2.0.2/src/dot_inference/mock.py +151 -0
  35. dot_inference-2.0.2/src/dot_inference/models.yaml +481 -0
  36. dot_inference-2.0.2/src/dot_inference/settings.py +138 -0
  37. dot_inference-2.0.2/tests/__init__.py +2 -0
  38. dot_inference-2.0.2/tests/test_cost_tracker.py +62 -0
  39. dot_inference-2.0.2/tests/test_factories.py +151 -0
  40. dot_inference-2.0.2/tests/test_llm_registry.py +272 -0
  41. dot_inference-2.0.2/tests/test_local_check.py +103 -0
  42. dot_inference-2.0.2/tests/test_mistral_compat.py +341 -0
  43. dot_inference-2.0.2/tests/test_mistral_live.py +142 -0
  44. dot_inference-2.0.2/tests/test_openai_compat.py +753 -0
  45. dot_inference-2.0.2/tests/test_rate_limit.py +47 -0
  46. dot_inference-2.0.2/tests/test_retry.py +77 -0
  47. dot_inference-2.0.2/tests/test_settings.py +151 -0
  48. dot_inference-2.0.2/tests/test_types.py +59 -0
  49. dot_inference-2.0.2/uv.lock +727 -0
@@ -0,0 +1,49 @@
1
+ # === GENERATION ===
2
+ DOTI_GENERATION__PROVIDER=
3
+
4
+ # --- OpenAI ---
5
+ DOTI_GENERATION__OPENAI__MODEL_NAME=
6
+ DOTI_GENERATION__OPENAI__API_KEY=
7
+
8
+ # --- OpenRouter ---
9
+ DOTI_GENERATION__OPENROUTER__MODEL_NAME=
10
+ DOTI_GENERATION__OPENROUTER__API_KEY=
11
+
12
+ # --- Mistral ---
13
+ DOTI_GENERATION__MISTRAL__MODEL_NAME=
14
+ DOTI_GENERATION__MISTRAL__API_KEY=
15
+
16
+ # --- Azure ---
17
+ DOTI_GENERATION__AZURE__MODEL_NAME=
18
+ DOTI_GENERATION__AZURE__API_KEY=
19
+ DOTI_GENERATION__AZURE__BASE_URL=
20
+ DOTI_GENERATION__AZURE__API_VERSION=
21
+
22
+ # --- Local ---
23
+ DOTI_GENERATION__LOCAL__MODEL_NAME=
24
+ DOTI_GENERATION__LOCAL__BASE_URL=
25
+
26
+ # === EMBEDDING ===
27
+ DOTI_EMBEDDING__PROVIDER=
28
+
29
+ # --- OpenAI ---
30
+ DOTI_EMBEDDING__OPENAI__MODEL_NAME=
31
+ DOTI_EMBEDDING__OPENAI__API_KEY=
32
+
33
+ # --- OpenRouter ---
34
+ DOTI_EMBEDDING__OPENROUTER__MODEL_NAME=
35
+ DOTI_EMBEDDING__OPENROUTER__API_KEY=
36
+
37
+ # --- Mistral ---
38
+ DOTI_EMBEDDING__MISTRAL__MODEL_NAME=
39
+ DOTI_EMBEDDING__MISTRAL__API_KEY=
40
+
41
+ # --- Azure ---
42
+ DOTI_EMBEDDING__AZURE__MODEL_NAME=
43
+ DOTI_EMBEDDING__AZURE__API_KEY=
44
+ DOTI_EMBEDDING__AZURE__BASE_URL=
45
+ DOTI_EMBEDDING__AZURE__API_VERSION=
46
+
47
+ # --- Local ---
48
+ DOTI_EMBEDDING__LOCAL__MODEL_NAME=
49
+ DOTI_EMBEDDING__LOCAL__BASE_URL=
@@ -0,0 +1,58 @@
1
+ # Python
2
+ *.py[cod]
3
+ *.pyo
4
+ *.egg
5
+ *.egg-info/
6
+ **/__pycache__/
7
+ *.so
8
+ build/
9
+ dist/
10
+
11
+ # Tooling caches
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .ty_cache/
15
+ .mypy_cache/
16
+
17
+ # Coverage
18
+ .coverage
19
+ .coverage.*
20
+ coverage.xml
21
+ htmlcov/
22
+ coverage_html_report/
23
+
24
+ # Environment & Secrets
25
+ .venv/
26
+ venv/
27
+ .env
28
+ .env.*
29
+ !.env.template
30
+
31
+ # IDE
32
+ .vscode/
33
+ .idea/
34
+
35
+ # Agent config
36
+ .agents/
37
+ .claude/
38
+
39
+ # OS
40
+ .DS_Store
41
+ Thumbs.db
42
+
43
+ # Jupyter
44
+ .ipynb_checkpoints/
45
+
46
+ # Local files
47
+ local/
48
+ sources/
49
+ working-notes/
50
+
51
+ # Pin Python (overrides the global ignore)
52
+ !.python-version
53
+
54
+ # --- CI caches (UV_CACHE_DIR / PRE_COMMIT_HOME point here in .gitlab-ci.yml) ---
55
+ # Not just local hygiene: hatchling would otherwise pull them into the sdist,
56
+ # and a cached virtualenv carries absolute symlinks that break the build.
57
+ .uv-cache/
58
+ .pre-commit-cache/
@@ -0,0 +1,180 @@
1
+ # Pipeline for a Python library published to PyPI.
2
+ #
3
+ # quality lint, format and type checks (pre-commit)
4
+ # test pytest on every supported Python version
5
+ # publish tag-only: build, then TestPyPI, then PyPI behind a manual gate
6
+ #
7
+ # Publishing uses PyPI Trusted Publishing (OIDC): GitLab mints a short-lived ID
8
+ # token, PyPI exchanges it for a publish token valid for minutes. No API token
9
+ # is stored in the project. Declare this repository as a trusted publisher at
10
+ # https://pypi.org/manage/project/dot-inference/settings/publishing/ (and the same on
11
+ # test.pypi.org) before the first release.
12
+
13
+ workflow:
14
+ rules:
15
+ # Merge requests take priority...
16
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
17
+ when: always
18
+ # ...release tags (vX.Y.Z, optionally -rc.N)...
19
+ - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+(?:-rc\.\d+)?$/
20
+ when: always
21
+ # ...and pushes to main. The MR rule above keeps this from double-firing.
22
+ - if: $CI_COMMIT_BRANCH == "main"
23
+ when: always
24
+ # Anything else (branch pushes without an MR, malformed tags) runs nothing.
25
+ - when: never
26
+
27
+ stages:
28
+ - quality
29
+ - test
30
+ - publish
31
+
32
+ variables:
33
+ UV_CACHE_DIR: "$CI_PROJECT_DIR/.uv-cache"
34
+ PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.pre-commit-cache"
35
+ # Keep resolution reproducible: fail rather than silently relock.
36
+ UV_FROZEN: "1"
37
+
38
+ default:
39
+ image: ghcr.io/astral-sh/uv:python3.12-bookworm-slim
40
+ cache:
41
+ key:
42
+ files:
43
+ - uv.lock
44
+ paths:
45
+ - .uv-cache
46
+ - .pre-commit-cache
47
+
48
+ # --------------------------------------------------------------------------
49
+ # quality
50
+ # --------------------------------------------------------------------------
51
+
52
+ quality:
53
+ stage: quality
54
+ before_script:
55
+ - apt-get update && apt-get install -y --no-install-recommends git
56
+ - uv sync --all-extras --all-groups
57
+ script:
58
+ - uv run pre-commit run --all-files --show-diff-on-failure
59
+
60
+ # --------------------------------------------------------------------------
61
+ # test
62
+ # --------------------------------------------------------------------------
63
+
64
+ test:
65
+ stage: test
66
+ image: ghcr.io/astral-sh/uv:python$PYTHON_VERSION-bookworm-slim
67
+ parallel:
68
+ matrix:
69
+ # Every version the package claims to support in requires-python.
70
+ - PYTHON_VERSION: ["3.12", "3.13"]
71
+ before_script:
72
+ - uv sync --all-extras --all-groups --python "$PYTHON_VERSION"
73
+ script:
74
+ - uv run --python "$PYTHON_VERSION" pytest --cov=src --cov-report=term --cov-report=xml
75
+ coverage: '/^TOTAL.*\s+(\d+%)$/'
76
+ artifacts:
77
+ when: always
78
+ reports:
79
+ coverage_report:
80
+ coverage_format: cobertura
81
+ path: coverage.xml
82
+
83
+ # --------------------------------------------------------------------------
84
+ # publish (release tags only)
85
+ # --------------------------------------------------------------------------
86
+
87
+ # The tag drives the release, so it must agree with the packaged version:
88
+ # publishing v1.2.3 from a tree that says 1.2.2 cannot be undone on PyPI.
89
+ check_version:
90
+ stage: publish
91
+ script:
92
+ - VERSION="$(uv version --short)"
93
+ - |
94
+ if [ "v$VERSION" != "$CI_COMMIT_TAG" ]; then
95
+ echo "Tag $CI_COMMIT_TAG does not match project version v$VERSION."
96
+ echo "Run 'uv version <new>' and retag."
97
+ exit 1
98
+ fi
99
+ - echo "Tag matches version v$VERSION."
100
+ rules:
101
+ - if: $CI_COMMIT_TAG
102
+
103
+ build:
104
+ stage: publish
105
+ needs: ["check_version"]
106
+ # No cache here on purpose: the shared cache restores .uv-cache/ and
107
+ # .pre-commit-cache/ into the project directory, and the sdist would pick
108
+ # them up — cached virtualenvs carry absolute symlinks that fail the build.
109
+ cache: []
110
+ script:
111
+ # --no-sources ignores tool.uv.sources, so the build matches what a user
112
+ # installing from PyPI will actually get.
113
+ - uv build --no-sources
114
+ - ls -l dist/
115
+ artifacts:
116
+ paths:
117
+ - dist/
118
+ expire_in: 1 week
119
+ rules:
120
+ - if: $CI_COMMIT_TAG
121
+
122
+ .publish:
123
+ stage: publish
124
+ needs: ["build"]
125
+ before_script:
126
+ - apt-get update && apt-get install -y --no-install-recommends curl jq
127
+ script:
128
+ # Exchange the GitLab OIDC token for a short-lived PyPI publish token.
129
+ # Never echoed: it would land in the job log in clear text.
130
+ - |
131
+ MINTED="$(curl -sS -X POST "$PYPI_MINT_URL" \
132
+ -H 'Content-Type: application/json' \
133
+ -d "{\"token\":\"${PYPI_ID_TOKEN}\"}" | jq -r '.token // empty')"
134
+ if [ -z "$MINTED" ]; then
135
+ echo "Could not mint a publish token. Is this project registered as a"
136
+ echo "trusted publisher on $PYPI_HOST, with the right branch/tag rules?"
137
+ exit 1
138
+ fi
139
+ export UV_PUBLISH_TOKEN="$MINTED"
140
+ - uv publish --publish-url "$PYPI_PUBLISH_URL" dist/*
141
+
142
+ publish_testpypi:
143
+ extends: .publish
144
+ id_tokens:
145
+ PYPI_ID_TOKEN:
146
+ aud: testpypi
147
+ variables:
148
+ PYPI_HOST: test.pypi.org
149
+ PYPI_MINT_URL: https://test.pypi.org/_/oidc/mint-token
150
+ PYPI_PUBLISH_URL: https://test.pypi.org/legacy/
151
+ environment:
152
+ name: testpypi
153
+ url: https://test.pypi.org/project/dot-inference/
154
+ rules:
155
+ - if: $CI_COMMIT_TAG
156
+
157
+ publish_pypi:
158
+ extends: .publish
159
+ # extends: replaces needs:, it does not merge it — so the template's
160
+ # needs: ["build"] is gone here and dist/ has to be asked for explicitly,
161
+ # or uv publish runs against an empty directory.
162
+ needs:
163
+ - job: build
164
+ artifacts: true
165
+ - job: publish_testpypi
166
+ artifacts: false
167
+ id_tokens:
168
+ PYPI_ID_TOKEN:
169
+ aud: pypi
170
+ variables:
171
+ PYPI_HOST: pypi.org
172
+ PYPI_MINT_URL: https://pypi.org/_/oidc/mint-token
173
+ PYPI_PUBLISH_URL: https://upload.pypi.org/legacy/
174
+ environment:
175
+ name: pypi
176
+ url: https://pypi.org/project/dot-inference/
177
+ rules:
178
+ # Manual on purpose: a PyPI release cannot be taken back, only yanked.
179
+ - if: $CI_COMMIT_TAG
180
+ when: manual
@@ -0,0 +1,34 @@
1
+ # Verbatim legal texts: the AGPL and the DCO both forbid modification,
2
+ # so no hook may normalise their whitespace or line endings.
3
+ exclude: '^(LICENSE\.md|DCO)$'
4
+
5
+ repos:
6
+ - repo: https://github.com/pre-commit/pre-commit-hooks
7
+ rev: v6.0.0
8
+ hooks:
9
+ - id: trailing-whitespace
10
+ - id: end-of-file-fixer
11
+ - id: check-yaml
12
+ - id: check-toml
13
+ - id: check-merge-conflict
14
+ - id: check-case-conflict
15
+ - id: check-added-large-files
16
+ args: ["--maxkb=1000"]
17
+ - id: detect-private-key
18
+ - id: debug-statements
19
+
20
+ - repo: https://github.com/astral-sh/ruff-pre-commit
21
+ rev: v0.16.0
22
+ hooks:
23
+ - id: ruff-check
24
+ args: [--fix]
25
+ - id: ruff-format
26
+
27
+ - repo: local
28
+ hooks:
29
+ - id: ty
30
+ name: ty (type check)
31
+ entry: uv run --frozen ty check
32
+ language: system
33
+ types: [python]
34
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,14 @@
1
+ # Authors
2
+
3
+ Copyright in this project is held by **Kannon For Deep Tech**.
4
+ This file credits the individuals who have contributed to it. Being listed
5
+ here does not confer any ownership of, or rights in, the project.
6
+
7
+ ## Kannon For Deep Tech
8
+
9
+ - Adrien Marjollet
10
+ - Clément Olivier
11
+ - Jean Fechter
12
+ - Louis Le Tarnec
13
+
14
+ ## External contributors
@@ -0,0 +1,67 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.0.2] - 2026-08-27
11
+
12
+ ### Fixed
13
+
14
+ - The `gpt-oss` models (`openai/gpt-oss-20b`, `openai/gpt-oss-120b` and their
15
+ `-local` aliases) are now declared with `supports_reasoning: true`, so
16
+ reasoning deltas are streamed for them instead of being dropped.
17
+ - `publish_pypi` now declares `build` among its `needs:`, so the wheel and
18
+ sdist actually reach the job. `extends:` replaces `needs:` rather than
19
+ merging it, which left the release job publishing an empty directory.
20
+
21
+ ## [2.0.0] - 2026-07-30
22
+
23
+ First public release.
24
+
25
+ ### Added
26
+
27
+ - Unified async interface over multiple LLM providers: OpenAI, Mistral,
28
+ OpenRouter and any OpenAI-compatible local server.
29
+ - Structured outputs backed by Pydantic models.
30
+ - Event streaming: text deltas, reasoning deltas, incremental tool-call
31
+ arguments, assembled tool calls, and usage/cost events.
32
+ - Native tool calling with `tool_choice` control (`auto` / `required` / `none`).
33
+ - Embeddings with automatic batching.
34
+ - Rate limiting through an async sliding window.
35
+ - Cost tracking in tokens and USD.
36
+ - Retry on transient errors, honouring the `Retry-After` header, with
37
+ exponential backoff.
38
+ - YAML model registry carrying pricing and per-model capabilities, extensible
39
+ through `DOTI_CUSTOM_MODELS`.
40
+ - Per-model default provider resolution.
41
+ - Configurable HTTP timeouts.
42
+ - Mock clients for testing without API calls.
43
+ - Settings from environment variables (`DOTI_` prefix) or an env file.
44
+
45
+ ### Security
46
+
47
+ - `ProviderSettings.api_key` is a `SecretStr`: API keys no longer appear in
48
+ `repr()`, `str()`, `model_dump()` or JSON output, so a settings object caught
49
+ in a traceback or an error report cannot leak credentials. Read the value with
50
+ `api_key.get_secret_value()`.
51
+ - An API key set to an empty string is treated as absent, so "is a key
52
+ configured?" checks cannot be fooled by a blank environment variable.
53
+
54
+ ### Changed
55
+
56
+ These matter only if you were installing the package straight from git before
57
+ this release.
58
+
59
+ - `api_key` is now a `SecretStr` rather than a `str`.
60
+ - `LLMCallable` is a `Protocol` rather than a `Callable` alias, which makes
61
+ `response_format` and `tools` genuinely optional at the call site.
62
+ - `LLMCallable` and `EmbeddingCallable` return a `Coroutine` rather than the
63
+ looser `Awaitable`, matching what `asyncio.run_coroutine_threadsafe` accepts.
64
+
65
+ [Unreleased]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/compare/v2.0.2...main
66
+ [2.0.2]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/tags/v2.0.2
67
+ [2.0.0]: https://gitlab.com/deepika6190303/deepika-open-toolbox/dot-inference/-/tags/v2.0.0
@@ -0,0 +1,87 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in this project. Contributions are welcome.
4
+
5
+ This project is maintained by **Kannon For Deep Tech** and released under the
6
+ GNU Affero General Public License v3.0 or later (`AGPL-3.0-or-later`).
7
+
8
+ ## 1. Sign off your commits (DCO)
9
+
10
+ Every commit must carry a `Signed-off-by` line. Add it automatically with:
11
+
12
+ ```
13
+ git commit -s
14
+ ```
15
+
16
+ This appends:
17
+
18
+ ```
19
+ Signed-off-by: Jane Doe <jane@example.com>
20
+ ```
21
+
22
+ The name and email must be your real ones and must match your commit author
23
+ details. By signing off, you certify the [Developer Certificate of Origin](DCO)
24
+ (v1.1) **and** you agree to the licensing terms in section 2 below.
25
+
26
+ Pull requests with unsigned commits will not be merged.
27
+
28
+ ## 2. Licensing of your contribution
29
+
30
+ By contributing to this project, you agree to the following.
31
+
32
+ **2.1 — Outbound licence.** Your contribution is licensed to the public under
33
+ `AGPL-3.0-or-later`, the same terms as the rest of the project.
34
+
35
+ **2.2 — Additional grant to the maintainer.** You additionally grant Kannon For
36
+ Deep Tech a perpetual, worldwide, irrevocable, non-exclusive, royalty-free,
37
+ transferable and sublicensable right to reproduce, modify, adapt, translate,
38
+ publish, distribute and otherwise exploit your contribution, in whole or in
39
+ part, in any form and by any means, on any medium, **under any licensing terms,
40
+ including proprietary and commercial terms**, for the entire duration of the
41
+ applicable copyright protection and worldwide.
42
+
43
+ **2.3 — What this means in practice.** This project is dual-licensed: it is
44
+ available to everyone under the AGPL, and Kannon For Deep Tech also sells
45
+ commercial licences to organisations that cannot comply with the AGPL. Section
46
+ 2.2 is what makes that possible. Without it, no contribution could be included
47
+ in a commercially licensed version.
48
+
49
+ **2.4 — You keep your copyright.** This is a licence grant, not a transfer of
50
+ ownership. You remain the author and copyright holder of your contribution and
51
+ stay free to use and relicense it however you wish, elsewhere.
52
+
53
+ **2.5 — Your warranties.** You confirm that you are entitled to grant the above
54
+ rights, that your contribution is your original work or that you hold the
55
+ necessary rights over it, and that it does not infringe any third-party rights.
56
+ If you are contributing in the course of your employment or under a service
57
+ agreement, you confirm that your employer or client has authorised you to
58
+ contribute under these terms, or has waived any rights that would conflict with
59
+ them.
60
+
61
+ ## 3. Contractors and employees of Kannon For Deep Tech
62
+
63
+ If you are working for Kannon For Deep Tech as an employee or under a service
64
+ agreement, the assignment of rights set out in your contract governs, and takes
65
+ precedence over this file. The sign-off above does not replace it.
66
+
67
+ ## 4. Submitting a change
68
+
69
+ 1. Open an issue first for anything substantial, so we can agree on the approach.
70
+ 2. Fork, branch, and keep commits focused.
71
+ 3. Add or update tests where relevant.
72
+ 4. Add the SPDX headers to any new file:
73
+
74
+ ```
75
+ # SPDX-FileCopyrightText: Kannon For Deep Tech and contributors
76
+ # SPDX-License-Identifier: AGPL-3.0-or-later
77
+ ```
78
+
79
+ Do not modify the copyright lines of existing files. If you would like to be
80
+ credited individually, add yourself to [AUTHORS.md](AUTHORS.md) in the same pull request.
81
+
82
+ 5. Sign off every commit (`git commit -s`) and open a pull request.
83
+
84
+ ## 5. Questions
85
+
86
+ For anything about licensing, including commercial licences, contact
87
+ <louis.letarnec@deepika.ai>.
@@ -0,0 +1,34 @@
1
+ Developer Certificate of Origin
2
+ Version 1.1
3
+
4
+ Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
5
+
6
+ Everyone is permitted to copy and distribute verbatim copies of this
7
+ license document, but changing it is not allowed.
8
+
9
+
10
+ Developer's Certificate of Origin 1.1
11
+
12
+ By making a contribution to this project, I certify that:
13
+
14
+ (a) The contribution was created in whole or in part by me and I
15
+ have the right to submit it under the open source license
16
+ indicated in the file; or
17
+
18
+ (b) The contribution is based upon previous work that, to the best
19
+ of my knowledge, is covered under an appropriate open source
20
+ license and I have the right under that license to submit that
21
+ work with modifications, whether created in whole or in part
22
+ by me, under the same open source license (unless I am
23
+ permitted to submit under a different license), as indicated
24
+ in the file; or
25
+
26
+ (c) The contribution was provided directly to me by some other
27
+ person who certified (a), (b) or (c) and I have not modified
28
+ it.
29
+
30
+ (d) I understand and agree that this project and the contribution
31
+ are public and that a record of the contribution (including all
32
+ personal information I submit with it, including my sign-off) is
33
+ maintained indefinitely and may be redistributed consistent with
34
+ this project or the open source license(s) involved.