diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..023277a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +* +!docker +!fl_server +!fl_server_ai +!fl_server_api +!fl_server_core +!manage.py +!pyproject.toml +!README.md +**/__pycache__ diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1fa5de1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.py] +indent_size = 4 + +[.vscode/*.json] +indent_size = 4 + +[{Dockerfile,Dockerfile.*}] +indent_size = 4 + +[*.md] +indent_size = 4 +max_line_length = off +trim_trailing_whitespace = false + +[*.puml] +insert_final_newline = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..c480d96 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,170 @@ +name: Main + +on: + - push + - pull_request + +jobs: + lint-code: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + cache: 'pip' + - name: Install dependencies + run: bash ./dev install -e ".[all]" + - name: Start static code analysis + run: bash ./dev lint-code + + lint-doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 'lts/hydrogen' + - name: Install dependencies + run: npm install markdownlint-cli2 + - name: Start type checking + run: bash ./dev lint-doc + + lint-scripts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Start shell script analysis tool + run: bash ./dev lint-scripts + + mypy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + cache: 'pip' + - name: Install dependencies + run: bash ./dev install -e ".[all]" + - name: Start type checking + run: bash ./dev mypy + + coverage: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:latest + env: + POSTGRES_USER: demo + POSTGRES_PASSWORD: example + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + redis: + image: redis:latest + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + cache: 'pip' + - name: Install dependencies + run: bash ./dev install -e ".[all]" + - name: Start coverage + env: + FL_POSTGRES_HOST: localhost + FL_POSTGRES_PORT: 5432 + FL_POSTGRES_DBNAME: demo + FL_POSTGRES_USER: demo + FL_POSTGRES_PASSWD: example + FL_REDIS_HOST: localhost + run: bash ./dev coverage + + build-and-push-docker-image: + needs: [lint-code, lint-doc, lint-scripts, mypy, coverage] + permissions: + contents: read + packages: write + env: + REGISTRY: ghcr.io + runs-on: ubuntu-latest + strategy: + matrix: + docker_target: ['celery', 'django'] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.docker_target }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + file: ./docker/${{ matrix.docker_target }}/Dockerfile + context: . + push: ${{ contains(github.ref, 'main') || startsWith(github.ref, 'refs/tags/v') }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + + build-pages: + needs: [lint-code, lint-doc, lint-scripts, mypy, coverage] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.10' + cache: 'pip' + - name: Install dependencies + run: bash ./dev install -e ".[all]" + - name: Build pages + run: bash ./dev doc-build + - name: Fix permissions + run: | + chmod -c -R +rX "site/" | while read line; do + echo "::warning title=Invalid file permissions automatically fixed::$line" + done + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v2 + with: + path: site + + deploy-pages: + if: ${{ contains(github.ref, 'main') || startsWith(github.ref, 'refs/tags/v') }} + needs: [build-pages] + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c76895 --- /dev/null +++ b/.gitignore @@ -0,0 +1,367 @@ +/builds/ +/logs/ +/out/ + +# static file generation (admin and rest_framework) +/static/ +admin.tar.gz +rest_framework.tar.gz + +# ignore nodejs requirements for markdown linting +node_modules +package-lock.json +package.json + + +# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,intellij,windows,linux,python +# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,intellij,windows,linux,python + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,intellij,windows,linux,python + + +!/docker/.env diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..1c93189 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,47 @@ +// Reference: https://github.com/DavidAnson/markdownlint +// Rules: https://github.com/DavidAnson/markdownlint#rules--aliases +// Exception: https://github.com/DavidAnson/markdownlint#configuration +{ + // Enable all markdownlint rules + "default": true, + + // Set unordered list item prefix to dash (use - not * for unordered lists) + "MD004": { "style": "dash" }, + + // Set list indent level to 4 which Python-Markdown requires + "MD007": { "indent": 4 }, + + // Disable line length check + "MD013": false, + //"MD013": { + // "strict": true, + // "line_length": 120, + // "heading_line_length": 80, + // "code_blocks": false + //}, + + // Multiple headings with the same title + "MD024": { "siblings_only": true }, + + // Set Ordered list item prefix to "ordered" (use 1. 2. 3. not 1. 1. 1.) + "MD029": { "style": "ordered" }, + + // Allow inline HTML + "MD033": false, + //"MD033": { "allowed_elements": ["br", "figcaption", "figure"] }, + + // Deny leading and trailing spaces inside code spans like inline code + "MD038": false, + + // Set code block style to fenced (use ``` not indented code blocks) + "MD046": { "style": "fenced" }, + + // Set code block style to backtick (use ``` not ~~~ for code blocks) + "MD048": { "style": "backtick" }, + + // Set emphasis style to underscore (use _text_ not *text* for emphasis) + "MD049": { "style": "underscore" }, + + // Set strong style to asterisk (use **text** not __text__ for strong) + "MD050": { "style": "asterisk" } +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..f11f82a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,9 @@ +repos: + - repo: https://github.com/pycqa/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.3.0 + hooks: + - id: mypy diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7aed78 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,15 @@ +{ + "recommendations": [ + "batisteo.vscode-django", + "davidanson.vscode-markdownlint", + "donjayamanne.python-environment-manager", + "editorconfig.editorconfig", + "kevinglasson.cornflakes-linter", + "matangover.mypy", + "ms-python.flake8", + "ms-python.python", + "pachwenko.django-test-runner", + "streetsidesoftware.code-spell-checker", + "streetsidesoftware.code-spell-checker-scientific-terms" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4583a75 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Serve Documentation", + "type": "python", + "request": "launch", + "module": "mkdocs", + "justMyCode": false, + "args": [ + "serve" + ], + "env": { + "DJANGO_SETTINGS_MODULE": "fl_server.settings.production", + "FL_DJANGO_SECRET_KEY": "", + "FL_POSTGRES_PASSWD": "" + } + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c9856ae --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,50 @@ +{ + "cSpell.allowCompoundWords": true, + "cSpell.language": "en,scientific-terms-us", + "cSpell.words": [ + "corsheaders", + "djangorestframework", + "mypy", + "NOSONAR", + "pdoc", + "probs", + "redoc", + "venv" + ], + "shellcheck.customArgs": [ + "--external-sources", + "--shell", "bash" + ], + "files.associations": { + ".markdownlint.json": "jsonc", + "*.env": "ini", + "pyproject.toml": "ini" + }, + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true, + "**/.mypy_cache/*/**": true, + "**/.venv/*/**": true + }, + "files.exclude": { + ".pytest_cache": true, + ".tox": true, + "*.egg-info": true, + "**/__pycache__": true, + "**/.mypy_cache": true + }, + "mypy.runUsingActiveInterpreter": true, + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "yaml.schemas": { + "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" + }, + "yaml.customTags": [ + "!ENV scalar", + "!ENV sequence", + "!relative scalar", + "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", + "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", + "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..32c8f89 --- /dev/null +++ b/README.md @@ -0,0 +1,135 @@ +# Federated Learning Demonstrator + +This repository contains the Federated Learning Demonstrator, a comprehensive suite of tools designed for machine learning applications in a Federated context. +This server component that handles the orchestration and notification of all training participants and ensuring smooth and efficient operation. + +The demonstrator further provides capabilities for diverse model aggregation methods, merging the model inputs from each participant. +It also offers model inference, enabling the generation of predictions using the trained models. +The repository also includes utilities for quantifying uncertainty, which provide a measure of the reliability of the model's predictions. + +This project is the server component of the Federated Learning (FL) platform, serving as a proof of concept for the [Catena-X](https://catena-x.net/en) project. +The FL platform aims to demonstrate the potential of federated learning in a practical, real-world context. + +For a comprehensive understanding of the FL platform, please refer to the official [FL platform documentation](https://dlr-ki.github.io/fl-documentation). + +A complete list of all repositories relevant to the FL platform can be found [here](https://dlr-ki.github.io/fl-documentation#repositories). + +## Get Started + +This README.md is primarily intended for developers and contributors, providing necessary information for setup, installation, and contribution guidelines. +If you're interested in using or testing this project, we recommend starting with the [GitHub pages](https://dlr-ki.github.io/fl-demonstrator). +They offer a more user-friendly interface and comprehensive guides to get you started. + +## Requirements + +### Python > 3.10 + +```bash +sudo apt install python +#If not available you can add latest versions with +sudo add-apt-repository ppa:deadsnakes/ppa +``` + +### Venv + +```bash +#Install venv +sudo apt install python-venv +``` + +### Virtualenv (alternative to venv) + +```bash +#python 3.10 or later +which python +#virtualenv or venv +pip install -U virtualenv +``` + +## Install + +```bash +# create virtual environment +virtualenv -p $(which python) .venv +# or +python -m venv .venv + +# activate our virtual environment +source .venv/bin/activate + +# update pip (optional) +python -m pip install -U pip + +# install +./dev install -U -e ".[all]" +``` + +## Helpers + +```txt +$ ./dev --help +usage: ./dev [options] + +positional arguments: + {celery,clean,collectstatic,coverage,coverage-report,db-reset,doc,doc-build,docker-build,help,install,licenses,licenses-check,lint,lint-code,lint-doc,lint-scripts,makemigrations,manage,migrate,mypy,safety-check,start,superuser,test,version,versions} + Available sub commands + help Show this help message and exit + start Run the application + celery Run celery worker + migrate Run database migrations + makemigrations Create new database migrations + manage Run django manage.py + superuser Create superuser + collectstatic Collect static files + db-reset Reset database + docker-build Build docker images for local development + test Run all tests + lint Run all linter + lint-code Run code linter + lint-doc Run documentation linter + lint-scripts Run bash script linter + mypy Run type checker + coverage Run unit tests + coverage-report Generate test coverage report + doc Start documentation server + doc-build Build documentation + licenses Generate licenses + licenses-check Check licenses + safety-check Check dependencies for known security vulnerabilities + install Install package + clean Clean up local files + version Show package version + versions Show versions + +options: + --no-http-serve Do not serve the action result via HTTP +``` + +## Contribution + +- Type-Save and linting with mypy+flake8 +- Scripts and examples for linux, wsl (bash) + +### Documentation + +This projects is using the Docstring style from +[Google](https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings). +At least public classes, methods, fields, ... should be documented. + +```python +""" +This is the single line short description. + +This is the multiline or long description. +Note, that the whole Docstring support markdown styling. + +The long description can also contains multiple paragraphs. + +Args: + log_filepath (str): Log file path. + ensure_log_dir (bool, optional): Create directory for the log file if not exists. Defaults to True. + +Returns: + Dict[str, Any]: logging configuration dict +""" +``` diff --git a/dev b/dev new file mode 100755 index 0000000..7c5345d --- /dev/null +++ b/dev @@ -0,0 +1,365 @@ +#!/bin/bash +############################################################################### +# Helper commands # +################### +# This script contains a few little helper commands to make development easier. +############################################################################### +set -e +set -o pipefail + +# imports +source "$(dirname "${BASH_SOURCE[0]}")/scripts/utils.sh" + +# global variables +PROJECT_ROOT="." +PROJECT_ROOT_ABSOLUTE="$(realpath ${PROJECT_ROOT})" +BUILD_ROOT="${PROJECT_ROOT}/build" +DOC_ROOT="${PROJECT_ROOT}/docs" + +SOURCE_DJANGO="${PROJECT_ROOT}/fl_server" +SOURCE_AI="${PROJECT_ROOT}/fl_server_ai" +SOURCE_API="${PROJECT_ROOT}/fl_server_api" +SOURCE_CORE="${PROJECT_ROOT}/fl_server_core" +SCRIPTS_ROOT="${PROJECT_ROOT}/scripts" + +# default values of arguments +HTTP_SERVE=true + +# parse arguments +action=${1,,}; shift +[ "$action" == "--help" ] || [ "$action" == "-h" ] && action=help +while [[ $# -gt 0 ]]; do + case $1 in + --no-http-serve) HTTP_SERVE=false; shift ;; + --help|-h) action=help; shift ;; + --version) action=version; shift ;; + --) shift; break ;; + *) + # warn "Unknown argument: '$1'; Skip further parsing."; + break ;; + esac +done + + +no_actions="$(compgen -A function)" +############################################################################### +# action functions + +function help() { + actions="$(actions="$(printf '%s,' "${action_map[@]}")"; echo "{${actions%,}}")" + [ ${#actions} -lt 22 ] && actions=$(printf '%-22s' "$actions") || actions="$actions\n$(printf %24s "")" + info2 "usage: $0 [options]" + info2 "" + info2 "positional arguments:" + info2 -e " ${actions}Available sub commands" + info2 " help Show this help message and exit" + info2 " start Run the application" + info2 " celery Run celery worker" + info2 " migrate Run database migrations" + info2 " makemigrations Create new database migrations" + info2 " manage Run django manage.py" + info2 " superuser Create superuser" + info2 " collectstatic Collect static files" + info2 " db-reset Reset database" + info2 " docker-build Build docker images for local development" + info2 " test Run all tests" + info2 " lint Run all linter" + info2 " lint-code Run code linter" + info2 " lint-doc Run documentation linter" + info2 " lint-scripts Run bash script linter" + info2 " mypy Run type checker" + info2 " coverage Run unit tests" + info2 " coverage-report Generate test coverage report" + info2 " doc Start documentation server" + info2 " doc-build Build documentation" + info2 " licenses Generate licenses" + info2 " licenses-check Check licenses" + info2 " safety-check Check dependencies for known security vulnerabilities" + info2 " install Install package" + info2 " clean Clean up local files" + info2 " version Show package version" + info2 " versions Show versions" + info2 "" + info2 "options:" + info2 " --no-http-serve Do not serve the action result via HTTP" +} + +function version() { + awk -F "=" '/version/ {print $2}' "${PROJECT_ROOT}/pyproject.toml" | awk -F'"' '{print $2}' | awk NF | head -n 1 +} + +function versions() { + info "versions" + info "$(python --version)" + info "$(python -m pip --version)" + if ! command -v docker > /dev/null 2>&1; then + warn "docker not found, skipping docker version" + else + info "$(docker --version)" + info "$(docker compose version)" + fi + info -n "package version: " + version +} + +function install() { + versions + info "install package" + if [ "$#" -eq "0" ]; then + python -m pip install -e . + else + python -m pip install "$@" + + # check if "doc" extra should be installed + install_doc=false + for value in "$@"; do + value="${value//[[:blank:]]/}" + [[ "$value" =~ \[(.*,)?(doc|all)(,.*)?\] ]] && install_doc=true + done + if [[ "$install_doc" == "true" ]]; then + info "install markdown linter" + if command -v npm > /dev/null 2>&1; then + npm install --no-save markdownlint-cli2 + else + warn "npm not found, skipping markdownlint-cli2 installation" + fi + fi + fi + #info "post-install" + #py_pack_dir="$(python -c 'import site; print(site.getsitepackages()[0])')" + #info " + setup user documentation plugins" + #cp "$py_pack_dir/plantuml_markdown.py" "$py_pack_dir/markdown/extensions/" +} + +function clean() { + info "remove __pycache__|.pyc|.pyo" + find "${PROJECT_ROOT}" | grep -E "(__pycache__|\.pyc$$|\.pyo$$)" | xargs rm -rf + info "remove builds" + rm -rf "${BUILD_ROOT}" + rm -rf "${PROJECT_ROOT}/site" + info "remove egg-info" + rm -rf "${PROJECT_ROOT}/*.egg-info" + info "remove tox" + rm -rf "${PROJECT_ROOT}/.tox" + info "remove pytest cache" + rm -rf "${PROJECT_ROOT}/.pytest_cache" + info "remove mypy cache" + rm -rf "${PROJECT_ROOT}/.mypy_cache" +} + +function start() { + docker compose up -d db redis + migrate + python manage.py runserver +} + +function celery() { + docker compose up -d redis + DJANGO_SETTINGS_MODULE="${DJANGO_SETTINGS_MODULE:-"fl_server.settings.development"}" \ + python -m celery --workdir "${PROJECT_ROOT_ABSOLUTE}" --app fl_server_ai worker --loglevel=INFO +} + +function migrate() { + python manage.py migrate + python manage.py check +} + +function makemigrations() { + python manage.py makemigrations fl_server_core +} + +function manage() { + python manage.py "$@" +} + +function superuser() { + DJANGO_SUPERUSER_PASSWORD="${DJANGO_SUPERUSER_PASSWORD:-"password"}" \ + python manage.py createsuperuser --username admin --email "admin@example.com" --no-input +} + +function collectstatic() { + versions + info "$(tar --version | head -n 1)" + info "collect static files" + rm -rf static + rm -rf "${BUILD_ROOT}/static" + FL_DJANGO_SECRET_KEY="${FL_DJANGO_SECRET_KEY:-}" FL_POSTGRES_PASSWD="${FL_POSTGRES_PASSWD:-}" \ + python manage.py collectstatic --settings "fl_server.settings.production" + info "compressing static files" + mkdir -p "${BUILD_ROOT}/static" + info " | create admin.tar.gz" + tar -czf "${BUILD_ROOT}/static/admin.tar.gz" -C static admin + info " | create rest_framework.tar.gz" + tar -czf "${BUILD_ROOT}/static/rest_framework.tar.gz" -C static rest_framework + info "clean up" + rm -rf static +} + +function db-reset() { + if docker ps --format "table {{.Names}}" | grep -q -e "db"; then + info "Destroy db container including its volumes and restart it" + docker compose rm -fsv db + docker compose up -d db + info "Clear redis cache" + docker exec -it redis redis-cli FLUSHALL + sleep 2 + $(MAKE) --no-print-directory migration + else + warn "Remove all unused anonymous volumes" + docker volume prune -f + fi +} + +function docker-build() { + versions + info "build docker images for local development" + project_name="$(awk -F "=" '/name/ {print $2}' "${PROJECT_ROOT}/pyproject.toml" | awk -F'"' '{print $2}' | awk NF | head -n 1)" + celery_image_name="local/${project_name}-celery:latest" + django_image_name="local/${project_name}-django:latest" + info "build docker image: ${django_image_name}" + docker build -f ./docker/celery/Dockerfile -t "${celery_image_name}" . "$@" + info "build docker image: ${django_image_name}" + docker build -f ./docker/django/Dockerfile -t "${django_image_name}" . "$@" +} + +function test() { + versions + info "run all tests" + lint + mypy + coverage + coverage-report + if [ "${HTTP_SERVE}" = "true" ]; then + if [ -d "${BUILD_ROOT}/htmlcov" ]; then + python -m http.server --directory "${BUILD_ROOT}/htmlcov" 8080 + else + error "no coverage report found" + exit 1 + fi + fi +} + +function lint() { + versions + info "linting" + lint-code + lint-doc + lint-scripts +} + +function lint-code() { + info "lint code" + info "flake8 version: $(python -m flake8 --version | xargs)" + python -m flake8 "${SOURCE_CORE}" + python -m flake8 "${SOURCE_API}" + python -m flake8 "${SOURCE_AI}" + python -m flake8 "${SOURCE_DJANGO}" + python -m flake8 "${SCRIPTS_ROOT}" +} + +function lint-doc() { + info "lint documentation" + # use markdownlint from David Anson (based on nodejs) + # https://github.com/DavidAnson/markdownlint + npm exec markdownlint-cli2 "${DOC_ROOT}/**/*.md" "${PROJECT_ROOT}/README.md" +} + +function lint-scripts() { + info "lint bash scripts" + info "shellcheck $(shellcheck --version | head -n 2 | tail -n 1)" + shellcheck --external-sources --shell bash --source-path "${PROJECT_ROOT}" "${PROJECT_ROOT}/dev" + shellcheck --external-sources --shell bash --source-path "${SCRIPTS_ROOT}" "${SCRIPTS_ROOT}/"*.sh +} + +function mypy() { + info "type checking" + python -m mypy "${SOURCE_CORE}" + python -m mypy "${SOURCE_API}" + python -m mypy "${SOURCE_AI}" + python -m mypy "${SOURCE_DJANGO}" + if find "${SCRIPTS_ROOT}" -type f -name "*.py" | grep -q .; then + python -m mypy "${SCRIPTS_ROOT}" + fi +} + +function coverage() { + info "run python tests with coverage" + python -m coverage run manage.py test + python -m coverage html --directory "${BUILD_ROOT}/htmlcov" +} + +function coverage-report() { + info "print test coverage report" + python -m coverage report +} + +function doc() { + versions + info + mkdocs_version="$(python -m mkdocs --version)" + info "${mkdocs_version#"python -m "}" + # check if the user has passed the --dirtyreload flag + dirty_flag=false + for value in "$@"; do + [[ "--dirty" = "$value" ]] && dirty_flag=true + done + if [[ "$dirty_flag" == "false" ]]; then + warn "consider using --dirty to reload only file changes instead of the" + warn "whole project. This can lead to a significant speed up during the" + warn "documentation development." + fi + # create and serve documentation + DJANGO_SETTINGS_MODULE="${DJANGO_SETTINGS_MODULE:-"fl_server.settings.production"}" \ + FL_DJANGO_SECRET_KEY="${FL_DJANGO_SECRET_KEY:-}" FL_POSTGRES_PASSWD="${FL_POSTGRES_PASSWD:-}" \ + python -m mkdocs serve "$@" +} + +function doc-build() { + versions + mkdocs_version="$(python -m mkdocs --version)" + info "${mkdocs_version#"python -m "}" + info "build documentation" + DJANGO_SETTINGS_MODULE="${DJANGO_SETTINGS_MODULE:-"fl_server.settings.production"}" \ + FL_DJANGO_SECRET_KEY="${FL_DJANGO_SECRET_KEY:-}" FL_POSTGRES_PASSWD="${FL_POSTGRES_PASSWD:-}" \ + python -m mkdocs build "$@" +} + +function licenses() { + info "generate licenses" + # create a tox environment and pull in license information + license_dir="${PROJECT_ROOT}/licenses" + mkdir -p "${license_dir}" + python -m tox --recreate -e licenses +} + +function licenses-check() { + info "search for license conflicts" + licensecheck + info "search for license changes" + git --no-pager diff --exit-code "${PROJECT_ROOT}/licenses/license_info.no_versions.csv" +} + +function safety-check() { + info "check dependencies for known security vulnerabilities" + # main only no dev dependencies etc. + python -m tox --recreate -e safety + # alternative + #python -m pip install -U safety + #safety check + ##python -m pip uninstall safety +} + + +# create array with all action functions (above) +readarray -t action_map <<< "$(comm -3 <(compgen -A function) <(echo "$no_actions"))" +############################################################################### +# run action + +if ! printf '%s\n' "${action_map[@]}" | grep -x -q -- "$action"; then + echo "Invalid action : $action" + echo "Allowed actions: ${action_map[*]}" + echo "Use --help for more information" + exit 1 +fi + +$action "$@" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2b51cb8 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,53 @@ +version: '3.7' + +services: + web: + image: ghcr.io/dlr-ki/fl-demonstrator:main + container_name: web + restart: always + build: + context: . + dockerfile: ./docker/django/Dockerfile + ports: + - 8000:8000 + depends_on: + - db + - redis + env_file: + - docker/.env + + celery: + image: ghcr.io/dlr-ki/fl-demonstrator-celery:main + container_name: celery + restart: always + build: + context: . + dockerfile: ./docker/celery/Dockerfile + depends_on: + - redis + env_file: + - docker/.env + + redis: + image: redis + container_name: redis + restart: always + ports: + - "6379:6379" # port mapping only for development + + db: + image: postgres + container_name: db + restart: always + ports: + - "5432:5432" # port mapping only for development + environment: + POSTGRES_USER: demo + POSTGRES_PASSWORD: example + + # adminer: + # image: adminer + # container_name: adminer + # restart: always + # ports: + # - 8080:8080 diff --git a/docker/.env b/docker/.env new file mode 100644 index 0000000..a9bc4a8 --- /dev/null +++ b/docker/.env @@ -0,0 +1,9 @@ +FL_POSTGRES_HOST=db +FL_POSTGRES_PORT=5432 +FL_POSTGRES_DBNAME=demo +FL_POSTGRES_USER=demo +FL_POSTGRES_PASSWD=example +FL_REDIS_HOST=redis +# TODO: user docker secret with FL_DJANGO_SECRET_KEY_FILE +FL_DJANGO_SECRET_KEY=django-insecure-*z=iw5n%b--qdim+x5b+j9=^_gq7hq)kk8@7$^(tyn@oc#_8by +FL_DJANGO_ALLOWED_HOSTS=* diff --git a/docker/celery/Dockerfile b/docker/celery/Dockerfile new file mode 100644 index 0000000..2aca594 --- /dev/null +++ b/docker/celery/Dockerfile @@ -0,0 +1,39 @@ +FROM python:3.10-slim + +# system dependencies +RUN apt-get update && \ + apt-get install -y \ + # psycopg2 dependencies + libpq-dev \ + # translations + gettext \ + # git dependencies + git \ + && \ + rm -rf /var/lib/apt/lists/* + +# add user: celery +RUN useradd -ms /bin/bash celery +USER celery +WORKDIR /home/celery/app + +# install dependencies +COPY --chown=celery:celery pyproject.toml README.md /home/celery/app/ +RUN mkdir fl_server fl_server_ai fl_server_api fl_server_core && \ + pip install --no-warn-script-location --extra-index-url https://download.pytorch.org/whl/cpu . && \ + rm -rf fl_server fl_server_ai fl_server_api fl_server_core pyproject.toml README.md + +# copy scripts +COPY --chown=celery:celery ./docker/celery/docker-start.sh /home/celery/app/docker-start.sh + +# copy fl_server +COPY --chown=celery:celery ./manage.py /home/celery/app/manage.py +COPY --chown=celery:celery ./fl_server /home/celery/app/fl_server +COPY --chown=celery:celery ./fl_server_core /home/celery/app/fl_server_core +COPY --chown=celery:celery ./fl_server_api /home/celery/app/fl_server_api +COPY --chown=celery:celery ./fl_server_ai /home/celery/app/fl_server_ai + +ENV DJANGO_SETTINGS_MODULE=fl_server.settings.production +VOLUME [ "./logs" ] +CMD ["./docker-start.sh"] +STOPSIGNAL SIGINT diff --git a/docker/celery/docker-start.sh b/docker/celery/docker-start.sh new file mode 100755 index 0000000..5d8bb66 --- /dev/null +++ b/docker/celery/docker-start.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +python -m celery \ + --workdir . \ + --app fl_server_ai \ + worker \ + --loglevel "${CELERY_LOG_LEVEL:-INFO}" diff --git a/docker/django/Dockerfile b/docker/django/Dockerfile new file mode 100644 index 0000000..5beed8e --- /dev/null +++ b/docker/django/Dockerfile @@ -0,0 +1,40 @@ +FROM python:3.10-slim + +# system dependencies +RUN apt-get update && \ + apt-get install -y \ + # psycopg2 dependencies + libpq-dev \ + # translations + gettext \ + # git dependencies + git \ + && \ + rm -rf /var/lib/apt/lists/* + +# add user: django +RUN useradd -ms /bin/bash django +USER django +WORKDIR /home/django/app + +# install dependencies +COPY --chown=django:django pyproject.toml README.md /home/django/app/ +RUN mkdir fl_server fl_server_ai fl_server_api fl_server_core && \ + pip install --no-warn-script-location --extra-index-url https://download.pytorch.org/whl/cpu . && \ + rm -rf fl_server fl_server_ai fl_server_api fl_server_core pyproject.toml README.md + +# copy scripts +COPY --chown=django:django ./docker/django/docker-start.sh /home/django/app/docker-start.sh + +# copy fl_server +COPY --chown=django:django ./manage.py /home/django/app/manage.py +COPY --chown=django:django ./fl_server /home/django/app/fl_server +COPY --chown=django:django ./fl_server_core /home/django/app/fl_server_core +COPY --chown=django:django ./fl_server_api /home/django/app/fl_server_api +COPY --chown=django:django ./fl_server_ai /home/django/app/fl_server_ai + +ENV DJANGO_SETTINGS_MODULE=fl_server.settings.production +EXPOSE 8000 +VOLUME [ "./logs" ] +CMD ["./docker-start.sh"] +STOPSIGNAL SIGINT diff --git a/docker/django/docker-start.sh b/docker/django/docker-start.sh new file mode 100755 index 0000000..02805b3 --- /dev/null +++ b/docker/django/docker-start.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# migration +python manage.py migrate + +# TODO: collect static files +#python manage.py collectstatic --no-input --no-post-process + +# run DLR FL demonstrator server +# NOTE: set insecure otherwise static file will not be served +# TODO: remove insecure flag +python manage.py runserver 0.0.0.0:8000 --insecure diff --git a/docs/.overrides/.icons/dlr-ki.svg b/docs/.overrides/.icons/dlr-ki.svg new file mode 100644 index 0000000..758ea06 --- /dev/null +++ b/docs/.overrides/.icons/dlr-ki.svg @@ -0,0 +1,217 @@ + + + + + + + + + + diff --git a/docs/.overrides/.icons/dlr-logo.svg b/docs/.overrides/.icons/dlr-logo.svg new file mode 100644 index 0000000..b17447d --- /dev/null +++ b/docs/.overrides/.icons/dlr-logo.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/docs/Fl Platform.postman_collection.json b/docs/Fl Platform.postman_collection.json new file mode 100644 index 0000000..540e1c6 --- /dev/null +++ b/docs/Fl Platform.postman_collection.json @@ -0,0 +1,947 @@ +{ + "info": { + "_postman_id": "a26cce21-d9a3-4b13-abc9-6f06a8ae6d1b", + "name": "Fl Platform", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "20639678" + }, + "item": [ + { + "name": "Create User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();\r", + "pm.collectionVariables.set(\"USER_ID\", jsonData[\"id\"]);\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"username\": \"testuser\",\r\n \"password\": \"password\",\r\n \"first_name\": \"John\",\r\n \"last_name\": \"Catena\",\r\n \"email\": \"john-doe@example.com\",\r\n \"message_endpoint\": \"https://example.com\",\r\n \"client\": true,\r\n \"actor\": true\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BASE_URL}}/users/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "users", + "" + ] + } + }, + "response": [] + }, + { + "name": "Create Second User", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();\r", + "pm.collectionVariables.set(\"USER_ID_2\", jsonData[\"id\"]);\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"username\": \"testuser2\",\r\n \"password\": \"password\",\r\n \"first_name\": \"Johnanna\",\r\n \"last_name\": \"Catena\",\r\n \"email\": \"jc@example.com\",\r\n \"message_endpoint\": \"https://example.com\",\r\n \"client\": true,\r\n \"actor\": false\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BASE_URL}}/users/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "users", + "" + ] + } + }, + "response": [] + }, + { + "name": "[MARKED FOR DELETE] List User Groups", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/users/groups/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "users", + "groups", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get User Data", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/users/{{USER_ID}}", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "users", + "{{USER_ID}}" + ] + } + }, + "response": [] + }, + { + "name": "Upload Model", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();\r", + "pm.collectionVariables.set(\"MODEL_ID\", jsonData[\"model_id\"]);\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "model_file", + "type": "file", + "src": "/C:/Users/fran_bi/Downloads/test_model.pt" + }, + { + "key": "name", + "value": "my_test_model", + "type": "text" + }, + { + "key": "description", + "value": "A test model for postman", + "type": "text" + } + ] + }, + "url": { + "raw": "{{BASE_URL}}/models/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "models", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Models", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/models/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "models", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Model Metadata", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "model.pkl", + "value": "", + "type": "text", + "disabled": true + } + ] + }, + "url": { + "raw": "{{BASE_URL}}/models/{{MODEL_ID}}/metadata/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "models", + "{{MODEL_ID}}", + "metadata", + "" + ] + } + }, + "response": [] + }, + { + "name": "Download Model", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/models/{{MODEL_ID}}/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "models", + "{{MODEL_ID}}", + "" + ] + } + }, + "response": [] + }, + { + "name": "Create Training", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "var jsonData = pm.response.json();\r", + "pm.collectionVariables.set(\"TRAINING_ID\", jsonData[\"training_id\"]);\r", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"model_id\": \"{{MODEL_ID}}\",\r\n \"target_num_updates\": 1,\r\n \"metric_names\": [\"accuracy\"],\r\n \"aggregation_method\": \"FedAvg\",\r\n \"clients\": [\"{{USER_ID}}\"]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BASE_URL}}/trainings/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "trainings", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Trainings", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/trainings/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "trainings", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Training By ID", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/trainings/{{TRAINING_ID}}", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "trainings", + "{{TRAINING_ID}}" + ] + } + }, + "response": [] + }, + { + "name": "List User Trainings", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/users/trainings/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "users", + "trainings", + "" + ] + } + }, + "response": [] + }, + { + "name": "Add Client To Training", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"clients\": [\"{{USER_ID_2}}\"]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BASE_URL}}/trainings/{{TRAINING_ID}}/clients/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "trainings", + "{{TRAINING_ID}}", + "clients", + "" + ] + } + }, + "response": [] + }, + { + "name": "Remove Client From Training", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"clients\": [\"{{USER_ID_2}}\"]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BASE_URL}}/trainings/{{TRAINING_ID}}/clients/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "trainings", + "{{TRAINING_ID}}", + "clients", + "" + ] + } + }, + "response": [] + }, + { + "name": "Start Training", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "disabled": true + } + ], + "url": { + "raw": "{{BASE_URL}}/trainings/{{TRAINING_ID}}/start/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "trainings", + "{{TRAINING_ID}}", + "start", + "" + ] + } + }, + "response": [] + }, + { + "name": "Upload Model Update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "model_file", + "type": "file", + "src": "/C:/Users/fran_bi/Downloads/test_model.pt" + }, + { + "key": "round", + "value": "0", + "type": "text" + }, + { + "key": "sample_size", + "value": "2000000", + "type": "text" + } + ] + }, + "url": { + "raw": "{{BASE_URL}}/models/{{MODEL_ID}}/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "models", + "{{MODEL_ID}}", + "" + ] + } + }, + "response": [] + }, + { + "name": "Upload Model Metrics", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "metric_names", + "value": "accuracy", + "type": "text" + }, + { + "key": "metric_values", + "value": "0.96", + "type": "text" + }, + { + "key": "sample_size", + "value": "2000000", + "type": "text", + "disabled": true + } + ] + }, + "url": { + "raw": "{{BASE_URL}}/models/{{MODEL_ID}}/metrics/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "models", + "{{MODEL_ID}}", + "metrics", + "" + ] + } + }, + "response": [] + }, + { + "name": "Get Model Metrics", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{BASE_URL}}/models/{{MODEL_ID}}/metrics/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "models", + "{{MODEL_ID}}", + "metrics", + "" + ] + } + }, + "response": [] + }, + { + "name": "Model Inference JSON", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"model_id\": \"{{MODEL_ID}}\",\r\n \"model_input\": [[1.0, 1.0, 1.0, 0.0, 1.0, 5.0, 1.0, 1.0, 7.0, 10.0]]\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{BASE_URL}}/inference/", + "host": [ + "{{BASE_URL}}" + ], + "path": [ + "inference", + "" + ] + } + }, + "response": [] + } + ], + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "password", + "type": "string" + }, + { + "key": "username", + "value": "testuser", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "BASE_URL", + "value": "http://127.0.0.1:8000/api", + "type": "string" + }, + { + "key": "USER_ID", + "value": "" + }, + { + "key": "MODEL_ID", + "value": "" + }, + { + "key": "TRAINING_ID", + "value": "" + }, + { + "key": "USER_ID_2", + "value": "" + } + ] +} \ No newline at end of file diff --git a/docs/ai-ecosystem/FL-demonstrator.drawio.png b/docs/ai-ecosystem/FL-demonstrator.drawio.png new file mode 100644 index 0000000..5634c89 Binary files /dev/null and b/docs/ai-ecosystem/FL-demonstrator.drawio.png differ diff --git a/docs/ai-ecosystem/ecosystem.drawio.png b/docs/ai-ecosystem/ecosystem.drawio.png new file mode 100644 index 0000000..1e4db67 Binary files /dev/null and b/docs/ai-ecosystem/ecosystem.drawio.png differ diff --git a/docs/ai-ecosystem/ideal-data.drawio.png b/docs/ai-ecosystem/ideal-data.drawio.png new file mode 100644 index 0000000..9a4f773 Binary files /dev/null and b/docs/ai-ecosystem/ideal-data.drawio.png differ diff --git a/docs/ai-ecosystem/ideal-services.drawio.png b/docs/ai-ecosystem/ideal-services.drawio.png new file mode 100644 index 0000000..93d2d5c Binary files /dev/null and b/docs/ai-ecosystem/ideal-services.drawio.png differ diff --git a/docs/arc42/quality-model.drawio.png b/docs/arc42/quality-model.drawio.png new file mode 100644 index 0000000..cdde331 Binary files /dev/null and b/docs/arc42/quality-model.drawio.png differ diff --git a/docs/gitlab-runner/check.png b/docs/gitlab-runner/check.png new file mode 100644 index 0000000..768a319 Binary files /dev/null and b/docs/gitlab-runner/check.png differ diff --git a/docs/gitlab-runner/register.png b/docs/gitlab-runner/register.png new file mode 100644 index 0000000..c528cf0 Binary files /dev/null and b/docs/gitlab-runner/register.png differ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..41490e5 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,76 @@ +--- +title: Home +hide: navigation +--- + + +# Federated Learning Demonstrator + +This repository contains the Federated Learning Demonstrator, a comprehensive suite of tools designed for machine learning applications in a Federated context. +This server component that handles the orchestration and notification of all training participants and ensuring smooth and efficient operation. + +The demonstrator further provides capabilities for diverse model aggregation methods, merging the model inputs from each participant. +It also offers model inference, enabling the generation of predictions using the trained models. +The repository also includes utilities for quantifying uncertainty, which provide a measure of the reliability of the model's predictions. + +This project is the server component of the Federated Learning (FL) platform, serving as a proof of concept for the [Catena-X](https://catena-x.net/en) project. +The FL platform aims to demonstrate the potential of federated learning in a practical, real-world context. + +For a comprehensive understanding of the FL platform, please refer to the official [FL platform documentation](https://dlr-ki.github.io/fl-documentation). + +A complete list of all repositories relevant to the FL platform can be found [here](https://dlr-ki.github.io/fl-documentation#repositories). + +## Quick Start + +Along with the general [FL platform documentation](https://dlr-ki.github.io/fl-documentation), there also exists a [tutorial](https://dlr-ki.github.io/fl-documentation/tutorial) in which all components are explained using a simple example. + +The simplest way to get the demonstrator up running is to use Docker in combination with Docker Compose. + +```yaml title="docker-compose.yml" +version: '3.7' + +services: + web: + image: ghcr.io/dlr-ki/fl-demonstrator:main + container_name: web + restart: always + ports: + - 8000:8000 + depends_on: + - db + - redis + environment: + FL_DJANGO_SECRET_KEY: django-insecure-*z=iw5n%b--qdim+x5b+j9=^_gq7hq)kk8@7$^(tyn@oc#_8by + FL_DJANGO_ALLOWED_HOSTS: '*' + FL_POSTGRES_HOST: db + FL_POSTGRES_PORT: 5432 + FL_POSTGRES_DBNAME: demo + FL_POSTGRES_USER: demo + FL_POSTGRES_PASSWD: example + FL_REDIS_HOST: redis + + celery: + image: ghcr.io/dlr-ki/fl-demonstrator-celery:main + container_name: celery + restart: always + depends_on: + - redis + environment: + FL_REDIS_HOST: redis + + redis: + image: redis + container_name: redis + restart: always + + db: + image: postgres + container_name: db + restart: always + environment: + POSTGRES_USER: demo + POSTGRES_PASSWORD: example +``` + +After successfully starting all necessary server components with `docker compose up -d` you are ready to go. +A fitting start would be the API documentation: . diff --git a/docs/javascripts/katex.js b/docs/javascripts/katex.js new file mode 100644 index 0000000..f7fd704 --- /dev/null +++ b/docs/javascripts/katex.js @@ -0,0 +1,10 @@ +document$.subscribe(({ body }) => { + renderMathInElement(body, { + delimiters: [ + { left: "$$", right: "$$", display: true }, + { left: "$", right: "$", display: false }, + { left: "\\(", right: "\\)", display: false }, + { left: "\\[", right: "\\]", display: true } + ], + }) +}) diff --git a/docs/styles/style.css b/docs/styles/style.css new file mode 100644 index 0000000..a03ca4f --- /dev/null +++ b/docs/styles/style.css @@ -0,0 +1,3 @@ +.md-content { + text-align: justify; +} diff --git a/docs/web-service/BuildingBlock.drawio.png b/docs/web-service/BuildingBlock.drawio.png new file mode 100644 index 0000000..328c70d Binary files /dev/null and b/docs/web-service/BuildingBlock.drawio.png differ diff --git a/docs/web-service/RuL-Interaction.drawio.png b/docs/web-service/RuL-Interaction.drawio.png new file mode 100644 index 0000000..5cec138 Binary files /dev/null and b/docs/web-service/RuL-Interaction.drawio.png differ diff --git a/docs/web-service/model-enums.png b/docs/web-service/model-enums.png new file mode 100644 index 0000000..f4b92a3 Binary files /dev/null and b/docs/web-service/model-enums.png differ diff --git a/docs/web-service/model-enums.puml b/docs/web-service/model-enums.puml new file mode 100644 index 0000000..ccf47f6 --- /dev/null +++ b/docs/web-service/model-enums.puml @@ -0,0 +1,24 @@ +@startuml Model Enums +!theme plain +hide enum methods + +enum TrainingState { + I + O + C + E + S +} +enum AggregationMethod { + FedAvg + FedDC + FedProx +} +enum UncertaintyMethod { + NONE + ENSEMBLE_LOCAL + ENSEMBLE_GLOBAL + MC_DROPOUT + SWAG +} +@enduml \ No newline at end of file diff --git a/docs/web-service/models.png b/docs/web-service/models.png new file mode 100644 index 0000000..d865c49 Binary files /dev/null and b/docs/web-service/models.png differ diff --git a/docs/web-service/models.puml b/docs/web-service/models.puml new file mode 100644 index 0000000..ca60c8f --- /dev/null +++ b/docs/web-service/models.puml @@ -0,0 +1,71 @@ +@startuml Models +!theme plain + +object NotificationReceiver { + id: UUID + message_endpoint: URL +} +object User { + username: Varchar(150) + first_name: Varchar(150) + last_name: Varchar(150) + email: Email + actor: Boolean + client: Boolean +} +object Token { + key: Varchar(40) + created: DateTime +} +object Model { + id: UUID + round: Int + weights: Binary +} +object GlobalModel { + name: Varchar(256) + description: Text +} +object SWAGModel { + swag_first_moment: Binary + swag_second_moment: Binary +} +object MeanModel +object LocalModel { + sample_size: Int +} +object Training { + id: UUID + state: TrainingState + target_num_updates: Int + last_update: DateTime + aggregation_method: AggregationMethod + uncertainty_method: UncertaintyMethod + options: JSON + locked: Boolean +} +object Metric { + identifier: Varchar(64) + key: Varchar(32) + value: Float | Blob + step: Int +} + +' =================================== +Model "1..*" -up-> "1" User : owner +Model "1" <-left- "*" Metric : model +GlobalModel --|> Model +SWAGModel -up-|> GlobalModel +MeanModel --|> GlobalModel +MeanModel -[hidden]left-> GlobalModel : "\t" +MeanModel "*" --> "1..*" GlobalModel +LocalModel -up-|> Model +LocalModel "1..*" -right-> "1" GlobalModel : base_model +Training "1" --> "1" GlobalModel : model +Training -[hidden]right-> User +Training "1..*" --> "1..*" User : participants +Training "1..*" --> "1" User : actor +Token "1" --> "1" User : user +User -right-|> NotificationReceiver +Metric "1..*" -up-> "1" User : reporter +@enduml \ No newline at end of file diff --git a/docs/web-service/offline-usage.drawio.png b/docs/web-service/offline-usage.drawio.png new file mode 100644 index 0000000..49edb13 Binary files /dev/null and b/docs/web-service/offline-usage.drawio.png differ diff --git a/docs/web-service/online-inference.drawio.png b/docs/web-service/online-inference.drawio.png new file mode 100644 index 0000000..02ff80e Binary files /dev/null and b/docs/web-service/online-inference.drawio.png differ diff --git a/docs/web-service/training-process.png b/docs/web-service/training-process.png new file mode 100644 index 0000000..0fb8958 Binary files /dev/null and b/docs/web-service/training-process.png differ diff --git a/docs/web-service/training-process.puml b/docs/web-service/training-process.puml new file mode 100644 index 0000000..3240797 --- /dev/null +++ b/docs/web-service/training-process.puml @@ -0,0 +1,84 @@ +@startuml Training Process +!theme plain +'skinparam responseMessageBelowArrow true +skinparam style strictuml +skinparam sequence { + LifeLineBorderColor #848484 + GroupBorderColor #848484 +} + +Actor Actor +participant WebServer +database Database +collections Clients +participant "Celery Task Queue" as celery + +activate Actor + +Actor -> WebServer ++ : Create Model +WebServer -> Database ++ : Store Model +Database -->> WebServer -- +WebServer -->> Actor -- + +Actor -> WebServer ++ : Create Training +WebServer -> Database ++ : Store Training +Database -->> WebServer -- +WebServer -->> Actor -- + +Actor ->> WebServer --++ : Start Training +WebServer ->> Clients ++ : Start Training +deactivate Clients + +loop For n Updates + WebServer ->> Clients --++ : Start Training Round + + WebServer <- Clients ++ : Download Global Model + WebServer --> Clients -- : Global Model + + Clients -> Clients ++ : Train Local Model + Clients -[hidden]-> Clients -- + + Clients ->> WebServer --++ : Upload Local Model + WebServer -> Database ++ : Store Local Model + Database -->> WebServer -- + + note over WebServer,celery #eeeeee + continue if **all** __//model uploads//__ arrived + end note + + WebServer ->> celery --++ : Dispatch Aggregation Task + + celery -> Database ++ : Get Local Models + Database --> celery -- + + celery -> celery ++ : Do Aggregation + celery -[hidden]-> celery -- + + celery -> Database ++ : Store "New" Global Model + Database --> celery -- + + celery -> Database ++ : Clean Up Local Models + Database --> celery -- + + celery ->> Clients --++ : Start Model Test + + WebServer <- Clients ++ : Download Global Model + WebServer --> Clients -- : Global Model + + Clients -> Clients ++ : Test Global Model + Clients -[hidden]-> Clients -- + + Clients ->> WebServer --++ : Upload Global Model Test Metrics + WebServer -> Database ++ : Store Test Metrics + Database -->> WebServer -- + + note over WebServer,celery #eeeeee + continue if **all** __//test metrics//__ arrived + end note +end + +WebServer ->> Clients ++ : Training Finished +WebServer ->> Actor --++: Training Finished +deactivate Clients +deactivate Actor +@enduml \ No newline at end of file diff --git a/docs/web-service/training.drawio.png b/docs/web-service/training.drawio.png new file mode 100644 index 0000000..c8a183e Binary files /dev/null and b/docs/web-service/training.drawio.png differ diff --git a/fl_server/__init__.py b/fl_server/__init__.py new file mode 100644 index 0000000..fddd8ab --- /dev/null +++ b/fl_server/__init__.py @@ -0,0 +1,3 @@ +""" +Django Settings +""" diff --git a/fl_server/asgi.py b/fl_server/asgi.py new file mode 100644 index 0000000..2c56b97 --- /dev/null +++ b/fl_server/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for fl_server project. + +It exposes the ASGI callable as a module-level variable named `application`. + +For more information on this file, see + +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fl_server.settings.development") + +application = get_asgi_application() diff --git a/fl_server/settings/__init__.py b/fl_server/settings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fl_server/settings/base.py b/fl_server/settings/base.py new file mode 100644 index 0000000..cc34cb7 --- /dev/null +++ b/fl_server/settings/base.py @@ -0,0 +1,221 @@ +""" +General settings for DLR Federated Learning Demonstrator Server project. + +For more information on this file, see + + +For the full list of settings and their values, see + or + +""" + +from dlr.ki.logging import get_default_logging_dict +from pathlib import Path +from os import environ +from sys import argv + +from fl_server_core.utils.strings import str2bool + + +# Build paths inside the project like this: BASE_DIR / "subdir". +BASE_DIR = Path(__file__).resolve().parent.parent.parent + + +# Application definition + +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "polymorphic", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "corsheaders", + "rest_framework", + "rest_framework.authtoken", + "fl_server_core", + "fl_server_ai", + "fl_server_api", + "drf_spectacular", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "corsheaders.middleware.CorsMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", +] + +ROOT_URLCONF = "fl_server.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + }, +] + +WSGI_APPLICATION = "fl_server.wsgi.application" + +REST_FRAMEWORK = { + "DEFAULT_SCHEMA_CLASS": "fl_server_api.openapi.CustomAutoSchema", +} + +SPECTACULAR_SETTINGS = { + "TITLE": "DLR Federated Learning Demonstrator Server API", + "DESCRIPTION": "Catena-X ...", + "VERSION": "0.0.1.dev0", + "SERVE_AUTHENTICATION": [], + "PREPROCESSING_HOOKS": ["fl_server_api.openapi.custom_preprocessing_hook"], +} + + +# Database +# https://docs.djangoproject.com/en/4.1/ref/settings/#databases + + +DATABASES = { + "postgresql": { + "ENGINE": "django.db.backends.postgresql", + "HOST": environ.get("FL_POSTGRES_HOST", "db"), + "PORT": environ.get("FL_POSTGRES_PORT", "5432"), + "NAME": environ.get("FL_POSTGRES_DBNAME", "demo"), + "USER": environ.get("FL_POSTGRES_USER", "demo"), + "PASSWORD": environ.get("FL_POSTGRES_PASSWD", "example") + } +} +DATABASES["default"] = DATABASES["postgresql"] + + +# Cache +# https://docs.djangoproject.com/en/4.2/topics/cache + +def get_redis_location(*, fallback_host: str = "redis") -> str: + if (location := environ.get("FL_REDIS_LOCATION")) is not None: + return location + host = environ.get("FL_REDIS_HOST", fallback_host) + post = environ.get("FL_REDIS_PORT", "6379") + return f"redis://{host}:{post}/1" + +CACHES = { # noqa: E305 + "redis": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": get_redis_location(), + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + } + } +} +CACHES["default"] = CACHES["redis"] + + +# Password validation +# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.1/topics/i18n/ + +LANGUAGE_CODE = "en-us" + +TIME_ZONE = "Europe/Berlin" + +USE_I18N = True + +USE_TZ = True + + +# Cross-Origin Resource Sharing (CORS) configuration +# https://github.com/adamchainz/django-cors-headers#configuration + +CORS_ORIGIN_WHITELIST = environ.get("CORS_ORIGIN_WHITELIST", "").strip().splitlines() + +CORS_ALLOWED_ORIGIN_REGEXES = environ.get("CORS_ALLOWED_ORIGIN_REGEXES", "").strip().splitlines() + +CORS_ALLOW_ALL_ORIGINS = str2bool(environ.get("CORS_ALLOW_ALL_ORIGINS", "False")) + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.1/howto/static-files/ + +STATIC_URL = "static/" + + +# Default primary key field type +# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + + +# Substituting a custom User model +# https://docs.djangoproject.com/en/4.2/topics/auth/customizing/#substituting-a-custom-user-model + +AUTH_USER_MODEL = "fl_server_core.User" + + +# Celery Configuration Options +# https://docs.celeryq.dev/en/stable/userguide/configuration.html + +CELERY_TASK_ALWAYS_EAGER = False # `True` tells celery to run the task in sync (for debugging) +CELERY_TASK_TRACK_STARTED = True +CELERY_TASK_TIME_LIMIT = 30 * 60 +CELERY_TIMEZONE = TIME_ZONE +CELERY_TASK_SERIALIZER = "pickle" +CELERY_RESULT_SERIALIZER = "pickle" +CELERY_ACCEPT_CONTENT = ["pickle"] +CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True + + +# initializing and configuring logging +# https://docs.djangoproject.com/en/4.1/topics/logging/ + +LOGGING = get_default_logging_dict(str(BASE_DIR / "logs" / "server.log")) +# LOGGING["loggers"]["celery"] = LOGGING["loggers"][""] +# LOKI_SETTINGS = { +# "level": "DEBUG", +# "class": "logging_loki.LokiHandler", +# "url": "http://localhost:3100/loki/api/v1/push", +# "tags": { +# "app": "fl.server" +# }, +# "auth": ["admin", "admin"], +# "version": "1", +# } +# LOGGING["handlers"]["loki"] = LOKI_SETTINGS +# LOGGING["loggers"][""]["handlers"].append("loki") +# LOGGING["loggers"]["urllib3"] = {"level": "WARNING"} + + +# Federated Learning Properties + +MAX_RUNNING_CHILD_PROCESSES = int(environ.get("FL_MAX_CHILD_PROCESSES", 8)) +SSL_FORCE = str2bool(environ.get("FL_SSL_FORCE_REQUESTS"), "test" not in argv) diff --git a/fl_server/settings/development.py b/fl_server/settings/development.py new file mode 100644 index 0000000..e76a71e --- /dev/null +++ b/fl_server/settings/development.py @@ -0,0 +1,56 @@ +from os import environ + +# import and define setting defaults +from .base import * # noqa: F403 # NOSONAR + + +# SECRET_KEY and SECRET_KEY_FALLBACK +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#secret-key + +SECRET_KEY = "django-insecure-*z=iw5n%b--qdim+x5b+j9=^_gq7hq)kk8@7$^(tyn@oc#_8by" # cspell:ignore qdim + + +# DEBUG +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#debug + +DEBUG = True # if `True` celery will result in memory leaks + + +# ALLOWED_HOSTS +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#allowed-hosts + +ALLOWED_HOSTS = ["*"] + + +# Cross-Origin Resource Sharing (CORS) configuration +# https://github.com/adamchainz/django-cors-headers#configuration + +CORS_ALLOW_ALL_ORIGINS = True + + +# DATABASES +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#databases + +# overwrite postgresql host default value from "db" to "localhost" +DATABASES["postgresql"]["HOST"] = environ.get("FL_POSTGRES_HOST", "localhost") # noqa: F405 + +# add sqlite3 support +DATABASES["sqlite3"] = { # noqa: F405 + "ENGINE": "django.db.backends.sqlite3", + "NAME": "db.sqlite3", +} +DATABASES["default"] = DATABASES[environ.get("FL_DJANGO_DATABASE", "postgresql")] # noqa: F405 + + +# Cache +# https://docs.djangoproject.com/en/4.2/topics/cache + +# overwrite redis host default value from "redis" to "localhost" +CACHES["redis"]["LOCATION"] = get_redis_location(fallback_host="localhost") # noqa: F405 + + +# HTTPS +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#https + +CSRF_COOKIE_SECURE = False +SESSION_COOKIE_SECURE = True diff --git a/fl_server/settings/production.py b/fl_server/settings/production.py new file mode 100644 index 0000000..1a31455 --- /dev/null +++ b/fl_server/settings/production.py @@ -0,0 +1,78 @@ +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ + +from os import environ + +# import and define setting defaults +from .base import * # noqa: F403 # NOSONAR + + +def get_secret(env_key: str, *, ensure: bool = False) -> str | None: + if (secret_file := environ.get(f"{env_key}_FILE")) is not None: + with open(secret_file) as f: + return f.read().strip() + + if ensure: + # let this throw an exception if neither SECRET_KEY_FILE nor SECRET_KEY is set + return environ[env_key] + + return environ.get(env_key) + + +# SECRET_KEY and SECRET_KEY_FALLBACK +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#secret-key + +SECRET_KEY: str = get_secret("FL_DJANGO_SECRET_KEY", ensure=True) # type:ignore[assignment] +if (_secret_key_fallbacks := get_secret("FL_DJANGO_SECRET_KEY_FALLBACK")) is not None: + SECRET_KEY_FALLBACKS = _secret_key_fallbacks.strip().splitlines() + + +# DEBUG +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#debug + +DEBUG = False + + +# ALLOWED_HOSTS +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#allowed-hosts + +ALLOWED_HOSTS = environ.get("FL_DJANGO_ALLOWED_HOSTS", "").strip().splitlines() + + +# DATABASES +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#databases + +DATABASES["postgresql"]["PASSWORD"] = str(get_secret("FL_POSTGRES_PASSWD", ensure=True)) # noqa: F405 + + +# EMAIL_BACKEND and related settings +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#email-backend-and-related-settings + + +# STATIC_ROOT and STATIC_URL +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#static-root-and-static-url + +STATIC_ROOT = BASE_DIR / "static" # noqa: F405 +STATIC_URL = "static/" +ADMIN_MEDIA_PREFIX = STATIC_URL + "admin/" + + +# MEDIA_ROOT and MEDIA_URL +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#media-root-and-media-url + +# MEDIA_ROOT = "" +# MEDIA_URL = "media/" + + +# HTTPS +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#https + +CSRF_COOKIE_SECURE = True +SESSION_COOKIE_SECURE = True + + +# Performance optimizations +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#performance-optimizations + + +# Error reporting +# https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/#error-reporting diff --git a/fl_server/urls.py b/fl_server/urls.py new file mode 100644 index 0000000..08de532 --- /dev/null +++ b/fl_server/urls.py @@ -0,0 +1,33 @@ +""" +URL configuration for fl_server project. + +The `urlpatterns` list routes URLs to views. For more information please see: + + +Examples: + Function views + 1. Add an import: `from my_app import views` + 2. Add a URL to urlpatterns: `path("", views.home, name="home")` + + Class-based views + 1. Add an import: `from other_app.views import Home` + 2. Add a URL to urlpatterns: `path("", Home.as_view(), name="home")` + + Including another URLconf + 1. Import the include() function: `from django.urls import include, path` + 2. Add a URL to urlpatterns: `path("blog/", include("blog.urls"))` +""" +from django.contrib import admin +from django.urls import path, include + +from fl_server_api import urls as api_urls + + +urlpatterns = [ + path("admin/", admin.site.urls), + path("api-auth/", include("rest_framework.urls")), + path("api/", include(api_urls)), +] + +handler500 = "rest_framework.exceptions.server_error" +handler400 = "rest_framework.exceptions.bad_request" diff --git a/fl_server/wsgi.py b/fl_server/wsgi.py new file mode 100644 index 0000000..0f9bea8 --- /dev/null +++ b/fl_server/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for fl_server project. + +It exposes the WSGI callable as a module-level variable named `application`. + +For more information on this file, see + +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fl_server.settings.development") + +application = get_wsgi_application() diff --git a/fl_server_ai/__init__.py b/fl_server_ai/__init__.py new file mode 100644 index 0000000..e1f6a07 --- /dev/null +++ b/fl_server_ai/__init__.py @@ -0,0 +1,7 @@ +""" +AI Service +""" +from fl_server_ai.celery_tasks import app as celery_app + + +__all__ = ["celery_app"] diff --git a/fl_server_ai/aggregation/__init__.py b/fl_server_ai/aggregation/__init__.py new file mode 100644 index 0000000..1302a47 --- /dev/null +++ b/fl_server_ai/aggregation/__init__.py @@ -0,0 +1,6 @@ +from .base import Aggregation +from .mean import MeanAggregation +from .method import get_aggregation_class + + +__all__ = ["Aggregation", "get_aggregation_class", "MeanAggregation"] diff --git a/fl_server_ai/aggregation/base.py b/fl_server_ai/aggregation/base.py new file mode 100644 index 0000000..5aef5a7 --- /dev/null +++ b/fl_server_ai/aggregation/base.py @@ -0,0 +1,18 @@ +from abc import ABC, abstractmethod +from logging import getLogger +import torch +from typing import Sequence + + +class Aggregation(ABC): + _logger = getLogger("fl.server") + + @abstractmethod + def aggregate( + self, + models: Sequence[torch.nn.Module], + model_sample_sizes: Sequence[int], + *, + deepcopy: bool = True + ) -> torch.nn.Module: + pass diff --git a/fl_server_ai/aggregation/fed_dc.py b/fl_server_ai/aggregation/fed_dc.py new file mode 100644 index 0000000..1fe0444 --- /dev/null +++ b/fl_server_ai/aggregation/fed_dc.py @@ -0,0 +1,29 @@ +import torch +from typing import Sequence + +from .base import Aggregation + + +class FedDC(Aggregation): + """ + FedDC (Federated daisy-chaining) + + To tackle the problem that client models are potentially quite small and thus the models tend to overfit and + therefore result in bad prediction quality on unseen data, one proposed solution is + FedDC (also named Federated daisy-chaining). + FedDC sends before each aggregation step each client model to another randomly selected client, which trains + it on its local data. + From the model perspective, it is as if the model is trained on a larger dataset. + + Paper: [Picking Daisies in Private: Federated Learning from Small Datasets](https://openreview.net/forum?id=GVDwiINkMR) + """ # noqa: E501 + + @torch.no_grad() + def aggregate( + self, + models: Sequence[torch.nn.Module], + model_sample_sizes: Sequence[int], + *, + deepcopy: bool = True + ) -> torch.nn.Module: + raise NotImplementedError("FedDC is not implemented yet!") diff --git a/fl_server_ai/aggregation/fed_prox.py b/fl_server_ai/aggregation/fed_prox.py new file mode 100644 index 0000000..7cacd5e --- /dev/null +++ b/fl_server_ai/aggregation/fed_prox.py @@ -0,0 +1,17 @@ +from .mean import MeanAggregation + + +class FedProx(MeanAggregation): + """ + To tackle the problem that client models drift away from optimum due to data heterogeneity, + different learning speeds, etc. one proposed solution is FedProx. + FedProx limits the client drift by using a modified learning objective but keeping the standard + FedAvg aggregation method. + + Note: + FedProx does not do anything different on the server side than normal FedAvg. + The difference lies in the application of a special loss function on the client side. + + Paper: [Federated Optimization in Heterogeneous Networks](https://arxiv.org/abs/1812.06127) + """ + pass diff --git a/fl_server_ai/aggregation/mean.py b/fl_server_ai/aggregation/mean.py new file mode 100644 index 0000000..6d1e8d7 --- /dev/null +++ b/fl_server_ai/aggregation/mean.py @@ -0,0 +1,46 @@ +import copy +import torch +from typing import Sequence + +from ..exceptions import AggregationException + +from .base import Aggregation + + +class MeanAggregation(Aggregation): + + @torch.no_grad() + def aggregate( + self, + models: Sequence[torch.nn.Module], + model_sample_sizes: Sequence[int], + *, + deepcopy: bool = True + ) -> torch.nn.Module: + assert len(models) == len(model_sample_sizes) + + self._logger.debug(f"Doing mean aggregation for {len(models)} models!") + model_state_dicts = [model.state_dict() for model in models] + + total_dataset_size = model_sample_sizes[0] + result_dict = model_state_dicts[0] + for layer_name in result_dict: + result_dict[layer_name] *= model_sample_sizes[0] + + # sum accumulation + for model_dict, dataset_size in zip(model_state_dicts[1:], model_sample_sizes[1:]): + if set(model_dict.keys()) != set(result_dict.keys()): + raise AggregationException("Models do not have the same architecture!") + + total_dataset_size += dataset_size + for layer_name in result_dict: + result_dict[layer_name] += model_dict[layer_name] * dataset_size + + # factor 1/n + for layer_name in result_dict: + result_dict[layer_name] = result_dict[layer_name] / total_dataset_size + + # return aggregated model + result_model = copy.deepcopy(models[0]) if deepcopy else models[0] + result_model.load_state_dict(result_dict) + return result_model diff --git a/fl_server_ai/aggregation/method.py b/fl_server_ai/aggregation/method.py new file mode 100644 index 0000000..1ddf145 --- /dev/null +++ b/fl_server_ai/aggregation/method.py @@ -0,0 +1,41 @@ +from typing import overload, Type + +from fl_server_core.models import Model, Training +from fl_server_core.models.training import AggregationMethod + +from .base import Aggregation +from .fed_dc import FedDC +from .fed_prox import FedProx +from .mean import MeanAggregation + + +@overload +def get_aggregation_class(value: Model) -> Type[Aggregation]: ... + + +@overload +def get_aggregation_class(value: Training) -> Type[Aggregation]: ... + + +@overload +def get_aggregation_class(value: AggregationMethod) -> Type[Aggregation]: ... + + +def get_aggregation_class(value: AggregationMethod | Model | Training) -> Type[Aggregation]: + if isinstance(value, AggregationMethod): + method = value + elif isinstance(value, Training): + method = value.aggregation_method + elif isinstance(value, Model): + aggregation_method = Training.objects.filter(model=value) \ + .values("aggregation_method") \ + .first()["aggregation_method"] + method = aggregation_method + else: + raise ValueError(f"Unknown type: {type(value)}") + + match method: + case AggregationMethod.FED_AVG: return MeanAggregation + case AggregationMethod.FED_DC: return FedDC + case AggregationMethod.FED_PROX: return FedProx + case _: raise ValueError(f"Unknown aggregation method: {method}") diff --git a/fl_server_ai/apps.py b/fl_server_ai/apps.py new file mode 100644 index 0000000..aca6822 --- /dev/null +++ b/fl_server_ai/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class FlServerAiConfig(AppConfig): + name = "fl_server_ai" + verbose_name = "Federated Learning Demonstrator AI" diff --git a/fl_server_ai/celery_tasks.py b/fl_server_ai/celery_tasks.py new file mode 100644 index 0000000..a69385d --- /dev/null +++ b/fl_server_ai/celery_tasks.py @@ -0,0 +1,31 @@ +from celery import Celery +from celery.signals import setup_logging +from django.conf import settings +from logging.config import dictConfig + + +app = Celery("fl_server") + +# Using a string here means the worker doesn't have to serialize +# the configuration object to child processes. +# - namespace="CELERY" means all celery-related configuration keys +# should have a `CELERY_` prefix. +app.config_from_object("django.conf:settings", namespace="CELERY") +app.conf.update( + broker_url=settings.CACHES["default"]["LOCATION"], + result_backend=settings.CACHES["default"]["LOCATION"], + broker_transport_options={ + "visibility_timeout": 31540000, + "fanout_prefix": True, + "fanout_patterns": True, + } +) + +# Load task modules from all registered Django apps. +app.autodiscover_tasks() + + +# Configure logging +@setup_logging.connect +def init_loggers(*args, **kwargs): + dictConfig(settings.LOGGING) diff --git a/fl_server_ai/exceptions.py b/fl_server_ai/exceptions.py new file mode 100644 index 0000000..cc86f71 --- /dev/null +++ b/fl_server_ai/exceptions.py @@ -0,0 +1,34 @@ +from requests import Response +from typing import Any, Optional + + +class AggregationException(Exception): + pass + + +class NotificationException(Exception): + + def __init__( + self, + endpoint_url: str, + json_data: Any, + max_retries: int, + return_obj: Any = None, + inner_exception: Optional[Exception] = None, + *args, + **kwargs + ): + super().__init__(*args, **kwargs) + self.endpoint_url = endpoint_url + self.json_data = json_data + self.max_retries = max_retries + self.notification_return_object = return_obj + self.inner_exception = inner_exception + + +class ClientNotificationRejectionException(NotificationException): + + def __init__(self, response: Response, *args, **kwargs): + super().__init__(*args, **kwargs) + self.response = response + self.status_code = response.status_code diff --git a/fl_server_ai/notification/__init__.py b/fl_server_ai/notification/__init__.py new file mode 100644 index 0000000..81d3b58 --- /dev/null +++ b/fl_server_ai/notification/__init__.py @@ -0,0 +1,11 @@ +from .notification_type import NotificationType +from .notification import Notification +from .training import TrainingRoundStartNotification, TrainingFinishedNotification + + +__all__ = [ + "NotificationType", + "Notification", + "TrainingRoundStartNotification", + "TrainingFinishedNotification", +] diff --git a/fl_server_ai/notification/notification.py b/fl_server_ai/notification/notification.py new file mode 100644 index 0000000..c5a4b54 --- /dev/null +++ b/fl_server_ai/notification/notification.py @@ -0,0 +1,101 @@ +from abc import ABCMeta +from celery import Signature +from celery.result import AsyncResult +from celery.utils.log import get_task_logger +from dataclasses import dataclass, field +from rest_framework import status +import requests +import time +from typing import Any, Generic, Optional, TypeVar + +from fl_server_core.models.user import NotificationReceiver + +from ..celery_tasks import app +from ..exceptions import ClientNotificationRejectionException, NotificationException + +from .serializable import Serializable +from .notification_type import NotificationType + + +TBody = TypeVar("TBody", bound=Serializable) +TReturn = TypeVar("TReturn", bound=Any) + + +@app.task(bind=False, ignore_result=False) +def send_notifications( + notification: "Notification", + callback_success: Optional[Signature] = None, + callback_error: Optional[Signature] = None +): + logger = get_task_logger("fl.celery") + for receiver in notification.receivers: + logger.info( + f"Sending notification '{notification.type}' " + + f"to client '{receiver.id}' with URL '{receiver.message_endpoint}'" + ) + send_notification.s( + endpoint_url=receiver.message_endpoint, json_data=notification.serialize(), return_obj=receiver + ).apply_async(link=callback_success, link_error=callback_error, retry=False) + + +@app.task(bind=False, ignore_result=False) +def send_notification( + endpoint_url: str, + json_data: Any, + max_retries: int = 5, + *, + return_obj: Optional[TReturn] = None +) -> Optional[TReturn]: + logger = get_task_logger("fl.celery") + retries: int = 0 + while True: + try: + response = requests.post(url=endpoint_url, json=json_data, headers={"content-type": "application/json"}) + if not status.is_success(response.status_code): + raise ClientNotificationRejectionException(response, endpoint_url, json_data, max_retries, return_obj) + return return_obj + except ClientNotificationRejectionException as e: + logger.error(f"Sending notification to URL '{endpoint_url}' return status code: {e.status_code}") + raise e + except Exception as e: + logger.warn(f"Sending notification to URL '{endpoint_url}' produced exception: {e}") + retries += 1 + if retries > max_retries: + raise NotificationException(endpoint_url, json_data, max_retries, return_obj, e) + time.sleep(5*retries) + + +@dataclass +class Notification(Generic[TBody], Serializable, metaclass=ABCMeta): + receivers: list[NotificationReceiver] + body: TBody + type: NotificationType = field(init=False) + + @dataclass + class Body(Serializable): + pass + + @property + def callback_success(self) -> Optional[Signature]: + return None + + @property + def callback_error(self) -> Optional[Signature]: + return None + + def send( + self, + callback_success: Optional[Signature] = None, + callback_error: Optional[Signature] = None + ) -> AsyncResult: + callback_success = callback_success or self.callback_success + callback_error = callback_error or self.callback_error + return send_notifications.s( + notification=self, callback_success=callback_success, callback_error=callback_error + ).apply_async(retry=False) + + def serialize(self) -> dict[str, Any]: + return { + "notification_type": self.type.value, + "body": self.body.serialize() + } diff --git a/fl_server_ai/notification/notification_type.py b/fl_server_ai/notification/notification_type.py new file mode 100644 index 0000000..536b4c8 --- /dev/null +++ b/fl_server_ai/notification/notification_type.py @@ -0,0 +1,25 @@ +from django.utils.translation import gettext_lazy as _ +from enum import Enum +from typing import Optional + + +class NotificationType(Enum): + UPDATE_ROUND_START = "UPDATE_ROUND_START", _("Start update round") + SWAG_ROUND_START = "SWAG_ROUND_START", _("Start swag round") + TRAINING_START = "TRAINING_START", _("Training start") + TRAINING_FINISHED = "TRAINING_FINISHED", _("Training finished") + CLIENT_REMOVED = "CLIENT_REMOVED", _("Client removed") + MODEL_TEST_ROUND = "MODEL_TEST_ROUND", _("Start model round") + + def __new__(cls, *args, **kwargs): + obj = object.__new__(cls) + obj._value_ = args[0] + return obj + + def __init__(self, _: str, description: Optional[str] = None): + # ignore the first param since it's already set by __new__ + self._description_ = description + + @property + def description(self): + return self._description_ diff --git a/fl_server_ai/notification/serializable.py b/fl_server_ai/notification/serializable.py new file mode 100644 index 0000000..6cc1d91 --- /dev/null +++ b/fl_server_ai/notification/serializable.py @@ -0,0 +1,10 @@ +from dataclasses import asdict, dataclass +from typing import Any +from uuid import UUID + + +@dataclass +class Serializable: + + def serialize(self) -> dict[str, Any]: + return {key: str(value) if isinstance(value, UUID) else value for key, value in asdict(self).items()} diff --git a/fl_server_ai/notification/training/__init__.py b/fl_server_ai/notification/training/__init__.py new file mode 100644 index 0000000..25d50a2 --- /dev/null +++ b/fl_server_ai/notification/training/__init__.py @@ -0,0 +1,16 @@ +from .finished import TrainingFinishedNotification +from .model_test import TrainingModelTestNotification +from .round_start import TrainingRoundStartNotification +from .start import TrainingStartNotification +from .swag import TrainingSWAGRoundStartNotification +from .training import TrainingNotification + + +__all__ = [ + "TrainingModelTestNotification", + "TrainingNotification", + "TrainingFinishedNotification", + "TrainingStartNotification", + "TrainingSWAGRoundStartNotification", + "TrainingRoundStartNotification", +] diff --git a/fl_server_ai/notification/training/finished.py b/fl_server_ai/notification/training/finished.py new file mode 100644 index 0000000..0caba41 --- /dev/null +++ b/fl_server_ai/notification/training/finished.py @@ -0,0 +1,29 @@ +from dataclasses import dataclass +from uuid import UUID + +from fl_server_core.models import Training as TrainingDB + +from ..serializable import Serializable +from ..notification_type import NotificationType +from .training import TrainingNotification + + +class TrainingFinishedNotification(TrainingNotification["TrainingFinishedNotification.Body"]): + type: NotificationType = NotificationType.TRAINING_FINISHED + + @dataclass + class Body(Serializable): + global_model_uuid: UUID + + @classmethod + def from_training(cls, training: TrainingDB): + receivers = list(training.participants.all()) + if not receivers.__contains__(training.actor): + receivers.append(training.actor) + return cls( + receivers=receivers, + body=cls.Body( + global_model_uuid=training.model.id + ), + training_uuid=training.id + ) diff --git a/fl_server_ai/notification/training/model_test.py b/fl_server_ai/notification/training/model_test.py new file mode 100644 index 0000000..ab9868f --- /dev/null +++ b/fl_server_ai/notification/training/model_test.py @@ -0,0 +1,6 @@ +from ..notification_type import NotificationType +from .round_start import TrainingRoundStartNotification + + +class TrainingModelTestNotification(TrainingRoundStartNotification): + type: NotificationType = NotificationType.MODEL_TEST_ROUND diff --git a/fl_server_ai/notification/training/round_start.py b/fl_server_ai/notification/training/round_start.py new file mode 100644 index 0000000..a48b3a9 --- /dev/null +++ b/fl_server_ai/notification/training/round_start.py @@ -0,0 +1,71 @@ +from celery import Signature +from celery.utils.log import get_task_logger +from dataclasses import dataclass +from typing import Optional +from uuid import UUID + +from fl_server_core.models import Training as TrainingDB, User as UserDB +from fl_server_core.models.training import TrainingState +from fl_server_core.models.user import NotificationReceiver + +from ...celery_tasks import app +from ...exceptions import ClientNotificationRejectionException, NotificationException +from ..serializable import Serializable +from ..notification_type import NotificationType +from .training import TrainingNotification + + +@app.task(bind=False, ignore_result=True) +def training_notification_callback_success(receiver: NotificationReceiver, training_uuid: UUID): + logger = get_task_logger("fl.celery") + logger.debug(f"Training {training_uuid}: User {receiver.id} accepted notification") + + +@app.task(bind=False, ignore_result=True) +def training_notification_callback_failure(exception: NotificationException, training_uuid: UUID): + logger = get_task_logger("fl.celery") + if isinstance(exception, ClientNotificationRejectionException): + # client sent error response, remove + receiver: NotificationReceiver = exception.notification_return_object + logger.warn( + f"Training {training_uuid}: User {receiver.id} sent error response: {exception.status_code}." + "User will be removed from training!" + ) + user = receiver if isinstance(receiver, UserDB) else UserDB.objects.get(id=receiver.id) + TrainingDB.objects.get(id=training_uuid).participants.remove(user) + else: + # set training to error state + e = exception.inner_exception if exception.inner_exception else exception + logger.error(f"Training {training_uuid}: Exception occurred during sending: {e}") + logger.error(f"Training {training_uuid} is in error state!") + training = TrainingDB.objects.get(id=training_uuid) + training.state = TrainingState.ERROR + training.save() + + +class TrainingRoundStartNotification(TrainingNotification["TrainingRoundStartNotification.Body"]): + type: NotificationType = NotificationType.UPDATE_ROUND_START + + @property + def callback_success(self) -> Optional[Signature]: + return training_notification_callback_success.s(training_uuid=self.training_uuid) + + @property + def callback_error(self) -> Optional[Signature]: + return training_notification_callback_failure.s(training_uuid=self.training_uuid) + + @dataclass + class Body(Serializable): + round: int + global_model_uuid: UUID + + @classmethod + def from_training(cls, training: TrainingDB): + return cls( + receivers=training.participants.all(), + body=cls.Body( + round=training.model.round, + global_model_uuid=training.model.id + ), + training_uuid=training.id + ) diff --git a/fl_server_ai/notification/training/start.py b/fl_server_ai/notification/training/start.py new file mode 100644 index 0000000..a056704 --- /dev/null +++ b/fl_server_ai/notification/training/start.py @@ -0,0 +1,26 @@ +from dataclasses import dataclass +from uuid import UUID + +from fl_server_core.models import Training as TrainingDB + +from ..serializable import Serializable +from ..notification_type import NotificationType +from .training import TrainingNotification + + +class TrainingStartNotification(TrainingNotification["TrainingStartNotification.Body"]): + type: NotificationType = NotificationType.TRAINING_START + + @dataclass + class Body(Serializable): + global_model_uuid: UUID + + @classmethod + def from_training(cls, training: TrainingDB): + return cls( + receivers=training.participants.all(), + body=cls.Body( + global_model_uuid=training.model.id + ), + training_uuid=training.id + ) diff --git a/fl_server_ai/notification/training/swag.py b/fl_server_ai/notification/training/swag.py new file mode 100644 index 0000000..c429841 --- /dev/null +++ b/fl_server_ai/notification/training/swag.py @@ -0,0 +1,6 @@ +from ..notification_type import NotificationType +from .round_start import TrainingRoundStartNotification + + +class TrainingSWAGRoundStartNotification(TrainingRoundStartNotification): + type: NotificationType = NotificationType.SWAG_ROUND_START diff --git a/fl_server_ai/notification/training/training.py b/fl_server_ai/notification/training/training.py new file mode 100644 index 0000000..8a42c94 --- /dev/null +++ b/fl_server_ai/notification/training/training.py @@ -0,0 +1,15 @@ +from dataclasses import dataclass +from typing import Any, Generic +from uuid import UUID + +from ..notification import Notification, TBody + + +@dataclass +class TrainingNotification(Generic[TBody], Notification[TBody]): + training_uuid: UUID + + def serialize(self) -> dict[str, Any]: + data = super().serialize() + data["training_uuid"] = str(self.training_uuid) + return data diff --git a/fl_server_ai/tests/__init__.py b/fl_server_ai/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fl_server_ai/tests/test_aggregation.py b/fl_server_ai/tests/test_aggregation.py new file mode 100644 index 0000000..b62d81b --- /dev/null +++ b/fl_server_ai/tests/test_aggregation.py @@ -0,0 +1,40 @@ +from django.test import TestCase +import torch + +from ..aggregation.mean import MeanAggregation + + +def _create_model_and_init(init: float) -> torch.nn.Module: + init = float(init) + model = torch.nn.Sequential( + torch.nn.Linear(1, 5), + torch.nn.Tanh(), + torch.nn.BatchNorm1d(5), + torch.nn.Linear(5, 3) + ) + torch.nn.init.constant_(model[0].weight, init) + torch.nn.init.constant_(model[0].bias, init) + torch.nn.init.constant_(model[3].weight, init) + torch.nn.init.constant_(model[3].bias, init) + return model + + +class AggregationTest(TestCase): + + def test_aggregate(self): + aggr = MeanAggregation() + models = [_create_model_and_init(i) for i in range(10)] + res = aggr.aggregate(models, [1]*10) + self.assertTrue(isinstance(res, torch.nn.Sequential)) + self.assertEqual(len(list(models[0].parameters())), len(list(res.parameters()))) + torch.testing.assert_close(res[0].weight, torch.ones_like(res[0].weight) * 4.5) + torch.testing.assert_close(res[3].weight, torch.ones_like(res[3].weight) * 4.5) + + def test_aggregate_sample_sizes(self): + aggr = MeanAggregation() + models = [_create_model_and_init(i) for i in range(3)] + res = aggr.aggregate(models, [0, 1, 2]) + self.assertTrue(isinstance(res, torch.nn.Sequential)) + self.assertEqual(len(list(models[0].parameters())), len(list(res.parameters()))) + torch.testing.assert_close(res[0].weight, torch.ones_like(res[0].weight) * (5/3)) + torch.testing.assert_close(res[3].weight, torch.ones_like(res[3].weight) * (5/3)) diff --git a/fl_server_ai/tests/test_aggregation_process.py b/fl_server_ai/tests/test_aggregation_process.py new file mode 100644 index 0000000..6c7549e --- /dev/null +++ b/fl_server_ai/tests/test_aggregation_process.py @@ -0,0 +1,50 @@ +from django.test import TransactionTestCase +import json + +from fl_server_core.models.training import Training, TrainingState +from fl_server_core.tests import BASE_URL, Dummy + +from ..trainer import ModelTrainer, TrainerOptions +from ..trainer.events import TrainingRoundFinished + + +class AggregationProcessTest(TransactionTestCase): + + def setUp(self): + self.user = Dummy.create_user_and_authenticate(self.client) + + def test_check_and_run_aggregation_if_applicable_training_step(self): + clients = [Dummy.create_user() for _ in range(10)] + training = Dummy.create_training(state=TrainingState.ONGOING, target_num_updates=10, actor=self.user) + training.participants.set(clients) + updates = [Dummy.create_model_update(base_model=training.model, round=0) for _ in range(10)] + for update in updates: + update.save() + + with self.assertLogs("fl.server", level="INFO"): + ModelTrainer(training, TrainerOptions(skip_model_tests=True)).handle_cls(TrainingRoundFinished) + + response = self.client.get(f"{BASE_URL}/models/{training.model.id}/metadata/") + content = json.loads(response.content) + self.assertEqual(content["round"], 1) + + training = Training.objects.get(id=training.id) + self.assertEqual(TrainingState.ONGOING, training.state) + + def test_check_and_run_aggregation_if_applicable_training_finished(self): + clients = [Dummy.create_user() for _ in range(10)] + model = Dummy.create_model(owner=self.user, round=1) + training = Dummy.create_training(state=TrainingState.ONGOING, target_num_updates=1, actor=self.user, + model=model) + training.participants.set(clients) + updates = [Dummy.create_model_update(base_model=training.model, round=1) for _ in range(10)] + for update in updates: + update.save() + + options = TrainerOptions(skip_model_tests=True) + trainer = ModelTrainer(training, options) + with self.assertLogs("fl.server", level="INFO"): + trainer.handle_cls(TrainingRoundFinished) + + training = Training.objects.get(id=training.id) + self.assertEqual(TrainingState.COMPLETED, training.state) diff --git a/fl_server_ai/tests/test_ai_worker.py b/fl_server_ai/tests/test_ai_worker.py new file mode 100644 index 0000000..5d783fb --- /dev/null +++ b/fl_server_ai/tests/test_ai_worker.py @@ -0,0 +1,161 @@ +from django.test import TestCase +import pickle +import torch +from unittest.mock import MagicMock, patch + +from fl_server_core.models.model import SWAGModel +from fl_server_core.models.training import Training, TrainingState, UncertaintyMethod +from fl_server_core.tests import Dummy + +from ..notification import Notification +from ..trainer import ModelTrainer, process_trainer_task +from ..trainer.events import SWAGRoundFinished, TrainingRoundFinished +from ..trainer.options import TrainerOptions + +from .test_aggregation import _create_model_and_init + + +class AiWorkerTest(TestCase): + + def test_process_training_good(self): + training = Dummy.create_training(state=TrainingState.ONGOING, locked=True) + model1 = _create_model_and_init(0) + model2 = _create_model_and_init(1) + Dummy.create_model_update( + base_model=training.model, + owner=training.participants.all()[0], + round=0, + weights=pickle.dumps(model1), + ) + Dummy.create_model_update( + base_model=training.model, + owner=training.participants.all()[1], + round=0, + weights=pickle.dumps(model2) + ) + with self.assertLogs(level="INFO"): + ModelTrainer(training, TrainerOptions(skip_model_tests=True)).handle_cls(TrainingRoundFinished) + res = training.model.get_torch_model() + torch.testing.assert_close(res[0].weight, torch.ones_like(res[0].weight) * 0.5) + torch.testing.assert_close(res[3].weight, torch.ones_like(res[3].weight) * 0.5) + + @patch("fl_server_ai.aggregation.mean.MeanAggregation.aggregate") + def test_process_training_bad1(self, aggregate_updates: MagicMock): + training = Dummy.create_training(state=TrainingState.ONGOING, locked=True) + model1 = _create_model_and_init(0) + model2 = _create_model_and_init(1) + model3 = _create_model_and_init(500) + Dummy.create_model_update( + base_model=training.model, + owner=training.participants.all()[0], + round=0, + weights=pickle.dumps(model1), + ) + Dummy.create_model_update( + base_model=training.model, + owner=training.participants.all()[1], + round=0, + weights=pickle.dumps(model2) + ) + Dummy.create_model_update( + base_model=training.model, + owner=training.participants.all()[1], + round=0, + weights=pickle.dumps(model3) + ) + with self.assertLogs(level="ERROR"): + with self.assertRaises(RuntimeError): + ModelTrainer(training, TrainerOptions(skip_model_tests=True)).handle_cls(TrainingRoundFinished) + + self.assertFalse(aggregate_updates.called) + + @patch("fl_server_ai.aggregation.mean.MeanAggregation.aggregate") + def test_process_training_bad2(self, aggregate_updates: MagicMock): + training = Dummy.create_training(state=TrainingState.ONGOING, locked=True) + model1 = _create_model_and_init(0) + Dummy.create_model_update( + base_model=training.model, + owner=training.participants.all()[0], + round=0, + weights=pickle.dumps(model1), + ) + with self.assertLogs(level="ERROR"), self.assertRaises(RuntimeError): + ModelTrainer(training, TrainerOptions(skip_model_tests=True)).handle_cls(TrainingRoundFinished) + + self.assertFalse(aggregate_updates.called) + + @patch.object(Notification, "send") + def test_process_training(self, send_notification): + model = Dummy.create_model( + model_cls=SWAGModel, + weights=pickle.dumps(torch.nn.Sequential( # this model has exactly 15 parameters + torch.nn.Linear(1, 5), + torch.nn.ReLU(), + torch.nn.Linear(5, 1) + )), + round=100 + ) + training = Dummy.create_training( + state=TrainingState.SWAG_ROUND, + uncertainty_method=UncertaintyMethod.SWAG, + locked=True, + model=model, + target_num_updates=100 + ) + Dummy.create_metric( + step=100, + key="SWAG First Moment Local", + model=model, + reporter=training.participants.all()[0], + value_binary=pickle.dumps(torch.zeros(15)) + ) + Dummy.create_metric( + step=100, + key="SWAG Second Moment Local", + model=model, + reporter=training.participants.all()[0], + value_binary=pickle.dumps(torch.ones(15)) + ) + Dummy.create_metric( + step=100, + key="SWAG Sample Size Local", + model=model, + reporter=training.participants.all()[0], + value_float=1000 + ) + Dummy.create_metric( + step=100, + key="SWAG First Moment Local", + model=model, + reporter=training.participants.all()[1], + value_binary=pickle.dumps(torch.zeros(15)) + ) + Dummy.create_metric( + step=100, + key="SWAG Second Moment Local", + model=model, + reporter=training.participants.all()[1], + value_binary=pickle.dumps(torch.ones(15)) + ) + Dummy.create_metric( + step=100, + key="SWAG Sample Size Local", + model=model, + reporter=training.participants.all()[1], + value_float=1000 + ) + with self.assertLogs("fl.server", level="INFO") as cm: + process_trainer_task(training.id, SWAGRoundFinished) + self.assertEqual(cm.output, [ + f"INFO:fl.server:Training {training.id}: Doing SWAG aggregation as all 2 updates arrived", + f"INFO:fl.server:SWAG completed for training {training.id}", + ]) + self.assertTrue(send_notification.called) + training = Training.objects.get(id=training.id) + self.assertFalse(training.locked) + model = training.model + self.assertEquals(TrainingState.ONGOING, training.state) # next would be ModelTestFinished + fst = model.first_moment + snd = model.second_moment + torch.testing.assert_close(torch.zeros(15), fst) + torch.testing.assert_close(torch.ones(15), snd) diff --git a/fl_server_ai/tests/test_feddc.py b/fl_server_ai/tests/test_feddc.py new file mode 100644 index 0000000..bc976d9 --- /dev/null +++ b/fl_server_ai/tests/test_feddc.py @@ -0,0 +1,93 @@ +from django.test import TestCase +from unittest.mock import patch + +from fl_server_core.tests.dummy import Dummy + +from ..notification.training import TrainingRoundStartNotification +from ..trainer.events import DaisyChainRoundFinished, ModelTestFinished, TrainingRoundFinished +from ..trainer.model_trainer import get_trainer, get_trainer_class, FedDCModelTrainer + + +class FedDCTest(TestCase): + + def test_trainer_class(self): + training = Dummy.create_training(options=dict(daisy_chain_period=5)) + trainer_cls = get_trainer_class(training) + self.assertTrue(trainer_cls is FedDCModelTrainer) + + def test_trainer_type(self): + training = Dummy.create_training(options=dict(daisy_chain_period=5)) + trainer = get_trainer(training) + self.assertTrue(type(trainer) is FedDCModelTrainer) + + @patch.object(TrainingRoundStartNotification, "send") + def test_start_dc_round(self, send_method): + training = Dummy.create_training(options=dict(daisy_chain_period=5)) + trainer = get_trainer(training) + trainer.start_round() + self.assertTrue(send_method.called) + send_method.assert_called_once() + + @patch.object(TrainingRoundStartNotification, "send") + def test_start_permuted_dc_round(self, send_method): + N = 10 + participants = [Dummy.create_client() for _ in range(N)] + model = Dummy.create_model(round=2) + [Dummy.create_model_update(base_model=model, owner=participant) for participant in participants] + training = Dummy.create_training( + model=model, + participants=participants, + target_num_updates=model.round - 1, + options=dict(daisy_chain_period=5) + ) + trainer = get_trainer(training) + trainer.start_round() + self.assertTrue(send_method.called) + self.assertEqual(N, send_method.call_count) + + @patch.object(DaisyChainRoundFinished, "handle") + @patch.object(DaisyChainRoundFinished, "next") + def test_handle_round_finished(self, next_fn, handle_fn): + training = Dummy.create_training(options=dict(daisy_chain_period=5)) + trainer = get_trainer(training) + event = TrainingRoundFinished(trainer) + trainer.handle(event) + self.assertTrue(next_fn.called) + next_fn.assert_called_once() + self.assertTrue(handle_fn.called) + handle_fn.assert_called_once() + + @patch.object(TrainingRoundFinished, "handle") + @patch.object(DaisyChainRoundFinished, "next") + def test_handle_round_finished_handle_dc_period(self, next_fn, base_handle_fn): + training = Dummy.create_training(target_num_updates=42, options=dict(daisy_chain_period=5)) + trainer = get_trainer(training) + event = TrainingRoundFinished(trainer) + trainer.handle(event) + self.assertTrue(next_fn.called) + next_fn.assert_called_once() + self.assertFalse(base_handle_fn.called) + + @patch.object(TrainingRoundFinished, "handle") + @patch.object(DaisyChainRoundFinished, "next") + def test_handle_round_finished_handle_trainings_epoch(self, next_fn, base_handle_fn): + training = Dummy.create_training(options=dict(daisy_chain_period=5)) + trainer = get_trainer(training) + event = TrainingRoundFinished(trainer) + trainer.handle(event) + self.assertTrue(next_fn.called) + next_fn.assert_called_once() + self.assertTrue(base_handle_fn.called) + base_handle_fn.assert_called_once() + + @patch.object(ModelTestFinished, "handle") + @patch.object(ModelTestFinished, "next") + def test_handle_test_round_finished(self, next_fn, handle_fn): + training = Dummy.create_training(options=dict(daisy_chain_period=5)) + trainer = get_trainer(training) + event = ModelTestFinished(trainer) + trainer.handle(event) + self.assertTrue(next_fn.called) + next_fn.assert_called_once() + self.assertTrue(handle_fn.called) + handle_fn.assert_called_once() diff --git a/fl_server_ai/tests/test_notification.py b/fl_server_ai/tests/test_notification.py new file mode 100644 index 0000000..b1a0115 --- /dev/null +++ b/fl_server_ai/tests/test_notification.py @@ -0,0 +1,96 @@ +from django.test import TestCase +from requests import Response +import responses +from uuid import UUID, uuid4 + +from fl_server_core.models.training import Training, TrainingState +from fl_server_core.models.user import NotificationReceiver +from fl_server_core.tests.dummy import Dummy + +from ..exceptions import ClientNotificationRejectionException, NotificationException +from ..notification.notification import send_notification +from ..notification.training import TrainingRoundStartNotification, TrainingFinishedNotification + + +class NotificationTest(TestCase): + + DUMMY_MESSAGE_ENDPOINT = "http://example.com/" + + def _create_dummy_notification_receiver( + self, + id: UUID = uuid4(), + message_endpoint: str = DUMMY_MESSAGE_ENDPOINT + ) -> NotificationReceiver: + receiver = NotificationReceiver() + receiver.id = id + receiver.message_endpoint = message_endpoint + return receiver + + def test_send_notification(self): + notification = TrainingFinishedNotification( + receivers=[self._create_dummy_notification_receiver() for _ in range(10)], + body=TrainingFinishedNotification.Body(uuid4()), + training_uuid=uuid4() + ) + with responses.RequestsMock() as mock: + mock.add(responses.POST, NotificationTest.DUMMY_MESSAGE_ENDPOINT) + send_notification(NotificationTest.DUMMY_MESSAGE_ENDPOINT, notification.serialize()) + self.assertEqual(len(mock.calls), 1) + + def test_send_notification_bad(self): + notification = TrainingFinishedNotification( + receivers=[self._create_dummy_notification_receiver(message_endpoint="ooo://example.com/")], + body=TrainingFinishedNotification.Body(uuid4()), + training_uuid=uuid4() + ) + with self.assertLogs(level="WARN"), self.assertRaises(NotificationException) as cm: + send_notification("ooo://example.com/", notification.serialize(), max_retries=0) + self.assertTrue(isinstance(cm.exception.inner_exception, ValueError)) + + def test_make_training_notification_callback_success(self): + user = Dummy.create_client() + training = Dummy.create_training(participants=[user]) + notification = TrainingRoundStartNotification( + receivers=[user], + body=TrainingRoundStartNotification.Body(1, uuid4()), + training_uuid=training.id + ) + with self.assertLogs(logger="fl.celery", level="DEBUG"): + notification.callback_success(user) + + def test_make_training_notification_callback_failure_client_error(self): + user_kaputt = Dummy.create_client() + user_good = Dummy.create_client() + training = Dummy.create_training(participants=[user_kaputt, user_good]) + notification = TrainingRoundStartNotification( + receivers=[user_good, user_kaputt], + body=TrainingRoundStartNotification.Body(1, uuid4()), + training_uuid=training.id + ) + response = Response() + response.status_code = 404 + error = ClientNotificationRejectionException( + response, + NotificationTest.DUMMY_MESSAGE_ENDPOINT, + notification.serialize(), 5, user_kaputt + ) + with self.assertLogs(level="WARN"): + notification.callback_error(error) + + def test_training_round_start_notification_callback_failure_server_error(self): + user = Dummy.create_client() + training = Dummy.create_training() + notification = TrainingRoundStartNotification( + receivers=[user], + body=TrainingRoundStartNotification.Body(1, uuid4()), + training_uuid=training.id + ) + error = NotificationException( + NotificationTest.DUMMY_MESSAGE_ENDPOINT, + notification.serialize(), 5, user, + ValueError("Oops, your LAN-Cable decided to die!") + ) + with self.assertLogs(level="ERROR"): + notification.callback_error(error) + training = Training.objects.get(id=training.id) + self.assertEqual(TrainingState.ERROR, training.state) diff --git a/fl_server_ai/tests/test_uncertainty_ensemble.py b/fl_server_ai/tests/test_uncertainty_ensemble.py new file mode 100644 index 0000000..91805c5 --- /dev/null +++ b/fl_server_ai/tests/test_uncertainty_ensemble.py @@ -0,0 +1,42 @@ +from django.test import TestCase +import pickle +import torch + +from fl_server_core.models.model import GlobalModel, MeanModel +from fl_server_core.models.training import UncertaintyMethod +from fl_server_core.tests.dummy import Dummy + +from ..trainer.model_trainer import get_trainer, get_trainer_class, ModelTrainer +from ..uncertainty import Ensemble + + +class EnsembleTest(TestCase): + + def test_trainer_class(self): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.ENSEMBLE) + trainer_cls = get_trainer_class(training) + self.assertTrue(trainer_cls is ModelTrainer) + + def test_trainer_type(self): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.ENSEMBLE) + trainer = get_trainer(training) + self.assertTrue(type(trainer) is ModelTrainer) + + def test_prediction(self): + layer = torch.nn.Linear(1, 1) + layer.weight = torch.nn.Parameter(torch.tensor([[1.]])) + layer.bias = torch.nn.Parameter(torch.tensor([0.])) + models = [pickle.dumps(torch.nn.Sequential(layer, torch.nn.Tanh())) for _ in range(10)] + models_db = [Dummy.create_model(GlobalModel, weights=model) for model in models] + model = Dummy.create_model(MeanModel) + model.models.set(models_db) + Dummy.create_training( + model=model, + uncertainty_method=UncertaintyMethod.ENSEMBLE + ) + X = torch.tensor([[-4.0], [-2.0], [2.0], [4.0]]) + y = torch.tensor([-1.0, -1.0, 1.0, 1.0]) + logits, uncertainty_dict = Ensemble.prediction(X, model) + torch.testing.assert_close(y, torch.sign(torch.squeeze(logits))) + torch.testing.assert_close(torch.tensor([[0.]] * 4), uncertainty_dict["variance"]) + torch.testing.assert_close(torch.tensor([[0.]] * 4), uncertainty_dict["std"]) diff --git a/fl_server_ai/tests/test_uncertainty_mc.py b/fl_server_ai/tests/test_uncertainty_mc.py new file mode 100644 index 0000000..ce05f9d --- /dev/null +++ b/fl_server_ai/tests/test_uncertainty_mc.py @@ -0,0 +1,46 @@ +from django.test import TestCase +import pickle +import torch + +from fl_server_core.models.model import GlobalModel +from fl_server_core.models.training import UncertaintyMethod +from fl_server_core.tests.dummy import Dummy + +from ..trainer.model_trainer import get_trainer, get_trainer_class, ModelTrainer +from ..uncertainty import MCDropout + + +class MCDropoutTest(TestCase): + + def test_trainer_class(self): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.MC_DROPOUT) + trainer_cls = get_trainer_class(training) + self.assertTrue(trainer_cls is ModelTrainer) + + def test_trainer_type(self): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.MC_DROPOUT) + trainer = get_trainer(training) + self.assertTrue(type(trainer) is ModelTrainer) + + def test_prediction(self): + torch.manual_seed(42) + layer = torch.nn.Linear(1, 1) + layer.weight = torch.nn.Parameter(torch.tensor([[1.]])) + layer.bias = torch.nn.Parameter(torch.tensor([0.])) + model = pickle.dumps(torch.nn.Sequential(layer, torch.nn.Dropout(0.5), torch.nn.Tanh())) + model = Dummy.create_model(GlobalModel, weights=model) + Dummy.create_training( + model=model, + uncertainty_method=UncertaintyMethod.MC_DROPOUT + ) + X = torch.tensor([[-4.0], [-2.0], [2.0], [4.0]]) + y = torch.tensor([-1.0, -1.0, 1.0, 1.0]) + logits, uncertainty_dict = MCDropout.prediction(X, model) + torch.testing.assert_close(y, torch.sign(torch.squeeze(logits))) + torch.testing.assert_close(torch.tensor([[0.2667], [0.2330], [0.2663], [0.2333]]), + uncertainty_dict["variance"], atol=1e-4, rtol=0.001) + torch.testing.assert_close(torch.tensor([[0.5164], [0.4827], [0.5161], [0.4830]]), + uncertainty_dict["std"], atol=1e-4, rtol=0.001) + self.assertFalse("predictive_entropy" in uncertainty_dict) + self.assertFalse("expected_entropy" in uncertainty_dict) + self.assertFalse("mutual_info" in uncertainty_dict) diff --git a/fl_server_ai/tests/test_uncertainty_swag.py b/fl_server_ai/tests/test_uncertainty_swag.py new file mode 100644 index 0000000..0f8f2b5 --- /dev/null +++ b/fl_server_ai/tests/test_uncertainty_swag.py @@ -0,0 +1,77 @@ +from django.test import TestCase +import pickle +import torch +from unittest.mock import patch + +from fl_server_core.models.model import SWAGModel +from fl_server_core.models.training import TrainingState, UncertaintyMethod +from fl_server_core.tests.dummy import Dummy + +from ..notification.training import TrainingSWAGRoundStartNotification +from ..trainer.events import SWAGRoundFinished, TrainingRoundFinished +from ..trainer.model_trainer import get_trainer, get_trainer_class, SWAGModelTrainer +from ..uncertainty import SWAG + + +class SwagTest(TestCase): + + def test_trainer_class(self): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.SWAG) + trainer_cls = get_trainer_class(training) + self.assertTrue(trainer_cls is SWAGModelTrainer) + + def test_trainer_type(self): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.SWAG) + trainer = get_trainer(training) + self.assertTrue(type(trainer) is SWAGModelTrainer) + + @patch.object(TrainingSWAGRoundStartNotification, "send") + def test_start_swag_round(self, send_method): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.SWAG) + trainer = get_trainer(training) + assert type(trainer) is SWAGModelTrainer + trainer.start_swag_round() + self.assertEqual(TrainingState.SWAG_ROUND, training.state) + self.assertTrue(send_method.called) + + @patch.object(TrainingRoundFinished, "handle") + @patch.object(TrainingRoundFinished, "next") + @patch.object(TrainingSWAGRoundStartNotification, "send") + def test_start_swag_round_via_handle(self, send_method, next_method, handle_method): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.SWAG) + trainer = get_trainer(training) + assert type(trainer) is SWAGModelTrainer + event = TrainingRoundFinished(trainer) + trainer.handle(event) + self.assertEqual(TrainingState.SWAG_ROUND, training.state) + self.assertTrue(handle_method.called) + self.assertFalse(next_method.called) + self.assertTrue(send_method.called) + + @patch.object(SWAGRoundFinished, "handle") + @patch.object(TrainingRoundFinished, "next") + def test_handle_swag_round_finished(self, base_cls_next_method, handle_method): + training = Dummy.create_training(uncertainty_method=UncertaintyMethod.SWAG) + trainer = get_trainer(training) + assert type(trainer) is SWAGModelTrainer + event = SWAGRoundFinished(trainer) + trainer.handle(event) + self.assertEqual(TrainingState.ONGOING, training.state) + self.assertTrue(handle_method.called) + self.assertTrue(base_cls_next_method.called) + + def test_prediction(self): + model = pickle.dumps(torch.nn.Sequential(torch.nn.Linear(1, 1), torch.nn.Tanh())) + first_moment = pickle.dumps(torch.tensor([1.0, 0.0])) + second_moment = pickle.dumps(torch.tensor([1.0, 0.0])) + model = Dummy.create_model(SWAGModel, weights=model, swag_first_moment=first_moment, + swag_second_moment=second_moment) + Dummy.create_training( + model=model, + uncertainty_method=UncertaintyMethod.SWAG, + options=dict(uncertainty={"N": 10}) + ) + X = torch.tensor([[-4.0], [-2.0], [2.0], [4.0]]) + y = torch.tensor([-1.0, -1.0, 1.0, 1.0]) + logits, _ = SWAG.prediction(X, model) + torch.testing.assert_close(y, torch.sign(torch.squeeze(logits))) diff --git a/fl_server_ai/trainer/__init__.py b/fl_server_ai/trainer/__init__.py new file mode 100644 index 0000000..6af84cc --- /dev/null +++ b/fl_server_ai/trainer/__init__.py @@ -0,0 +1,5 @@ +from .model_trainer import ModelTrainer +from .options import TrainerOptions +from .tasks import process_trainer_task + +__all__ = ["ModelTrainer", "process_trainer_task", "TrainerOptions"] diff --git a/fl_server_ai/trainer/events/__init__.py b/fl_server_ai/trainer/events/__init__.py new file mode 100644 index 0000000..fdca7ca --- /dev/null +++ b/fl_server_ai/trainer/events/__init__.py @@ -0,0 +1,14 @@ +from .base import ModelTrainerEvent +from .daisy_chain_round_finished import DaisyChainRoundFinished +from .model_test_finished import ModelTestFinished +from .swag_round_finished import SWAGRoundFinished +from .training_round_finished import TrainingRoundFinished + + +__all__ = [ + "ModelTrainerEvent", + "DaisyChainRoundFinished", + "ModelTestFinished", + "SWAGRoundFinished", + "TrainingRoundFinished", +] diff --git a/fl_server_ai/trainer/events/base.py b/fl_server_ai/trainer/events/base.py new file mode 100644 index 0000000..fdb7352 --- /dev/null +++ b/fl_server_ai/trainer/events/base.py @@ -0,0 +1,22 @@ +from abc import ABC, abstractmethod +from logging import getLogger + +from .. import model_trainer + + +class ModelTrainerEvent(ABC): + + _logger = getLogger("fl.server") + + def __init__(self, trainer: "model_trainer.ModelTrainer"): + super().__init__() + self.trainer = trainer + self.training = trainer.training + + @abstractmethod + def handle(self): + pass + + @abstractmethod + def next(self): + pass diff --git a/fl_server_ai/trainer/events/daisy_chain_round_finished.py b/fl_server_ai/trainer/events/daisy_chain_round_finished.py new file mode 100644 index 0000000..b164b84 --- /dev/null +++ b/fl_server_ai/trainer/events/daisy_chain_round_finished.py @@ -0,0 +1,23 @@ +from .training_round_finished import TrainingRoundFinished +from .. import model_trainer + + +class DaisyChainRoundFinished(TrainingRoundFinished): + + def __init__(self, trainer: "model_trainer.ModelTrainer"): + super().__init__(trainer) + self.trainer.options.model_test_after_each_round = False + + def handle(self): + # the round increment is not done yet, therefore `model.round + 1` + if (self.training.model.round + 1) >= self.training.target_num_updates: + # local client training is finished, let's do the aggregation + super().handle() # also does the round increment + return + + # local client training is not finished yet, but we reach a daisy chaining period + # => no aggregation, just send the permutated client models back for further training + # also see `FedDCModelTrainer.handle()` + + self.training.model.round += 1 + self.training.model.save() diff --git a/fl_server_ai/trainer/events/model_test_finished.py b/fl_server_ai/trainer/events/model_test_finished.py new file mode 100644 index 0000000..eaf5d27 --- /dev/null +++ b/fl_server_ai/trainer/events/model_test_finished.py @@ -0,0 +1,15 @@ +from .base import ModelTrainerEvent + + +class ModelTestFinished(ModelTrainerEvent): + + def next(self): + if self.training.model.round < self.training.target_num_updates: + self.trainer.start_round() + else: + self.trainer.finish() + + def handle(self): + # currently do nothing + # Potentially, one could aggregate all common metrics here. + pass diff --git a/fl_server_ai/trainer/events/swag_round_finished.py b/fl_server_ai/trainer/events/swag_round_finished.py new file mode 100644 index 0000000..3b1d723 --- /dev/null +++ b/fl_server_ai/trainer/events/swag_round_finished.py @@ -0,0 +1,78 @@ +from django.db.models.query import QuerySet +import torch +from typing import List + +from fl_server_core.models import Metric +from fl_server_core.models.training import TrainingState + +from ...exceptions import AggregationException +from .training_round_finished import TrainingRoundFinished + + +class SWAGRoundFinished(TrainingRoundFinished): + + def next(self): + self.training.state = TrainingState.ONGOING + self.training.save() + super().next() + + def handle(self): + # collect metric value + swag_fst = [m.to_torch() for m in self._get_metric("SWAG First Moment Local")] + swag_snd = [m.to_torch() for m in self._get_metric("SWAG Second Moment Local")] + sample_sizes = [m.value_float for m in self._get_metric("SWAG Sample Size Local")] + n_participants = self.training.participants.count() + + # validate + self._validate_swag(swag_fst, swag_snd, sample_sizes, n_participants) + self._logger.info( + f"Training {self.training.id}: Doing SWAG aggregation as all {n_participants} updates arrived" + ) + + # SWAG aggregation and save + self.training.model.first_moment = self._aggregate_param_vectors(swag_fst, sample_sizes) + self.training.model.second_moment = self._aggregate_param_vectors(swag_snd, sample_sizes) + self.training.model.save() + self._logger.info(f"SWAG completed for training {self.training.id}") + + def _get_metric(self, key: str) -> QuerySet[Metric]: + return Metric.objects.filter( + model=self.training.model, + step=self.training.model.round, + key=key + ) + + def _validate_swag( + self, + swag_fst: List[torch.Tensor], + swag_snd: List[torch.Tensor], + sample_sizes: List[int], + n_participants: int + ): + if len(swag_fst) != len(swag_snd) != len(sample_sizes): + self.training.state = TrainingState.ERROR + self.training.save() + raise ValueError("SWAG stats in inconsistent state!") + + if len(swag_fst) != n_participants: + text = f"Aggregation was started, but training {self.training.id}" \ + f"has {len(swag_fst)} updates," \ + f"but {n_participants} clients!" + self._logger.error(text) + raise RuntimeError(text) + + @torch.no_grad() + def _aggregate_param_vectors( + self, + param_vectors: List[torch.Tensor], + sample_sizes: List[int] + ) -> torch.Tensor: + if not all(map(lambda v: len(v) == len(param_vectors[0]), param_vectors[1:])): + raise AggregationException("Models do not have the same number of parameters!") + if len(param_vectors) != len(sample_sizes): + raise RuntimeError("len(sample_sizes) != len(param_vectors)") + + factors = torch.tensor([s / sum(sample_sizes) for s in sample_sizes]) + result = torch.stack(param_vectors) * factors[:, None] + result = torch.sum(result, dim=0) + return result diff --git a/fl_server_ai/trainer/events/training_round_finished.py b/fl_server_ai/trainer/events/training_round_finished.py new file mode 100644 index 0000000..3171ef6 --- /dev/null +++ b/fl_server_ai/trainer/events/training_round_finished.py @@ -0,0 +1,75 @@ +from typing import List + +from fl_server_core.models import LocalModel + +from ...aggregation import get_aggregation_class + +from .base import ModelTrainerEvent +from .model_test_finished import ModelTestFinished + + +class TrainingRoundFinished(ModelTrainerEvent): + """ + After a trainings round is finised. + + This event should only be triggered when all model updates (local models) + that are to participate in the aggregation have arrived. + """ + + def next(self): + tests_enabled = not self.trainer.options.skip_model_tests + if tests_enabled and self.trainer.options.model_test_after_each_round: + self.trainer.test_round() + elif tests_enabled and self.training.model.round >= self.training.target_num_updates: + # at least test the final trained model + self.trainer.test_round() + else: + ModelTestFinished(self.trainer).next() + + def handle(self): + """ + Does the following: + - aggregates all model updates (local models) into a new global model + - saves the new global model into the database (i.e. updates/overwrites the weights field of the model) + - increase the round field of the global model by 1 + - deletes the model updates (local models) from the database, if the trainer options do not disagree + + Note: If not enough updates have arrived, the method does nothing. + """ + model_updates = LocalModel.objects.filter(base_model=self.training.model, round=self.training.model.round) + models = [m.get_torch_model() for m in model_updates] + model_sample_sizes = [m.sample_size for m in model_updates] + n_participants = self.training.participants.count() + + # validate + self._validate(models, n_participants) + self._logger.info(f"Training {self.training.id}: Doing aggregation as all {n_participants} updates arrived") + + # do aggregation + aggregation_cls = get_aggregation_class(self.training) + final_model = aggregation_cls().aggregate( + models, + model_sample_sizes, + deepcopy=not self.trainer.options.delete_local_models_after_aggregation + ) + + # write the result back to database and update the trainings round + self.training.model.set_torch_model(final_model) + self.training.model.round += 1 + self.training.model.save() + + # clean local updates + if self.trainer.options.delete_local_models_after_aggregation: + model_updates.delete() + + def _validate(self, models: List, n_participants: int): + if not models: + text = f"Aggregation was run for training {self.training.id} but no model updates were in db!" + self._logger.error(text) + raise RuntimeError(text) + + if len(models) != n_participants: + text = f"Aggregation was started, but training {self.training.id} has {len(models)} updates," \ + f"but {n_participants} clients!" + self._logger.error(text) + raise RuntimeError(text) diff --git a/fl_server_ai/trainer/model_trainer.py b/fl_server_ai/trainer/model_trainer.py new file mode 100644 index 0000000..9aadeea --- /dev/null +++ b/fl_server_ai/trainer/model_trainer.py @@ -0,0 +1,117 @@ +from random import shuffle +from typing import Optional, Type + +from fl_server_core.models.model import LocalModel +from fl_server_core.models.training import Training, TrainingState, UncertaintyMethod +from fl_server_ai.notification.training import ( + TrainingFinishedNotification, + TrainingModelTestNotification, + TrainingRoundStartNotification, + TrainingStartNotification, + TrainingSWAGRoundStartNotification, +) + +from .events import ModelTrainerEvent, DaisyChainRoundFinished, TrainingRoundFinished +from .options import TrainerOptions + + +def get_trainer_class(training: Training) -> Type["ModelTrainer"]: + if training.uncertainty_method == UncertaintyMethod.SWAG: + return SWAGModelTrainer + if training.options.get("daisy_chain_period", 0) > 0: + return FedDCModelTrainer + return ModelTrainer + + +def get_trainer(training: Training, options: Optional[TrainerOptions] = None) -> "ModelTrainer": + return get_trainer_class(training)(training, options) + + +class ModelTrainer: + + def __new__(cls, training: Training, options: Optional[TrainerOptions] = None) -> "ModelTrainer": + return super().__new__(cls.get_trainer_class(training)) + + @classmethod + def get_trainer_class(cls, training: Training) -> Type["ModelTrainer"]: + return get_trainer_class(training) + + def __init__(self, training: Training, options: Optional[TrainerOptions] = None): + super().__init__() + self.training = training + self.options = options if options else TrainerOptions() + + def start(self): + self.training.state = TrainingState.ONGOING + self.training.save() + TrainingStartNotification.from_training(self.training).send() + TrainingRoundStartNotification.from_training(self.training).send() + + def finish(self): + self.training.state = TrainingState.COMPLETED + self.training.save() + TrainingFinishedNotification.from_training(self.training).send() + + def start_round(self): + TrainingRoundStartNotification.from_training(self.training).send() + + def test_round(self): + TrainingModelTestNotification.from_training(self.training).send() + + def handle(self, event: ModelTrainerEvent): + event.handle() + event.next() + + def handle_cls(self, event_cls: Type[ModelTrainerEvent]): + self.handle(event_cls(self)) + + +class SWAGModelTrainer(ModelTrainer): + + def start_swag_round(self): + self.training.state = TrainingState.SWAG_ROUND + self.training.save() + TrainingSWAGRoundStartNotification.from_training(self.training).send() + + def handle(self, event: ModelTrainerEvent): + event.handle() + if type(event) is TrainingRoundFinished: + self.start_swag_round() + else: + event.next() + + +class FedDCModelTrainer(ModelTrainer): + + def start_round(self): + dc_period = self.training.options.get("daisy_chain_period", 0) + if dc_period < 1 or self.training.model.round % dc_period == 0: + # start training round, first (local) training round, therefore no local models to permute + TrainingRoundStartNotification.from_training(self.training).send() + return + + # daily chaining period, therefore send the permutated client models back for further training + clients = self.training.participants.all() + model_ids = list(LocalModel.objects.filter( + base_model=self.training.model, + round=self.training.model.round - 1 + ).values_list("pk", flat=True)) + shuffle(model_ids) + for client, model_id in zip(clients, model_ids): + TrainingRoundStartNotification( + receivers=[client], + body=TrainingRoundStartNotification.Body( + round=self.training.model.round, + global_model_uuid=model_id + ), + training_uuid=self.training.id + ).send() + + def handle(self, event: ModelTrainerEvent): + if type(event) is TrainingRoundFinished: + real_event = DaisyChainRoundFinished(self) + real_event.handle() + real_event.next() + else: + event.handle() + event.next() diff --git a/fl_server_ai/trainer/options.py b/fl_server_ai/trainer/options.py new file mode 100644 index 0000000..da6c9b4 --- /dev/null +++ b/fl_server_ai/trainer/options.py @@ -0,0 +1,8 @@ +from dataclasses import dataclass + + +@dataclass +class TrainerOptions: + skip_model_tests: bool = False + model_test_after_each_round: bool = True + delete_local_models_after_aggregation: bool = True diff --git a/fl_server_ai/trainer/tasks.py b/fl_server_ai/trainer/tasks.py new file mode 100644 index 0000000..60d290b --- /dev/null +++ b/fl_server_ai/trainer/tasks.py @@ -0,0 +1,53 @@ +from celery.utils.log import get_task_logger +from django.db import transaction, DatabaseError +from logging import getLogger +from traceback import format_exception +from typing import Type +from uuid import UUID + +from fl_server_core.models import Training + +from ..celery_tasks import app + +from .events import ModelTrainerEvent +from .model_trainer import ModelTrainer + + +@app.task(bind=False, ignore_result=False) +def process_trainer_task(training_uuid: UUID, event_cls: Type[ModelTrainerEvent]): + logger = get_task_logger("fl.celery") + try: + training = Training.objects.get(id=training_uuid) + ModelTrainer(training).handle_cls(event_cls) + except Exception as e: + error_msg = f"Exception occurred for training {training_uuid}: {e}" + logger.error(error_msg) + logger.debug(error_msg + "\n" + "".join(format_exception(e))) + raise e + finally: + logger.info(f"Unlocking training {training_uuid}") + if training: + training = Training.objects.get(id=training_uuid) + training.locked = False + training.save() + + +def dispatch_trainer_task(training: Training, event_cls: Type[ModelTrainerEvent], lock_training: bool): + logger = getLogger("fl.server") + if lock_training: + try: + with transaction.atomic(): + training.refresh_from_db() + assert not training.locked + + # set lock and do the aggregation + training.locked = True + training.save() + + logger.debug(f"Locking training {training.id}") + except (DatabaseError, AssertionError): + logger.debug(f"Training {training.id} is locked!") + return + + # start task async + process_trainer_task.s(training_uuid=training.id, event_cls=event_cls).apply_async(retry=False) diff --git a/fl_server_ai/uncertainty/__init__.py b/fl_server_ai/uncertainty/__init__.py new file mode 100644 index 0000000..551c997 --- /dev/null +++ b/fl_server_ai/uncertainty/__init__.py @@ -0,0 +1,16 @@ +from .base import UncertaintyBase +from .ensemble import Ensemble +from .mc_dropout import MCDropout +from .method import get_uncertainty_class +from .none import NoneUncertainty +from .swag import SWAG + + +__all__ = [ + "get_uncertainty_class", + "Ensemble", + "MCDropout", + "NoneUncertainty", + "SWAG", + "UncertaintyBase", +] diff --git a/fl_server_ai/uncertainty/base.py b/fl_server_ai/uncertainty/base.py new file mode 100644 index 0000000..f7745b2 --- /dev/null +++ b/fl_server_ai/uncertainty/base.py @@ -0,0 +1,114 @@ +from abc import ABC, abstractmethod +import json +from logging import getLogger +import numpy as np +import torch +from typing import Any, Dict, Tuple + +from fl_server_core.models import Model, Training + + +class UncertaintyBase(ABC): + _logger = getLogger("fl.server") + + @classmethod + @abstractmethod + def prediction(cls, input: torch.Tensor, model: Model) -> Tuple[torch.Tensor, Dict[str, Any]]: + pass + + @classmethod + def interpret(cls, outputs: torch.Tensor) -> Dict[str, Any]: + """ + Interpret the different network (model) outputs and calculate the uncertainty. + + Args: + outputs (torch.Tensor): multiple network (model) outputs (N, batch_size, n_classes) + + Return: + Tuple[torch.Tensor, Dict[str, Any]]: inference and uncertainty + """ + variance = outputs.var(dim=0) + std = outputs.std(dim=0) + if not (torch.all(outputs <= 1.) and torch.all(outputs >= 0.)): + return dict(variance=variance, std=std) + + predictive_entropy = cls.predictive_entropy(outputs) + expected_entropy = cls.expected_entropy(outputs) + mutual_info = predictive_entropy - expected_entropy # see cls.mutual_information + return dict( + variance=variance, + std=std, + predictive_entropy=predictive_entropy, + expected_entropy=expected_entropy, + mutual_info=mutual_info, + ) + + @classmethod + def expected_entropy(cls, predictions: torch.Tensor) -> torch.Tensor: + """ + Calculate the mean entropy of the predictive distribution across the MC samples. + + Args: + predictions (torch.Tensor): predictions of shape (n_mc x batch_size x n_classes) + + Returns: + torch.Tensor: mean entropy of the predictive distribution + """ + return torch.distributions.Categorical(probs=predictions).entropy().mean(dim=0) + + @classmethod + def predictive_entropy(cls, predictions: torch.Tensor) -> torch.Tensor: + """ + Calculate the entropy of the mean predictive distribution across the MC samples. + + Args: + predictions (torch.Tensor): predictions of shape (n_mc x batch_size x n_classes) + + Returns: + torch.Tensor: entropy of the mean predictive distribution + """ + return torch.distributions.Categorical(probs=predictions.mean(dim=0)).entropy() + + @classmethod + def mutual_information(cls, predictions: torch.Tensor) -> torch.Tensor: + """ + Calculate the BALD (Bayesian Active Learning by Disagreement) of a model; + the difference between the mean of the entropy and the entropy of the mean + of the predicted distribution on the predictions. + This method is also sometimes referred to as the mutual information (MI). + + Args: + predictions (torch.Tensor): predictions of shape (n_mc x batch_size x n_classes) + + Returns: + torch.Tensor: difference between the mean of the entropy and the entropy of the mean + of the predicted distribution + """ + return cls.predictive_entropy(predictions) - cls.expected_entropy(predictions) + + @classmethod + def get_options(cls, obj: Model | Training) -> Dict[str, Any]: + if isinstance(obj, Model): + return Training.objects.filter(model=obj) \ + .values("options") \ + .first()["options"] \ + .get("uncertainty", {}) + if isinstance(obj, Training): + return obj.options.get("uncertainty", {}) + raise TypeError(f"Expected Model or Training, got {type(obj)}") + + @classmethod + def to_json(cls, inference: torch.Tensor, uncertainty: Dict[str, Any] = {}, **json_kwargs) -> str: + def prepare(v): + if isinstance(v, torch.Tensor): + return v.cpu().tolist() + if isinstance(v, np.ndarray): # cspell:ignore ndarray + return v.tolist() + if isinstance(v, dict): + return {k: prepare(_v) for k, _v in v.items()} + return v + + return json.dumps({ + "inference": inference.tolist(), + "uncertainty": prepare(uncertainty) if uncertainty else {}, + }, **json_kwargs) diff --git a/fl_server_ai/uncertainty/ensemble.py b/fl_server_ai/uncertainty/ensemble.py new file mode 100644 index 0000000..15327b5 --- /dev/null +++ b/fl_server_ai/uncertainty/ensemble.py @@ -0,0 +1,22 @@ +import torch +from typing import Any, Dict, Tuple + +from fl_server_core.models import MeanModel + +from .base import UncertaintyBase + + +class Ensemble(UncertaintyBase): + + @classmethod + def prediction(cls, input: torch.Tensor, model: MeanModel) -> Tuple[torch.Tensor, Dict[str, Any]]: + output_list = [] + for m in model.models.all(): + net = m.get_torch_model() + output = net(input).detach() + output_list.append(output) + outputs = torch.stack(output_list, dim=0) # (N, batch_size, n_classes) # N = number of models + + inference = outputs.mean(dim=0) + uncertainty = cls.interpret(outputs) + return inference, uncertainty diff --git a/fl_server_ai/uncertainty/mc_dropout.py b/fl_server_ai/uncertainty/mc_dropout.py new file mode 100644 index 0000000..4dbf4f3 --- /dev/null +++ b/fl_server_ai/uncertainty/mc_dropout.py @@ -0,0 +1,62 @@ +import torch +from torch import Tensor +from torch.nn import Module +from torch.nn.modules.dropout import _DropoutNd +from typing import Any, Dict, Tuple + +from fl_server_core.models import Model + +from .base import UncertaintyBase + + +def set_dropout(model: Module, state: bool = True): + """ + Set the state of the dropout layers to enable or disable them even during inference. + + Args: + model (Module): PyTorch module + state (bool, optional): Enable or disable dropout layers. Defaults to True. + """ + for m in model.modules(): + if isinstance(m, _DropoutNd) or m.__class__.__name__.lower().__contains__("dropout"): + m.train(mode=state) + + +class MCDropout(UncertaintyBase): + """ + Monte Carlo (MC) Dropout Uncertainty Estimation + + Requirements: + + - model with dropout layers + - T, number of samples per input (number of monte-carlo samples/forward passes) + + References: + + - Paper: Understanding Measures of Uncertainty for Adversarial Example Detection + + - Code inspiration: + """ + + @classmethod + def prediction(cls, input: Tensor, model: Model) -> Tuple[torch.Tensor, Dict[str, Any]]: + options = cls.get_options(model) + N = options.get("N", 10) + softmax = options.get("softmax", False) + + net: Module = model.get_torch_model() + net.eval() + set_dropout(net, state=True) + + out_list = [] + for _ in range(N): + output = net(input).detach() + # convert to probabilities if necessary + if softmax: + output = torch.softmax(output, dim=1) + out_list.append(output) + out = torch.stack(out_list, dim=0) # (n_mc, batch_size, n_classes) + + inference = out.mean(dim=0) + uncertainty = cls.interpret(out) + return inference, uncertainty diff --git a/fl_server_ai/uncertainty/method.py b/fl_server_ai/uncertainty/method.py new file mode 100644 index 0000000..789d41a --- /dev/null +++ b/fl_server_ai/uncertainty/method.py @@ -0,0 +1,43 @@ +from typing import overload, Type + +from fl_server_core.models import Model, Training +from fl_server_core.models.training import UncertaintyMethod + +from .base import UncertaintyBase +from .ensemble import Ensemble +from .mc_dropout import MCDropout +from .none import NoneUncertainty +from .swag import SWAG + + +@overload +def get_uncertainty_class(value: Model) -> Type[UncertaintyBase]: ... + + +@overload +def get_uncertainty_class(value: Training) -> Type[UncertaintyBase]: ... + + +@overload +def get_uncertainty_class(value: UncertaintyMethod) -> Type[UncertaintyBase]: ... + + +def get_uncertainty_class(value: Model | Training | UncertaintyMethod) -> Type[UncertaintyBase]: + if isinstance(value, UncertaintyMethod): + method = value + elif isinstance(value, Training): + method = value.uncertainty_method + elif isinstance(value, Model): + uncertainty_method = Training.objects.filter(model=value) \ + .values("uncertainty_method") \ + .first()["uncertainty_method"] + method = uncertainty_method + else: + raise ValueError(f"Unknown type: {type(value)}") + + match method: + case UncertaintyMethod.ENSEMBLE: return Ensemble + case UncertaintyMethod.MC_DROPOUT: return MCDropout + case UncertaintyMethod.NONE: return NoneUncertainty + case UncertaintyMethod.SWAG: return SWAG + case _: raise ValueError(f"Unknown uncertainty method: {method}") diff --git a/fl_server_ai/uncertainty/none.py b/fl_server_ai/uncertainty/none.py new file mode 100644 index 0000000..3f89a08 --- /dev/null +++ b/fl_server_ai/uncertainty/none.py @@ -0,0 +1,15 @@ +import torch +from typing import Any, Dict, Tuple + +from fl_server_core.models import Model + +from .base import UncertaintyBase + + +class NoneUncertainty(UncertaintyBase): + + @classmethod + def prediction(cls, input: torch.Tensor, model: Model) -> Tuple[torch.Tensor, Dict[str, Any]]: + net: torch.nn.Module = model.get_torch_model() + prediction: torch.Tensor = net(input) + return prediction.argmax(dim=1), {} diff --git a/fl_server_ai/uncertainty/swag.py b/fl_server_ai/uncertainty/swag.py new file mode 100644 index 0000000..6063141 --- /dev/null +++ b/fl_server_ai/uncertainty/swag.py @@ -0,0 +1,37 @@ +import torch +from typing import Any, Dict, Tuple + +from fl_server_core.models import SWAGModel + +from .base import UncertaintyBase + + +class SWAG(UncertaintyBase): + """ + Stochastic weight averaging Gaussian + """ + + @classmethod + def prediction(cls, input: torch.Tensor, model: SWAGModel) -> Tuple[torch.Tensor, Dict[str, Any]]: + options = cls.get_options(model) + N = options.get("N", 10) + + net: torch.nn.Module = model.get_torch_model() + + # first and second moment are already ensured to be in + # alphabetical order in the database + fm = model.first_moment + sm = model.second_moment + std = sm - torch.pow(fm, 2) + params = torch.normal(mean=fm[None, :], std=std).expand(N, -1) + + prediction_list = [] + for n in range(N): + torch.nn.utils.vector_to_parameters(params[n], net.parameters()) + prediction = net(input) + prediction_list.append(prediction) + predictions = torch.stack(prediction_list) + + inference = predictions.mean(dim=0) + uncertainty = cls.interpret(predictions) + return inference, uncertainty diff --git a/fl_server_api/__init__.py b/fl_server_api/__init__.py new file mode 100644 index 0000000..297fd45 --- /dev/null +++ b/fl_server_api/__init__.py @@ -0,0 +1,3 @@ +""" +Federated Learning API +""" diff --git a/fl_server_api/apps.py b/fl_server_api/apps.py new file mode 100644 index 0000000..596ddd5 --- /dev/null +++ b/fl_server_api/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class FlServerApiConfig(AppConfig): + name = "fl_server_api" + verbose_name = "Federated Learning Demonstrator API" diff --git a/fl_server_api/openapi.py b/fl_server_api/openapi.py new file mode 100644 index 0000000..6eb0f19 --- /dev/null +++ b/fl_server_api/openapi.py @@ -0,0 +1,96 @@ +from docstring_parser import Docstring, parse, RenderingStyle +from docstring_parser.google import compose +from drf_spectacular.authentication import BasicScheme +from drf_spectacular.openapi import AutoSchema +from drf_spectacular.utils import OpenApiExample, OpenApiResponse +from inspect import cleandoc +from typing import Callable, List, Optional, Tuple + +from .serializers.generic import ErrorSerializer +from .utils import fullname + + +class BasicAuthAllowingTokenAuthInUrlScheme(BasicScheme): + target_class = "fl_server_api.views.base.BasicAuthAllowingTokenAuthInUrl" + priority = 0 + + +def create_error_response( + response_description: Optional[str], + example_name: str, + example_details: str, + example_description: Optional[str], + **example_kwargs +) -> OpenApiResponse: + return OpenApiResponse( + response=ErrorSerializer, + description=response_description, + examples=[ + OpenApiExample( + example_name, + value={"details": example_details}, + description=example_description, + **example_kwargs, + ) + ] + ) + + +error_response_403 = create_error_response( + "Unauthorized", + "Unauthorized", + "Authentication credentials were not provided.", + "Do not forget to authorize first!" +) + + +def custom_preprocessing_hook(endpoints: List[Tuple[str, str, str, Callable]]): + # your modifications to the list of operations that are exposed in the schema + # for (path, path_regex, method, callback) in endpoints: + # pass + return filter(lambda endpoint: endpoint[0] != "/api/dummy/", endpoints) + + +class CustomAutoSchema(AutoSchema): + + show_examples = True + rendering_style = RenderingStyle.CLEAN + + def _get_docstring(self): + return parse(super().get_description()) + + def _get_param_docstring(self, docstring: Docstring, argument: str) -> Optional[str]: + params = [p for p in docstring.params if p.arg_name == argument] + if not params: + return None + return params[0].description + + def get_description(self): + docstring = self._get_docstring() + tmp_docstring = Docstring(style=docstring.style) + tmp_docstring.short_description = docstring.short_description + tmp_docstring.long_description = docstring.long_description + if self.show_examples: + tmp_docstring.meta.extend(docstring.examples) + desc = compose(tmp_docstring, self.rendering_style, indent="") + if self.show_examples and desc.__contains__("Examples:"): + # customize examples section: + # - examples should be in a new paragraph (not concatenated with the description) + # - the examples header should be a h3 title + desc = desc.replace("\nExamples:\n", "\n\n### Examples:\n\n") + desc = cleandoc(desc) + return desc + + def _resolve_path_parameters(self, variables: List[str]): + parameters = super()._resolve_path_parameters(variables) + docstring = self._get_docstring() + for parameter in parameters: + if "description" not in parameter: + description = self._get_param_docstring(docstring, parameter["name"]) + if description: + parameter["description"] = description + return parameters + + def get_operation_id(self): + action_or_method = getattr(self.view, getattr(self.view, 'action', self.method.lower()), None) + return fullname(action_or_method or self.view.__class__) diff --git a/fl_server_api/serializers/__init__.py b/fl_server_api/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fl_server_api/serializers/generic.py b/fl_server_api/serializers/generic.py new file mode 100644 index 0000000..83ec1e6 --- /dev/null +++ b/fl_server_api/serializers/generic.py @@ -0,0 +1,41 @@ +from django.contrib.auth.models import Group +from django.db import models +from rest_framework import serializers +from typing import List, Optional, Type + +from fl_server_core.models import ( + Metric, + Training, +) + + +class ErrorSerializer(serializers.Serializer): + detail = serializers.CharField() + + +def _create_generic_serializer( + cls: Type[models.Model], + selected_fields: Optional[List[str]] = None +) -> Type[serializers.ModelSerializer]: + """ + Create a generic database model serializer. + + Args: + cls (Type[models.Model]): database model + selected_fields (Optional[List[str]], optional): model fields to serialize. + If `None` serialize all model fields. Defaults to `None`. + + Returns: + Type[serializers.ModelSerializer]: model serializer + """ + class GenericSerializer(serializers.ModelSerializer): + class Meta: + model = cls + fields = selected_fields if selected_fields else serializers.ALL_FIELDS + extra_kwargs = {"id": {"read_only": True}} + return type(f"{cls.__name__}Serializer", (GenericSerializer, ), {}) + + +TrainingSerializer: Type[serializers.ModelSerializer] = _create_generic_serializer(Training) +MetricSerializer: Type[serializers.ModelSerializer] = _create_generic_serializer(Metric) +GroupSerializer: Type[serializers.ModelSerializer] = _create_generic_serializer(Group, ["id", "name"]) diff --git a/fl_server_api/serializers/model.py b/fl_server_api/serializers/model.py new file mode 100644 index 0000000..ea47302 --- /dev/null +++ b/fl_server_api/serializers/model.py @@ -0,0 +1,172 @@ +from django.http import HttpRequest +from logging import getLogger +from rest_framework import serializers +from typing import Any, Dict, Optional, Tuple, Type + +from fl_server_core.models import ( + GlobalModel, + LocalModel, + MeanModel, + Model, + SWAGModel, +) +from fl_server_core.models.model import TModel + +from ..utils import get_file + + +def _create_model_serializer(cls: Type[TModel], *, name: Optional[str] = None) -> Type[serializers.ModelSerializer]: + """ + Create a generic Model serializer. + + Args: + cls (Type[TModel]): database Model model + name (Optional[str], optional): serializer name. Defaults to `None`. + + Returns: + Type[serializers.ModelSerializer]: Model model serializer + """ + class ModelSerializer(serializers.ModelSerializer): + + class Meta: + model = cls + exclude = ["polymorphic_ctype"] + + def to_representation(self, instance): + # only return the whole model (weights) if requested + data = serializers.ModelSerializer.to_representation(self, instance) + if not self.context.get("with-weights", False): + del data["weights"] + return data + + return type(name or f"{cls.__name__}Serializer", (ModelSerializer, ), {}) + + +GlobalModelSerializer = _create_model_serializer(GlobalModel) +LocalModelSerializer = _create_model_serializer(LocalModel) +ModelFallbackSerializer = _create_model_serializer(Model, name="ModelFallbackSerializer") + +MeanModelSerializer = _create_model_serializer(MeanModel) +SWAGModelSerializer = _create_model_serializer(SWAGModel) + + +class ModelSerializer(serializers.ModelSerializer): + + class Meta: + model = Model + exclude = ["polymorphic_ctype"] + + @classmethod + def get_serializer(cls, model: Type[Model]): + if model == GlobalModel: + return GlobalModelSerializer + if model == LocalModel: + return LocalModelSerializer + if model == MeanModel: + return MeanModelSerializer + if model == SWAGModel: + return SWAGModelSerializer + getLogger("fl.server").warning(f"Using fallback model serializer for {model.__name__}") + return ModelFallbackSerializer + + def to_representation(self, instance: Model): + serializer = self.get_serializer(instance.__class__) + return serializer(instance, context=self.context).data + + +class ModelSerializerNoWeights(ModelSerializer): + class Meta: + model = Model + exclude = ["polymorphic_ctype", "weights"] + + +####################################################################################################################### +# POST BODY SERIALIZERS # + + +def load_and_create_model_request(request: HttpRequest) -> Model: + """ + Load and create a model from a Django request. + + Args: + request (HttpRequest): request object + + Returns: + Model: created model + """ + model_cls, data = load_model_request(request) + if model_cls is MeanModel: + sub_models = data.pop("models") + model = model_cls.objects.create(**data) + model.models.set(sub_models) + return model + return model_cls.objects.create(**data) + + +def load_model_request(request: HttpRequest) -> Tuple[Type[Model], Dict[str, Any]]: + """ + Load model data from a Django request. + + Args: + request (HttpRequest): request object + + Returns: + Tuple[Type[Model], Dict[str, Any]]: model class and parsed request data + """ + if request.content_type == "application/json": + data = request.data + else: + # multipart/form-data + data = request.POST.dict() + data["owner"] = request.user + model_type = data.pop("type", "GLOBAL").upper() + + # name and description are required + if "name" not in data: + raise ValueError("Missing required field: name") + if "description" not in data: + raise ValueError("Missing required field: description") + + # round is an optional field (it may not even make sense to be able to set it) + if "round" not in data: + data["round"] = 0 + + if "input_shape" not in data: + data["input_shape"] = "[None]" + + # model_file is required except for MEAN models + if model_type != "MEAN": + data["weights"] = get_file(request, "model_file") + + # MEAN models require a list of model UUIDs + if model_type == "MEAN": + data = _parse_mean_model_models(data) + + # return class type and parsed data + match model_type: + case "SWAG": return SWAGModel, data + case "MEAN": return MeanModel, data + case _: return GlobalModel, data + + +def _parse_mean_model_models(data: Dict[str, Any]) -> Dict[str, Any]: + """ + Parse the models field of a mean model request. + + Args: + data (Dict[str, Any]): request data + + Returns: + Dict[str, Any]: parsed request data + """ + if "models" not in data: + raise ValueError("Missing required field: models") + models = data["models"] + if not isinstance(models, list) or not all([isinstance(m, str) for m in models]): + raise ValueError("Invalid type for field: models") + data["models"] = Model.objects.filter(id__in=models) + if data["models"].count() != len(models): + raise ValueError("Invalid model UUIDs found.") + if not all([m.owner.id == data["owner"].id for m in data["models"]]): + raise ValueError("Invalid model selection. Insufficient model permissions.") + return data diff --git a/fl_server_api/serializers/training.py b/fl_server_api/serializers/training.py new file mode 100644 index 0000000..b060c22 --- /dev/null +++ b/fl_server_api/serializers/training.py @@ -0,0 +1,54 @@ +from dataclasses import dataclass, field +from marshmallow import fields, post_load, Schema +from typing import Any, Dict, List +from uuid import UUID + +from fl_server_core.models.training import AggregationMethod, UncertaintyMethod + + +class CreateTrainingRequestSchema(Schema): + model_id = fields.UUID() + target_num_updates = fields.Integer() + metric_names = fields.List(fields.Str()) + aggregation_method = fields.Enum( + AggregationMethod, + required=True, + dump_default=AggregationMethod.FED_AVG, + by_value=True + ) + uncertainty_method = fields.Enum( + UncertaintyMethod, + required=False, + dump_default=UncertaintyMethod.NONE, + by_value=True + ) + options = fields.Dict(required=False, dump_default={}) + clients = fields.List(fields.UUID(), dump_default=[]) + + @post_load + def _make_create_training_request(self, data: Dict[str, Any], **kwargs): + return CreateTrainingRequest(**data) + + +@dataclass +class CreateTrainingRequest: + model_id: UUID + target_num_updates: int + metric_names: list[str] + aggregation_method: AggregationMethod = field(default=AggregationMethod.FED_AVG) # type: ignore[assignment] + uncertainty_method: UncertaintyMethod = field(default=UncertaintyMethod.NONE) # type: ignore[assignment] + options: Dict[str, Any] = field(default_factory=lambda: {}) + clients: List[UUID] = field(default_factory=lambda: []) + + +class ClientAdministrationBodySchema(Schema): + clients = fields.List(fields.UUID, required=True) + + @post_load + def _make_client_administration_body(self, data: Dict[str, Any], **kwargs): + return ClientAdministrationBody(**data) + + +@dataclass +class ClientAdministrationBody: + clients: list[UUID] diff --git a/fl_server_api/serializers/user.py b/fl_server_api/serializers/user.py new file mode 100644 index 0000000..64c18e1 --- /dev/null +++ b/fl_server_api/serializers/user.py @@ -0,0 +1,41 @@ +from rest_framework import serializers +from rest_framework.authtoken.models import Token + +from fl_server_core.models import User + + +class UserSerializer(serializers.ModelSerializer): + token = serializers.SerializerMethodField() + + class Meta: + model = User + fields = [ + "username", "first_name", "last_name", + "email", "id", "actor", "client", + "message_endpoint", "token", "password", + ] + extra_kwargs = { + "id": {"read_only": True}, + "token": {"read_only": True}, + "password": {"write_only": True}, + } + + def get_token(self, user: User) -> str | None: + # return the user token only if the request user is the same as the requested user + if self.context.get("request_user_id") == user.id: + return Token.objects.get(user=user).key + return "**********" + + def to_representation(self, instance): + # remove the token key from the response if the request user is not the same as + # the requested user since its always empty or "**********" + data = super().to_representation(instance) + if data.get("token") == "**********": + del data["token"] + return data + + def create(self, validated_data): + user = User.objects.create(**validated_data) + user.set_password(validated_data["password"]) + user.save() + return user diff --git a/fl_server_api/tests/__init__.py b/fl_server_api/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fl_server_api/tests/test_dummy.py b/fl_server_api/tests/test_dummy.py new file mode 100644 index 0000000..b620efb --- /dev/null +++ b/fl_server_api/tests/test_dummy.py @@ -0,0 +1,28 @@ +from django.test import TestCase +import json + +from ..views.dummy import DummyView + + +class DummyTests(TestCase): + + def test_create_dummy_metrics_and_models(self): + response = DummyView().create_dummy_metrics_and_models(_request=None) + self.assertEqual(200, response.status_code) + response_json = json.loads(response.content) + self.assertEqual("Created Dummy Data in Metrics Database!", response_json["message"]) + + def test_create_dummy_metrics_and_models_twice(self): + response = DummyView().create_dummy_metrics_and_models(_request=None) + self.assertEqual(200, response.status_code) + response_json = json.loads(response.content) + self.assertEqual("Created Dummy Data in Metrics Database!", response_json["message"]) + # second time + with self.assertLogs("fl.server", level="WARNING") as cm: + response = DummyView().create_dummy_metrics_and_models(_request=None) + self.assertEqual(cm.output, [ + "WARNING:fl.server:Dummy User already exists", + ]) + self.assertEqual(200, response.status_code) + response_json = json.loads(response.content) + self.assertEqual("Created Dummy Data in Metrics Database!", response_json["message"]) diff --git a/fl_server_api/tests/test_group.py b/fl_server_api/tests/test_group.py new file mode 100644 index 0000000..22625dd --- /dev/null +++ b/fl_server_api/tests/test_group.py @@ -0,0 +1,105 @@ +from django.test import TestCase + +from fl_server_core.tests import BASE_URL, Dummy + + +class GroupTests(TestCase): + + def setUp(self): + self.user = Dummy.create_user_and_authenticate(self.client) + + def test_get_all_groups(self): + [Dummy.create_group() for _ in range(10)] + with self.assertLogs("django.request", level="WARNING") as cm: + response = self.client.get(f"{BASE_URL}/groups/") + self.assertEqual(cm.output, [ + "WARNING:django.request:Forbidden: /api/groups/", + ]) + self.assertEqual(403, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual("You are not allowed to access all groups.", response_json["detail"]) + + def test_get_all_groups_as_superuser(self): + self.user.is_superuser = True + self.user.save() + [Dummy.create_group() for _ in range(10)] + response = self.client.get(f"{BASE_URL}/groups/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(10, len(response_json)) + + def test_get_own_group(self): + Dummy.create_group() + group = Dummy.create_group() + Dummy.create_group() + self.user.groups.add(group) + self.user.save() + response = self.client.get(f"{BASE_URL}/groups/{group.id}/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(group.id, response_json["id"]) + + def test_get_other_group(self): + group = Dummy.create_group() + with self.assertLogs("django.request", level="WARNING") as cm: + response = self.client.get(f"{BASE_URL}/groups/{group.id}/") + self.assertEqual(cm.output, [ + f"WARNING:django.request:Forbidden: /api/groups/{group.id}/", + ]) + self.assertEqual(403, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual("You are not allowed to access this group.", response_json["detail"]) + + def test_create_group(self): + group = dict(name="test-group") + response = self.client.post(f"{BASE_URL}/groups/", group) + self.assertEqual(201, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual("test-group", response_json["name"]) + + def test_create_invalid_group(self): + group = dict(hello="test-group") + with self.assertLogs("django.request", level="WARNING") as cm: + response = self.client.post(f"{BASE_URL}/groups/", group) + self.assertEqual(cm.output, [ + "WARNING:django.request:Bad Request: /api/groups/", + ]) + self.assertEqual(400, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual("This field is required.", response_json["name"][0]) + + def test_update_group(self): + group = Dummy.create_group() + self.user.groups.add(group) + self.user.save() + group_update = dict(name="group-name") + response = self.client.put(f"{BASE_URL}/groups/{group.id}/", group_update, content_type="application/json") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(group_update["name"], response_json["name"]) + + def test_update_group_partial(self): + group = Dummy.create_group() + self.user.groups.add(group) + self.user.save() + group_update = dict(name="group-name") + response = self.client.patch(f"{BASE_URL}/groups/{group.id}/", group_update, content_type="application/json") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(group_update["name"], response_json["name"]) + + def test_delete_group(self): + group = Dummy.create_group() + self.user.groups.add(group) + self.user.save() + response = self.client.delete(f"{BASE_URL}/groups/{group.id}/") + self.assertEqual(204, response.status_code) + self.assertEqual(0, len(response.content)) diff --git a/fl_server_api/tests/test_inference.py b/fl_server_api/tests/test_inference.py new file mode 100644 index 0000000..add5be7 --- /dev/null +++ b/fl_server_api/tests/test_inference.py @@ -0,0 +1,140 @@ +from django.core.files.uploadedfile import SimpleUploadedFile +from django.test import TestCase +import json +import pickle +import torch +from uuid import uuid4 + +from fl_server_core.tests import BASE_URL, Dummy + + +class mxb(torch.nn.Module): + def forward(self, x: torch.Tensor) -> torch.Tensor: + return 2*x + 5 + + +class InferenceTests(TestCase): + + def setUp(self): + self.user = Dummy.create_user_and_authenticate(self.client) + + def test_inference_success(self): + inp = pickle.dumps(torch.zeros(3, 3)) + training = Dummy.create_training(actor=self.user) + input_file = SimpleUploadedFile( + "input.pkl", + inp, + content_type="application/octet-stream" + ) + response = self.client.post( + f"{BASE_URL}/inference/", + {"model_id": str(training.model.id), "model_input": input_file} + ) + self.assertEqual(response.status_code, 200) + + results = pickle.loads(response.content) + self.assertEqual({}, results["uncertainty"]) + inference = results["inference"] + self.assertIsNotNone(inference) + results = torch.as_tensor(inference) + self.assertTrue(torch.all(results <= 1)) + self.assertTrue(torch.all(results >= 0)) + + def test_inference_json(self): + inp = torch.zeros(3, 3).tolist() + training = Dummy.create_training(actor=self.user) + response = self.client.post( + f"{BASE_URL}/inference/", + json.dumps({"model_id": str(training.model.id), "model_input": inp}), + content_type="application/json" + ) + self.assertEqual(response.status_code, 200) + response_json = response.json() + self.assertEqual({}, response_json["uncertainty"]) + inference = response_json["inference"] + self.assertIsNotNone(inference) + results = torch.as_tensor(inference) + self.assertTrue(torch.all(results <= 1)) + self.assertTrue(torch.all(results >= 0)) + + def test_inference_with_unknown_content_type(self): + with self.assertLogs("root", level="INFO") as cm: + response = self.client.post( + f"{BASE_URL}/inference/", + {"model_id": "not important", "model_input": "not important"}, + "application/octet-stream" + ) + self.assertEqual(cm.output, [ + "ERROR:fl.server:Unknown Content-Type 'application/octet-stream'", + "WARNING:django.request:Unsupported Media Type: /api/inference/", + ]) + self.assertEqual(response.status_code, 415) + + def test_model_not_exist(self): + inp = pickle.dumps(torch.zeros(3, 3)) + Dummy.create_model() + unused_id = uuid4() + input_file = SimpleUploadedFile( + "input.pkl", + inp, + content_type="application/octet-stream" + ) + with self.assertLogs("root", level="WARNING") as cm: + response = self.client.post( + f"{BASE_URL}/inference/", + {"model_id": unused_id, "model_input": input_file}, + # 'multipart/form-data; boundary=...' is set automatically (default) + ) + self.assertEqual(cm.output, [ + "WARNING:django.request:Bad Request: /api/inference/", + ]) + self.assertEqual(response.status_code, 400) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual(f"Model {unused_id} not found.", response_json["detail"]) + + def test_model_weights_corrupted(self): + inp = pickle.dumps(torch.zeros(3, 3)) + model = Dummy.create_broken_model() + Dummy.create_training(model=model, actor=self.user) + input_file = SimpleUploadedFile( + "input.pkl", + inp, + content_type="application/octet-stream" + ) + with self.assertLogs("root", level="ERROR"): + response = self.client.post( + f"{BASE_URL}/inference/", + {"model_id": model.id, "model_input": input_file}, + ) + self.assertEqual(response.status_code, 500) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Unpickled object is not a torch object.", response_json["detail"]) + + def test_inference_result(self): + torch_model = mxb() + model = Dummy.create_model(owner=self.user, weights=pickle.dumps(torch_model)) + training = Dummy.create_training(actor=self.user, model=model) + inputs = torch.as_tensor([ + [0.9102, 1.0899, 2.0304, -0.8448], + [2.2616, -0.2974, 0.3805, -0.9301], + [0.4804, 0.2510, 0.2702, -0.1529], + ]) + input_file = SimpleUploadedFile( + "input.pkl", + pickle.dumps(inputs), + content_type="application/octet-stream" + ) + response = self.client.post( + f"{BASE_URL}/inference/", + {"model_id": str(training.model.id), "model_input": input_file} + ) + self.assertEqual(response.status_code, 200) + + results = pickle.loads(response.content) + self.assertEqual({}, results["uncertainty"]) + inference = results["inference"] + self.assertIsNotNone(inference) + inference_tensor = torch.as_tensor(inference) + self.assertTrue(torch.all(torch.tensor([2, 0, 0]) == inference_tensor)) diff --git a/fl_server_api/tests/test_model.py b/fl_server_api/tests/test_model.py new file mode 100644 index 0000000..70b322d --- /dev/null +++ b/fl_server_api/tests/test_model.py @@ -0,0 +1,463 @@ +from django.core.files.uploadedfile import SimpleUploadedFile +from django.test import TransactionTestCase +import pickle +import torch +from unittest.mock import MagicMock, patch + +from fl_server_core.models import GlobalModel, MeanModel, Model, SWAGModel +from fl_server_core.models.training import TrainingState +from fl_server_core.tests import BASE_URL, Dummy +from fl_server_ai.trainer.events import SWAGRoundFinished, TrainingRoundFinished + + +class ModelTests(TransactionTestCase): + + def setUp(self): + self.user = Dummy.create_user_and_authenticate(self.client) + + def test_unauthorized(self): + del self.client.defaults["HTTP_AUTHORIZATION"] + with self.assertLogs("root", level="WARNING"): + response = self.client.post( + f"{BASE_URL}/models/", + {"model_file": b"Hello World!"} + ) + self.assertEqual(401, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Authentication credentials were not provided.", response_json["detail"]) + + def test_get_all_models(self): + # make user actor and client + self.user.actor = True + self.user.client = True + self.user.save() + # create models and trainings - some related to user some not + [Dummy.create_model() for _ in range(2)] + models = [Dummy.create_model(owner=self.user) for _ in range(2)] + [Dummy.create_training() for _ in range(2)] + trainings = [Dummy.create_training(actor=self.user) for _ in range(2)] + trainings += [Dummy.create_training(participants=[self.user]) for _ in range(2)] + models += [t.model for t in trainings] + # get user related models + response = self.client.get(f"{BASE_URL}/models/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(len(models), len(response_json)) + self.assertEqual( + sorted([str(model.id) for model in models]), + sorted([model["id"] for model in response_json]) + ) + + def test_get_model_metadata(self): + model = Dummy.create_model(input_shape="torch.FloatTensor(None, 1, 1)") + response = self.client.get(f"{BASE_URL}/models/{model.id}/metadata/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(str(model.id), response_json["id"]) + self.assertEqual(str(model.name), response_json["name"]) + self.assertEqual(str(model.description), response_json["description"]) + self.assertEqual(str(model.input_shape), response_json["input_shape"]) + + def test_get_model(self): + model = Dummy.create_model(weights=b"Hello World!") + response = self.client.get(f"{BASE_URL}/models/{model.id}/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/octet-stream", response["content-type"]) + self.assertEqual(b"Hello World!", response.getvalue()) + + def test_get_model_and_unpickle(self): + model = Dummy.create_model() + response = self.client.get(f"{BASE_URL}/models/{model.id}/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/octet-stream", response["content-type"]) + torch_model = pickle.loads(response.content) + self.assertIsNotNone(torch_model) + self.assertTrue(isinstance(torch_model, torch.nn.Module)) + + def test_upload(self): + torch_model = torch.nn.Sequential( + torch.nn.Linear(3, 64), + torch.nn.ELU(), + torch.nn.Linear(64, 64), + torch.nn.ELU(), + torch.nn.Linear(64, 1), + ) + model_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch_model), + content_type="application/octet-stream" + ) + response = self.client.post(f"{BASE_URL}/models/", { + "model_file": model_file, + "name": "Test Model", + "description": "Test Model Description - Test Model Description Test", + "input_shape": "torch.FloatTensor(None, 3)" + }) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Upload Accepted", response_json["detail"]) + uuid = response_json["model_id"] + self.assertIsNotNone(uuid) + self.assertIsNot("", uuid) + self.assertEqual(GlobalModel, type(Model.objects.get(id=uuid))) + self.assertEqual("torch.FloatTensor(None, 3)", Model.objects.get(id=uuid).input_shape) + + def test_upload_swag_model(self): + torch_model = torch.nn.Sequential( + torch.nn.Linear(3, 64), + torch.nn.ELU(), + torch.nn.Linear(64, 64), + torch.nn.ELU(), + torch.nn.Linear(64, 1), + ) + model_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch_model), + content_type="application/octet-stream" + ) + response = self.client.post(f"{BASE_URL}/models/", { + "type": "SWAG", + "model_file": model_file, + "name": "Test SWAG Model", + "description": "Test SWAG Model Description - Test SWAG Model Description Test", + }) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Upload Accepted", response_json["detail"]) + uuid = response_json["model_id"] + self.assertIsNotNone(uuid) + self.assertIsNot("", uuid) + self.assertEqual(SWAGModel, type(Model.objects.get(id=uuid))) + + def test_upload_mean_model(self): + models = [Dummy.create_model(owner=self.user) for _ in range(10)] + model_uuids = [str(m.id) for m in models] + response = self.client.post(f"{BASE_URL}/models/", { + "type": "MEAN", + "name": "Test MEAN Model", + "description": "Test MEAN Model Description - Test MEAN Model Description Test", + "models": model_uuids, + }, "application/json") + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Upload Accepted", response_json["detail"]) + uuid = response_json["model_id"] + self.assertIsNotNone(uuid) + self.assertIsNot("", uuid) + self.assertEqual(MeanModel, type(Model.objects.get(id=uuid))) + + @patch("fl_server_ai.trainer.tasks.process_trainer_task.apply_async") + def test_upload_update(self, apply_async: MagicMock): + model = Dummy.create_model(owner=self.user, round=0) + Dummy.create_training(model=model, actor=self.user, state=TrainingState.ONGOING, + participants=[self.user, Dummy.create_user()]) + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + {"model_file": model_update_file, "round": 0, + "sample_size": 100} + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Update Accepted", response_json["detail"]) + self.assertFalse(apply_async.called) + + def test_upload_update_bad_keys(self): + model = Dummy.create_model(owner=self.user, round=0) + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + with self.assertLogs("django.request", level="WARNING"): + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + {"xXx_model_file_xXx": model_update_file, "round": 0, "sample_size": 100} + ) + self.assertEqual(400, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("No uploaded file 'model_file' found.", response_json["detail"]) + + def test_upload_update_no_training(self): + model = Dummy.create_model(owner=self.user, round=0) + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + with self.assertLogs("django.request", level="WARNING"): + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + {"model_file": model_update_file, "round": 0, "sample_size": 100} + ) + self.assertEqual(404, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual(f"Model with ID {model.id} does not have a training process running", response_json["detail"]) + + def test_upload_update_no_participant(self): + self.client.defaults["HTTP_ACCEPT"] = "application/json" + actor = Dummy.create_actor() + model = Dummy.create_model(owner=actor, round=0) + training = Dummy.create_training( + model=model, actor=actor, state=TrainingState.ONGOING, + participants=[actor, Dummy.create_client()] + ) + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + with self.assertLogs("root", level="WARNING"): + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + {"model_file": model_update_file, "round": 0, + "sample_size": 500} + ) + self.assertEqual(403, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual(f"You are not a participant of training {training.id}!", response_json["detail"]) + + @patch("fl_server_ai.trainer.tasks.process_trainer_task.apply_async") + def test_upload_update_and_aggregate(self, apply_async: MagicMock): + model = Dummy.create_model(owner=self.user, round=0) + train = Dummy.create_training(model=model, actor=self.user, state=TrainingState.ONGOING, + participants=[self.user]) + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + {"model_file": model_update_file, "round": 0, + "sample_size": 100} + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Update Accepted", response_json["detail"]) + self.assertTrue(apply_async.called) + apply_async.assert_called_once_with( + (), + {"training_uuid": train.id, "event_cls": TrainingRoundFinished}, + retry=False + ) + + @patch("fl_server_ai.trainer.tasks.process_trainer_task.apply_async") + def test_upload_update_and_not_aggregate_since_training_is_locked(self, apply_async: MagicMock): + model = Dummy.create_model(owner=self.user, round=0) + training = Dummy.create_training( + model=model, actor=self.user, state=TrainingState.ONGOING, participants=[self.user] + ) + training.locked = True + training.save() + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + {"model_file": model_update_file, "round": 0, + "sample_size": 100} + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Update Accepted", response_json["detail"]) + self.assertFalse(apply_async.called) + + def test_upload_update_with_metrics(self): + model = Dummy.create_model(owner=self.user, round=0) + Dummy.create_training(model=model, actor=self.user, state=TrainingState.ONGOING, + participants=[self.user, Dummy.create_user()]) + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + { + "model_file": model_update_file, + "round": 0, + "metric_names": ["loss", "accuracy", "dummy_binary"], + "metric_values": [1999.0, 0.12, b"Hello World!"], + "sample_size": 50 + }, + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Update Accepted", response_json["detail"]) + + def test_upload_update_with_metrics_bad(self): + model = Dummy.create_model(owner=self.user) + Dummy.create_training(model=model, actor=self.user, state=TrainingState.ONGOING, + participants=[self.user, Dummy.create_user()]) + model_update_file = SimpleUploadedFile( + "model.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + content_type="application/octet-stream" + ) + with self.assertLogs("root", level="WARNING"): + response = self.client.post( + f"{BASE_URL}/models/{model.id}/", + {"model_file": model_update_file, "round": 0, "metric_names": 5, + "sample_size": 500} + ) + self.assertEqual(400, response.status_code) + + def test_upload_global_model_metrics(self): + model = Dummy.create_model(owner=self.user, round=0) + metrics = dict( + metric_names=["loss", "accuracy", "dummy_binary"], + metric_values=[1999.0, 0.12, b"Hello World!"], + ) + with self.assertLogs("fl.server", level="WARNING") as cm: + response = self.client.post( + f"{BASE_URL}/models/{model.id}/metrics/", + metrics, + ) + self.assertEqual(cm.output, [ + f"WARNING:fl.server:Global model {model.id} is not connected to any training.", + ]) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Metrics Upload Accepted", response_json["detail"]) + self.assertEqual(str(model.id), response_json["model_id"]) + + def test_upload_local_model_metrics(self): + model = Dummy.create_model_update(owner=self.user) + metrics = dict( + metric_names=["loss", "accuracy", "dummy_binary"], + metric_values=[1999.0, 0.12, b"Hello World!"], + ) + response = self.client.post( + f"{BASE_URL}/models/{model.id}/metrics/", + metrics, + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Model Metrics Upload Accepted", response_json["detail"]) + self.assertEqual(str(model.id), response_json["model_id"]) + + def test_upload_bad_metrics(self): + model = Dummy.create_model(owner=self.user, round=0) + metrics = dict( + metric_names=["loss", "accuracy", "dummy_binary"], + metric_values=[1999.0, b"Hello World!"], + ) + with self.assertLogs("django.request", level="WARNING"): + response = self.client.post( + f"{BASE_URL}/models/{model.id}/metrics/", + metrics, + ) + self.assertEqual(400, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Metric names and values must have the same length", response_json["detail"]) + + @patch("fl_server_ai.trainer.tasks.process_trainer_task.apply_async") + def test_upload_swag_stats(self, apply_async: MagicMock): + model = Dummy.create_model(owner=self.user, round=0) + train = Dummy.create_training( + model=model, + actor=self.user, + state=TrainingState.SWAG_ROUND, + participants=[self.user] + ) + + first_moment_file = SimpleUploadedFile( + "first_moment.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + ).state_dict()), + content_type="application/octet-stream" + ) + second_moment_file = SimpleUploadedFile( + "second_moment.pkl", + pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + ).state_dict()), + content_type="application/octet-stream" + ) + response = self.client.post(f"{BASE_URL}/models/{model.id}/swag/", { + "first_moment_file": first_moment_file, + "second_moment_file": second_moment_file, + "sample_size": 100, + "round": 0 + }) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("SWAG Statistic Accepted", response_json["detail"]) + self.assertTrue(apply_async.called) + apply_async.assert_called_once_with( + (), + {"training_uuid": train.id, "event_cls": SWAGRoundFinished}, + retry=False + ) + + def test_get_global_model_metrics(self): + model = Dummy.create_model(owner=self.user) + metric = Dummy.create_metric(model=model) + response = self.client.get(f"{BASE_URL}/models/{model.id}/metrics/") + self.assertEqual(200, response.status_code) + body = response.json() + self.assertEqual(1, len(body)) + self.assertEqual(metric.value_float, body[0]["value_float"]) + self.assertEqual(metric.key, body[0]["key"]) + + def test_get_local_model_metrics(self): + model = Dummy.create_model_update(owner=self.user) + metric = Dummy.create_metric(model=model) + response = self.client.get(f"{BASE_URL}/models/{model.id}/metrics/") + self.assertEqual(200, response.status_code) + body = response.json() + self.assertEqual(1, len(body)) + self.assertEqual(metric.value_float, body[0]["value_float"]) + self.assertEqual(metric.key, body[0]["key"]) diff --git a/fl_server_api/tests/test_openapi.py b/fl_server_api/tests/test_openapi.py new file mode 100644 index 0000000..ae68861 --- /dev/null +++ b/fl_server_api/tests/test_openapi.py @@ -0,0 +1,44 @@ +from django.test import TestCase +import json +import yaml + +from fl_server_core.tests import BASE_URL + + +class OpenApiTests(TestCase): + + def test_get_openapi(self): + response = self.client.get(f"{BASE_URL}/schema/swagger-ui/") + self.assertEqual(200, response.status_code) + + def test_get_redoc(self): + response = self.client.get(f"{BASE_URL}/schema/redoc/") + self.assertEqual(200, response.status_code) + + def test_get_yaml(self): + response = self.client.get(f"{BASE_URL}/schema/", HTTP_ACCEPT="application/yaml") + self.assertEqual(200, response.status_code) + self.assertEqual("application/yaml", response["content-type"].split(";")[0].strip()) + response_yaml = yaml.load(response.content, Loader=yaml.FullLoader) + self.assertIsNotNone(response_yaml) + + def test_get_openapi_yaml(self): + response = self.client.get(f"{BASE_URL}/schema/", HTTP_ACCEPT="application/vnd.oai.openapi") + self.assertEqual(200, response.status_code) + self.assertEqual("application/vnd.oai.openapi", response["content-type"].split(";")[0].strip()) + response_yaml = yaml.load(response.content, Loader=yaml.FullLoader) + self.assertIsNotNone(response_yaml) + + def test_get_json(self): + response = self.client.get(f"{BASE_URL}/schema/", HTTP_ACCEPT="application/json") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"].split(";")[0].strip()) + response_json = response.json() + self.assertIsNotNone(response_json) + + def test_get_openapi_json(self): + response = self.client.get(f"{BASE_URL}/schema/", HTTP_ACCEPT="application/vnd.oai.openapi+json") + self.assertEqual(200, response.status_code) + self.assertEqual("application/vnd.oai.openapi+json", response["content-type"].split(";")[0].strip()) + response_json = json.loads(response.content) # Django `response.json()` requires Content-Type json + self.assertIsNotNone(response_json) diff --git a/fl_server_api/tests/test_training.py b/fl_server_api/tests/test_training.py new file mode 100644 index 0000000..08570a1 --- /dev/null +++ b/fl_server_api/tests/test_training.py @@ -0,0 +1,231 @@ +import json +from unittest.mock import MagicMock, patch +from uuid import uuid4 +from django.test import TestCase + +from fl_server_core.tests import BASE_URL, Dummy +from fl_server_core.models.training import TrainingState + + +class TrainingTests(TestCase): + + def setUp(self): + self.user = Dummy.create_user_and_authenticate(self.client) + + def test_create_training(self): + model = Dummy.create_model(owner=self.user) + request_body = dict( + model_id=str(model.id), + target_num_updates=100, + metric_names=["accuracy", "f1_score"], + uncertainty_method="NONE", + aggregation_method="FedAvg" + ) + response = self.client.post( + f"{BASE_URL}/trainings/", + data=json.dumps(request_body), + content_type="application/json" + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Training created successfully!", response_json["detail"]) + + def test_create_training_with_clients(self): + model = Dummy.create_model(owner=self.user) + clients = [Dummy.create_client(username=f"client-{n}") for n in range(3)] + request_body = dict( + model_id=str(model.id), + target_num_updates=100, + metric_names=["accuracy", "f1_score"], + uncertainty_method="NONE", + aggregation_method="FedAvg", + clients=list(map(lambda c: str(c.id), clients)) + ) + response = self.client.post( + f"{BASE_URL}/trainings/", + data=json.dumps(request_body), + content_type="application/json" + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Training created successfully!", response_json["detail"]) + + def test_create_training_invalid_aggregation_method(self): + model = Dummy.create_model(owner=self.user) + request_body = dict( + model_id=str(model.id), + target_num_updates=100, + metric_names=["accuracy", "f1_score"], + uncertainty_method="NONE", + aggregation_method="INVALID" + ) + with self.assertLogs("root", level="WARNING"): + response = self.client.post( + f"{BASE_URL}/trainings/", + data=json.dumps(request_body), + content_type="application/json" + ) + self.assertEqual(400, response.status_code) + + def test_create_training_not_model_owner(self): + model = Dummy.create_model() + request_body = dict( + model_id=str(model.id), + target_num_updates=100, + metric_names=["accuracy", "f1_score"], + uncertainty_method="NONE", + aggregation_method="FedAvg" + ) + with self.assertLogs("django.request", level="WARNING") as cm: + response = self.client.post( + f"{BASE_URL}/trainings/", + data=json.dumps(request_body), + content_type="application/json" + ) + self.assertEqual(cm.output, [ + "WARNING:django.request:Forbidden: /api/trainings/", + ]) + self.assertEqual(403, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("You do not have permission to perform this action.", response_json["detail"]) + + def test_get_trainings(self): + # make user actor + self.user.actor = True + self.user.save() + # create trainings - some related to user some not + [Dummy.create_training() for _ in range(3)] + trainings = [Dummy.create_training(actor=self.user) for _ in range(3)] + # get user related trainings + response = self.client.get(f"{BASE_URL}/trainings/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(len(trainings), len(response_json)) + self.assertEqual( + sorted([str(training.id) for training in trainings]), + sorted([training["id"] for training in response_json]) + ) + + def test_get_training_good(self): + training = Dummy.create_training(actor=self.user) + response = self.client.get(f"{BASE_URL}/trainings/{training.id}/") + self.assertEqual(response.status_code, 200) + body = response.json() + self.assertEqual(str(training.actor.id), body["actor"]) + self.assertEqual(TrainingState.INITIAL, body["state"]) + self.assertEqual(0, body["target_num_updates"]) + + def test_get_training_bad(self): + training = Dummy.create_training() + with self.assertLogs("root", level="WARNING"): + response = self.client.get(f"{BASE_URL}/trainings/{training.id}/") + self.assertEqual(response.status_code, 403) + + def test_register_clients_good(self): + training = Dummy.create_training(actor=self.user) + users = [str(Dummy.create_user(username=f"client{i}").id) for i in range(1, 5)] + request_body = dict(clients=users) + + response = self.client.put( + f"{BASE_URL}/trainings/{training.id}/clients/", + json.dumps(request_body) + ) + self.assertEqual(response.status_code, 202) + body = response.json() + self.assertEqual("Users registered as participants!", body["detail"]) + + def test_register_clients_bad(self): + training = Dummy.create_training(actor=self.user) + users = [str(Dummy.create_user(username=f"client{i}").id) for i in range(1, 5)] + [str(uuid4())] + request_body = dict(clients=users) + with self.assertLogs("root", level="WARNING"): + response = self.client.put( + f"{BASE_URL}/trainings/{training.id}/clients/", + json.dumps(request_body) + ) + self.assertEqual(response.status_code, 400) + self.assertIsNotNone(response.content) + response_body = response.json() + self.assertEqual("Not all provided users were found!", response_body["detail"]) + + def test_remove_clients_good(self): + training = Dummy.create_training(actor=self.user) + users = [str(t.id) for t in training.participants.all()] + assert users + request_body = dict(clients=users) + + response = self.client.delete( + f"{BASE_URL}/trainings/{training.id}/clients/", + json.dumps(request_body) + ) + self.assertEqual(response.status_code, 200) + response = self.client.get(f"{BASE_URL}/trainings/{training.id}/") + self.assertEqual(response.status_code, 200) + body = response.json() + self.assertEqual(0, len(body["participants"])) + + @patch("fl_server_ai.notification.notification.send_notifications.apply_async") + def test_start_training(self, apply_async: MagicMock): + user = Dummy.create_user(message_endpoint="http://example.com") + training = Dummy.create_training(actor=self.user) + training.participants.set([user]) + training.save() + response = self.client.post(f"{BASE_URL}/trainings/{training.id}/start/") + self.assertEqual(response.status_code, 202) + self.assertEqual(2, apply_async.call_count) # TrainingStartNotification, TrainingRoundStartNotification + + def test_start_training_no_participants(self): + training = Dummy.create_training(actor=self.user) + training.participants.set([]) + training.save() + with self.assertLogs("root", level="WARNING"): + response = self.client.post(f"{BASE_URL}/trainings/{training.id}/start/") + self.assertEqual(response.status_code, 400) + self.assertIsNotNone(response.content) + response_body = response.json() + self.assertEqual("At least one participant must be registered!", response_body["detail"]) + + def test_start_training_not_initial_state(self): + user = Dummy.create_user(message_endpoint="http://example.com") + training = Dummy.create_training(actor=self.user, state=TrainingState.ONGOING) + training.participants.set([user]) + training.save() + with self.assertLogs("django.request", level="WARNING") as cm: + response = self.client.post(f"{BASE_URL}/trainings/{training.id}/start/") + self.assertEqual(cm.output, [ + f"WARNING:django.request:Bad Request: /api/trainings/{training.id}/start/", + ]) + self.assertEqual(response.status_code, 400) + self.assertIsNotNone(response.content) + response_body = response.json() + self.assertEqual(f"Training {training.id} is not in state INITIAL!", response_body["detail"]) + + def test_create_training_with_trained_model(self): + training = Dummy.create_training(actor=self.user) + model = training.model + request_body = dict( + model_id=str(model.id), + target_num_updates=100, + metric_names=["accuracy", "f1_score"], + uncertainty_method="NONE", + aggregation_method="FedAvg" + ) + response = self.client.post( + f"{BASE_URL}/trainings/", + data=json.dumps(request_body), + content_type="application/json" + ) + self.assertEqual(201, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertEqual("Training created successfully!", response_json["detail"]) + + response = self.client.get(f"{BASE_URL}/trainings/{response_json['training_id']}/") + self.assertEqual(200, response.status_code) + response_json = response.json() + self.assertIsNotNone(response_json) + self.assertNotEqual(model.id, response_json['id']) diff --git a/fl_server_api/tests/test_user.py b/fl_server_api/tests/test_user.py new file mode 100644 index 0000000..039928b --- /dev/null +++ b/fl_server_api/tests/test_user.py @@ -0,0 +1,146 @@ +import base64 +from django.test import TestCase +from rest_framework.authtoken.models import Token +from typing import Any, Dict, Optional, Union +from uuid import uuid4 + +from fl_server_core.tests import BASE_URL, Dummy +from fl_server_core.models import User + +from .utils import parse + + +class UserTests(TestCase): + + def assertUserEqual( + self, + expected: Union[User, Dict], + actual: Union[User, Dict], + *, + include_id_check: Optional[bool] = True + ) -> None: + expected_obj: Any = parse(expected) if isinstance(expected, Dict) else expected + actual_obj: Any = parse(actual) if isinstance(actual, Dict) else actual + # user model + if include_id_check: + self.assertEqual(str(expected_obj.id), str(actual_obj.id)) + self.assertEqual(bool(expected_obj.actor), bool(actual_obj.actor)) + self.assertEqual(bool(expected_obj.client), bool(actual_obj.client)) + self.assertEqual(str(expected_obj.message_endpoint), str(actual_obj.message_endpoint)) + # auth user model + self.assertEqual(str(expected_obj.username), str(actual_obj.username)) + self.assertEqual(str(expected_obj.first_name), str(actual_obj.first_name)) + self.assertEqual(str(expected_obj.last_name), str(actual_obj.last_name)) + self.assertEqual(str(expected_obj.email), str(actual_obj.email)) + + def test_get_user_via_auth(self): + user = Dummy.create_user_and_authenticate(self.client) + response = self.client.get(f"{BASE_URL}/users/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(1, len(response_json)) + self.assertUserEqual(user, response_json[0]) + + def test_get_user_via_url_token(self): + user = Dummy.create_user() + token = Token.objects.get(user=user).key + credentials = base64.b64encode(token.encode("utf-8")).decode("utf-8") + self.client.defaults["HTTP_AUTHORIZATION"] = "Basic " + credentials + # Note: Django self.client does not support: http://username:password@localhost:8000/api/... + response = self.client.get(f"{BASE_URL}/users/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(1, len(response_json)) + self.assertUserEqual(user, response_json[0]) + + def test_get_user_via_auth_token(self): + user = Dummy.create_user() + token = Token.objects.get(user=user).key + self.client.defaults["HTTP_AUTHORIZATION"] = "Token " + token + response = self.client.get(f"{BASE_URL}/users/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(1, len(response_json)) + self.assertUserEqual(user, response_json[0]) + + def test_get_user_via_auth_unauthenticate(self): + with self.assertLogs("django.request", level="WARNING") as cm: + response = self.client.get(f"{BASE_URL}/users/") + self.assertEqual(cm.output, [ + "WARNING:django.request:Unauthorized: /api/users/", + ]) + self.assertEqual(401, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual("Authentication credentials were not provided.", response_json["detail"]) + + def test_get_user_via_uuid(self): + user = Dummy.create_user_and_authenticate(self.client) + response = self.client.get(f"{BASE_URL}/users/{user.id}/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertUserEqual(user, response_json) + + def test_get_user_via_uuid_unauthenticate(self): + user = Dummy.create_user() + with self.assertLogs("django.request", level="WARNING") as cm: + response = self.client.get(f"{BASE_URL}/users/{user.id}/") + self.assertEqual(cm.output, [ + f"WARNING:django.request:Unauthorized: /api/users/{user.id}/", + ]) + self.assertEqual(401, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual("Authentication credentials were not provided.", response_json["detail"]) + + def test_create_user(self): + user = dict( + # user model + actor=False, + client=True, + message_endpoint="https://example.com", + # auth user model + username=str(uuid4()).split("-")[0], + first_name="Jane", + last_name="Doe", + email="jane.doe@example.com", + password="secret", + ) + response = self.client.post(f"{BASE_URL}/users/", user, content_type="application/json") + self.assertEqual(201, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertUserEqual(user, response_json, include_id_check=False) + + def test_get_user_groups(self): + user = Dummy.create_user_and_authenticate(self.client) + [Dummy.create_group() for _ in range(3)] + groups = [Dummy.create_group() for _ in range(3)] + [user.groups.add(group) for group in groups] + response = self.client.get(f"{BASE_URL}/users/groups/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(3, len(response_json)) + self.assertEqual( + sorted([group.id for group in groups]), + sorted([group["id"] for group in response_json]) + ) + + def test_get_user_trainings(self): + user = Dummy.create_user_and_authenticate(self.client) + [Dummy.create_training() for _ in range(3)] + trainings = [Dummy.create_training(actor=user) for _ in range(3)] + response = self.client.get(f"{BASE_URL}/users/trainings/") + self.assertEqual(200, response.status_code) + self.assertEqual("application/json", response["content-type"]) + response_json = response.json() + self.assertEqual(3, len(response_json)) + self.assertEqual( + sorted([str(training.id) for training in trainings]), + sorted([training["id"] for training in response_json]) + ) diff --git a/fl_server_api/tests/test_utils.py b/fl_server_api/tests/test_utils.py new file mode 100644 index 0000000..ebec8d8 --- /dev/null +++ b/fl_server_api/tests/test_utils.py @@ -0,0 +1,119 @@ +from django.core.files.uploadedfile import SimpleUploadedFile +from django.http import HttpRequest +from django.test import TestCase +from rest_framework.exceptions import ParseError +from uuid import uuid4 +import pickle +import torch +from typing import Optional + +from fl_server_core.tests import Dummy +from fl_server_core.models import User +from fl_server_core.utils.strings import str2bool + +from ..utils import get_entity, get_file, is_json + + +class UtilsTest(TestCase): + + def test_views_get_entity(self): + user = Dummy.create_actor() + user2 = get_entity(User, pk=user.id) + self.assertIsNotNone(user2) + self.assertEqual(user.id, user2.id) + + def test_views_get_entity_not_exists(self): + uid = uuid4() + with self.assertRaises(ParseError) as context: + get_entity(User, pk=uid) + self.assertTrue(str(context.exception).__contains__(f"User {uid} not found.")) + + def test_views_get_entity_custom_error_identifier(self): + uid = uuid4() + error_identifier = "'hello world!'" + with self.assertRaises(ParseError) as context: + get_entity(User, error_identifier=error_identifier, pk=uid) + self.assertTrue(str(context.exception).__contains__(f"User {error_identifier} not found.")) + + def test_views_get_entity_custom_error_message(self): + uid = uuid4() + error_message = "hello world!" + with self.assertRaises(ParseError) as context: + get_entity(User, error_message=error_message, pk=uid) + self.assertTrue(str(context.exception).__contains__(error_message)) + + def test_views_get_file(self): + key = "model-key" + inp = pickle.dumps(torch.zeros(3, 3)) + input_file = SimpleUploadedFile("input.pkl", inp, content_type="application/octet-stream") + request = HttpRequest() + request.FILES.appendlist(key, input_file) + file_content = get_file(request, key) + self.assertIsNotNone(file_content) + self.assertEqual(len(inp), len(file_content)) + + def test_views_get_file_file_not_exist(self): + key = "model-key" + request = HttpRequest() + request.FILES.appendlist(key, None) + with self.assertRaises(ParseError) as context: + get_file(request, key) + self.assertTrue(str(context.exception).__contains__(f"No uploaded file '{key}' found.")) + + def test_views_get_file_custom_validator(self): + key = "model-key" + inp = pickle.dumps(torch.zeros(3, 3)) + input_file = SimpleUploadedFile("input.pkl", inp, content_type="application/octet-stream") + request = HttpRequest() + request.FILES.appendlist(key, input_file) + + def validator(req, name, uploaded_file, file_content, **kwargs) -> Optional[str]: + self.assertIsNotNone(req) + self.assertEqual(key, name) + self.assertIsNotNone(uploaded_file) + self.assertEqual(len(inp), len(file_content)) + self.assertEqual(5, kwargs["x"]) + return None + + file_content = get_file(request, key, validator=validator, x=5) + self.assertIsNotNone(file_content) + self.assertEqual(len(inp), len(file_content)) + + def test_views_get_file_custom_validator_error(self): + key = "model-key" + inp = pickle.dumps(torch.zeros(3, 3)) + input_file = SimpleUploadedFile("input.pkl", inp, content_type="application/octet-stream") + request = HttpRequest() + request.FILES.appendlist(key, input_file) + error_message = "ERROR: Hello World!" + with self.assertRaises(ParseError) as context: + get_file(request, key, validator=lambda req, name, uploaded_file, file_content, **kwargs: error_message) + self.assertTrue(str(context.exception).__contains__(error_message)) + + def test_str2bool_true(self): + TRUES = [True, "yes", "true", "t", "y", "1"] + for true in TRUES: + self.assertTrue(str2bool(true)) + + def test_str2bool_false(self): + FALSES = [False, "no", "false", "f", "n", "0"] # cspell:ignore FALSES + for false in FALSES: + self.assertFalse(str2bool(false)) + + def test_str2bool_error(self): + value = "hello world!" + with self.assertRaises(ValueError) as context: + str2bool(value) + self.assertTrue(str(context.exception).__contains__(f"Can not convert '{value}' to boolean.")) + + def test_str2bool_fallback(self): + self.assertTrue(str2bool("hello world!", fallback=True)) + self.assertFalse(str2bool("hello world!", fallback=False)) + self.assertTrue(str2bool(None, fallback=True)) + self.assertFalse(str2bool(None, fallback=False)) + + def test_is_json_true(self): + self.assertEqual({"hello": "world"}, is_json('{"hello": "world"}')) + + def test_is_json_false(self): + self.assertFalse(is_json('hello world')) diff --git a/fl_server_api/tests/utils.py b/fl_server_api/tests/utils.py new file mode 100644 index 0000000..0cdd940 --- /dev/null +++ b/fl_server_api/tests/utils.py @@ -0,0 +1,20 @@ +from types import SimpleNamespace +from typing import Dict + + +def parse(d: Dict) -> SimpleNamespace: + """ + Parse nested dict to namespace to support dot notation/access. + + Args: + d (Dict): dictionary to parse + + Returns: + SimpleNamespace: dict as namespace + """ + x = SimpleNamespace() + [setattr( # type:ignore[func-returns-value] + x, k, + parse(v) if isinstance(v, dict) else [parse(e) for e in v] if isinstance(v, list) else v + ) for k, v in d.items()] + return x diff --git a/fl_server_api/urls.py b/fl_server_api/urls.py new file mode 100644 index 0000000..a2ddf63 --- /dev/null +++ b/fl_server_api/urls.py @@ -0,0 +1,48 @@ +from django.conf import settings +from django.urls import path +from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView + +from .views import Group, Inference, Model, Training, User +from .views.dummy import DummyView + + +urlpatterns = [ + # OpenAPI Specification and UIs + path("schema/", SpectacularAPIView.as_view(), name="openapi"), + path("schema/swagger-ui/", SpectacularSwaggerView.as_view(url_name="openapi"), name="swagger-ui"), + path("schema/redoc/", SpectacularRedocView.as_view(url_name="openapi"), name="redoc"), + + # groups + path("groups/", view=Group.as_view({"get": "list", "post": "create"}), name="groups"), + path("groups//", view=Group.as_view({ + "get": "retrieve", "put": "update", "patch": "partial_update", "delete": "destroy" + }), name="group"), + # users + path("users/", view=User.as_view({"get": "get_users", "post": "create_user"}), name="users"), + path("users/groups/", view=User.as_view({"get": "get_user_groups"}), name="user-groups"), + path("users/trainings/", view=User.as_view({"get": "get_user_trainings"}), name="user-trainings"), + path("users//", view=User.as_view({"get": "get_user"}), name="user"), + # models + path("models/", view=Model.as_view({"get": "get_models", "post": "create_model"}), name="models"), + path("models//", view=Model.as_view({"get": "get_model", "post": "create_local_model"}), name="model"), + path("models//metadata/", view=Model.as_view({"get": "get_metadata"}), name="model-metadata"), + path("models//metrics/", view=Model.as_view( + {"get": "get_model_metrics", "post": "create_model_metrics"} + ), name="model-metrics"), + path("models//swag/", view=Model.as_view({"post": "create_swag_stats"}), name="model-swag"), + # trainings + path("trainings/", view=Training.as_view({"get": "get_trainings", "post": "create_training"}), name="trainings"), + path("trainings//", view=Training.as_view({"get": "get_training"}), name="training"), + path("trainings//clients/", view=Training.as_view( + {"put": "register_clients", "delete": "remove_clients"} + ), name="training-clients"), + path("trainings//start/", view=Training.as_view({"post": "start_training"}), name="training-start"), + # inference + path("inference/", view=Inference.as_view({"post": "inference"}), name="inference"), +] + +if settings.DEBUG: + urlpatterns += [ + # Dummies for Johannes + path("dummy/", view=DummyView.as_view({"get": "create_dummy_metrics_and_models"}, name="dummy")), + ] diff --git a/fl_server_api/utils.py b/fl_server_api/utils.py new file mode 100644 index 0000000..e6fb6e6 --- /dev/null +++ b/fl_server_api/utils.py @@ -0,0 +1,132 @@ +from django.db import models +from django.core.exceptions import ObjectDoesNotExist, ValidationError as ValidationException +from django.core.files.uploadedfile import UploadedFile +from django.http import HttpRequest +from collections.abc import Callable +import json +from rest_framework.exceptions import ParseError +from types import FunctionType, MethodType +from typing import Any, Optional, Type, TypeVar, Union + + +_TModel = TypeVar("_TModel", bound=models.Model) + + +def get_entity( + cls: Type[_TModel], + error_message: Optional[str] = None, + error_identifier: Optional[str] = None, + *args, + **kwargs +) -> _TModel: + """ + Get model instance. + + Try to get a model instance. Similar to `.objects.get()`. + But, catch and evaluate all kinds of exceptions which `.objects.get()` throws, + combine it and build an response including an error message inside a `HttpResponseBadRequest` + and throw `EntityNotFoundException` (one single Exception). + + Args: + cls (Type[_TModel]): model class where the entity should be found + error_message (Optional[str], optional): message added to `HttpResponseBadRequest` if an error occurs. + If `None` a " not found." message will be created. + error_identifier (Optional[str], optional): model identifier or field name for the error message creation + if an error occurs. + If `None` the arguments of `.objects.get()` are searched for "pk" or "id" as fallback. + + Raises: + ValidationError: If `.objects.get()` raise any kind of error. + + Returns: + _TModel: instance + + Examples: + ```python + def get_user(self, request: HttpRequest, id: int) -> HttpResponseBase: + user = get_entity(User, pk=id) # EntityNotFoundException will be handled by middleware + serializer = UserSerializer(user) + return Response(serializer.data) + ``` + """ + try: + return cls.objects.get(*args, **kwargs) + except (ObjectDoesNotExist, ValidationException): + if error_message: + raise ParseError(error_message) + + if error_identifier is None: + error_identifier = kwargs.get("pk", kwargs.get("id", None)) + msg = f"{cls.__name__} {error_identifier} not found." + raise ParseError(msg) + + +def get_file( + request: HttpRequest, + name: str, + validator: Optional[Callable[[HttpRequest, str, UploadedFile, bytes], Optional[str]]] = None, + **kwargs +) -> bytes: + """ + Try to get a single uploaded file and optional check it. + + Args: + request (HttpRequest): http request where the file should be found + name (str): name or key of the uploaded file + validator (Optional[Callable[[HttpRequest, str, UploadedFile, bytes], Optional[str]]]], optional): + file validation method, returns error message if file is not valid; otherwise `None` + kwargs: additional validator arguments + + Raises: + ParseError: If no file was found or validator return error messages. + + Returns: + bytes: file content + """ + uploaded_file = request.FILES.get(name) + if not uploaded_file or not uploaded_file.file: + raise ParseError(f"No uploaded file '{name}' found.") + file_content = uploaded_file.file.read() + if validator: + error_message = validator(request, name, uploaded_file, file_content, **kwargs) + if error_message: + raise ParseError(error_message) + return file_content + + +def is_json(s: Union[str, bytes, bytearray]) -> Any: + """ + Check if the given argument s is a valid json. + + Args: + s (Union[str, bytes, bytearray]): validation objective + + Returns: + Any: Deserialize object of objective `s` is a valid json; otherwise `False` + """ + try: + return json.loads(s) + except ValueError: + return False + + +def fullname(cls_or_obj_or_fn: Union[type, object, Callable]) -> str: + """ + Get full qualified name of class, object or function. + + Args: + cls_or_obj_or_fn (Union[type, object, Callable]): Inspection target. + + Returns: + str: qualified name + """ + if isinstance(cls_or_obj_or_fn, (type, FunctionType, MethodType)): + cls = cls_or_obj_or_fn # class or function + else: + cls = cls_or_obj_or_fn.__class__ # object + + module = cls.__module__ + # if module == "builtins": # or module == "__main__": # NOSONAR: S125 + # # avoid outputs like "builtins.str" + # return cls.__qualname__ + return module + "." + cls.__qualname__ diff --git a/fl_server_api/views/__init__.py b/fl_server_api/views/__init__.py new file mode 100644 index 0000000..45961e3 --- /dev/null +++ b/fl_server_api/views/__init__.py @@ -0,0 +1,8 @@ +from .group import Group +from .inference import Inference +from .model import Model +from .training import Training +from .user import User + + +__all__ = ["Group", "Inference", "Model", "Training", "User"] diff --git a/fl_server_api/views/base.py b/fl_server_api/views/base.py new file mode 100644 index 0000000..dee81ea --- /dev/null +++ b/fl_server_api/views/base.py @@ -0,0 +1,74 @@ +from logging import getLogger +from rest_framework.authentication import BasicAuthentication, SessionAuthentication, TokenAuthentication +from rest_framework.permissions import IsAuthenticated +from rest_framework.viewsets import ViewSet as DjangoViewSet + + +class BasicAuthAllowingTokenAuthInUrl(BasicAuthentication): + + def authenticate_credentials(self, userid_or_token, password, request=None): + """ + Authenticate credentials against username/password or token. + + Basic Authentication: + Authenticate the userid and password against username and password + with optional request for context. + + Token Authentication over URL: + Authenticate the given token against the token in the database. + """ + # check if special token authentication is used + if (len(userid_or_token) == 40 and password == ""): + # tokens are always 40 characters long + # see: rest_framework.authtoken.models.Token (class method: generate_key) + # which uses `binascii.hexlify(os.urandom(20)).decode()` + return TokenAuthentication().authenticate_credentials(userid_or_token) + + # default Basic Authentication + return super().authenticate_credentials(userid_or_token, password, request) + + +class ViewSet(DjangoViewSet): + """ + DLR Federated Learning base ViewSet including default authentication and permission classes. + + Authentication as well as permission classes can not only be overwritten by the child class, but also by the + request method. This allows to have different authentication and permission classes for each request method. + To overwrite the authentication and permission classes for a specific request method, simply add the designated + decorators: `@decorators.authentication_classes` and `@decorators.permission_classes` from + `rest_framework.decorators`. + """ + _logger = getLogger("fl.server") + + # Note: BasicAuthentication is sensles here since it will and can't never be called due to + # BasicAuthAllowingTokenAuthInUrl but is required for OpenAPI to work. + # Also note that the order of BasicAuthAllowingTokenAuthInUrl and BasicAuthentication is important + # since if BasicAuthentication is first, Django won't ever call BasicAuthAllowingTokenAuthInUrl! + authentication_classes = [ + TokenAuthentication, + BasicAuthAllowingTokenAuthInUrl, + BasicAuthentication, + SessionAuthentication, + ] + permission_classes = [IsAuthenticated] + + def get_authenticators(self): + if method := self._get_view_method(): + if hasattr(method, "authentication_classes"): + return method.authentication_classes + return super().get_authenticators() + + def get_permissions(self): + if method := self._get_view_method(): + if hasattr(method, "permission_classes"): + return method.permission_classes + return super().get_permissions() + + def _get_view_method(self): + if hasattr(self, "action") and self.action is not None: + return self.__getattribute__(self.action) + if hasattr(self.request, "method") and self.request.method is not None: + http_method = self.request.method.lower() + if hasattr(self, http_method): + return self.__getattribute__(http_method) + return None diff --git a/fl_server_api/views/dummy.py b/fl_server_api/views/dummy.py new file mode 100644 index 0000000..c6cbc05 --- /dev/null +++ b/fl_server_api/views/dummy.py @@ -0,0 +1,73 @@ +from django.db import IntegrityError, transaction +from django.http import HttpRequest, JsonResponse +from logging import getLogger +import random +from rest_framework.authtoken.models import Token +from rest_framework.viewsets import ViewSet as DjangoViewSet +from uuid import uuid4 + +from fl_server_core.models import Training, User +from fl_server_core.models.training import TrainingState +from fl_server_core.tests.dummy import Dummy + + +class DummyView(DjangoViewSet): + _logger = getLogger("fl.server") + authentication_classes: list = [] + permission_classes: list = [] + + def create_dummy_metrics_and_models(self, _request: HttpRequest): + epochs = 80 + try: + # `transaction.atomic` is important + # otherwise Django's internal atomic transaction won't be closed if an IntegrityError is raised + # and `User.objects.get` will raise an TransactionManagementError + with transaction.atomic(): + user = Dummy.create_user(username="dummy-user", password="secret") + except IntegrityError: + self._logger.warning("Dummy User already exists") + user = User.objects.get(username="dummy-user") + + model = Dummy.create_model(owner=user) + participants = [Dummy.create_client() for _ in range(5)] + training = Dummy.create_training( + state=TrainingState.COMPLETED, + target_num_updates=epochs, + actor=user, + model=model, + participants=participants, + ) + self._fill_metrics(training, epochs) + self.created = True + + return JsonResponse({ + "message": "Created Dummy Data in Metrics Database!", + "training_uuid": training.id, + "user_uuid": user.id, + "user_credentials": { + "username": "dummy-user", + "password": "secret", + "token": Token.objects.get(user=user).key, + }, + "participants": [str(p.id) for p in training.participants.all()], + }) + + def _fill_metrics(self, training: Training, epochs: int): + for epoch in range(epochs): + for client in training.participants.all(): + Dummy.create_metric( + model=training.model, + identifier=str(uuid4()).split("-")[0], + key="NLLoss", + value_float=27.354/(epoch+1) + random.randint(0, 100) / 100, + step=epoch, + reporter=client + ) + Dummy.create_metric( + model=training.model, + identifier=str(uuid4()).split("-")[0], + key="Accuracy", + value_float=epoch/epochs + random.randint(0, 100) / 1000, + step=epoch, + reporter=client + ) diff --git a/fl_server_api/views/group.py b/fl_server_api/views/group.py new file mode 100644 index 0000000..4b919e4 --- /dev/null +++ b/fl_server_api/views/group.py @@ -0,0 +1,224 @@ +from django.contrib.auth.models import Group as GroupModel +from django.http import HttpRequest, HttpResponse +from drf_spectacular.utils import extend_schema, OpenApiExample, OpenApiParameter +from rest_framework import status +from rest_framework.exceptions import PermissionDenied +from rest_framework.response import Response + +from fl_server_core.models import User as UserModel + +from .base import ViewSet +from ..utils import get_entity +from ..serializers.generic import ErrorSerializer, GroupSerializer +from ..openapi import error_response_403 + + +_default_group_example = OpenApiExample( + name="Get group by id", + description="\n\n".join([ + "Retrieve group data by group ID.", + "_Please not that the user Jane Doe has to be created and authorized first._", + ]), + value=1, + parameter_only=("id", OpenApiParameter.PATH) +) + + +class Group(ViewSet): + + serializer_class = GroupSerializer + + def _get_group(self, user: UserModel, group_id: int) -> GroupModel: + """ + Get group by id if user is member of the group. + Otherwise raise PermissionDenied. + + Args: + user (UserModel): user who makes the request + group_id (int): group id + + Raises: + PermissionDenied: If user is not member of the group. + + Returns: + GroupModel: group instance + """ + group = get_entity(GroupModel, pk=group_id) + if not user.groups.contains(group): + raise PermissionDenied("You are not allowed to access this group.") + return group + + @extend_schema( + responses={ + status.HTTP_200_OK: GroupSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + } + ) + def list(self, request: HttpRequest) -> HttpResponse: + """ + Get all groups. + + Args: + request (HttpRequest): request object + + Raises: + PermissionDenied: If user is not a superuser. + + Returns: + HttpResponse: list of groups as json response + """ + if not request.user.is_superuser: + raise PermissionDenied("You are not allowed to access all groups.") + groups = GroupModel.objects.all() + serializer = GroupSerializer(groups, many=True) + return Response(serializer.data) + + @extend_schema( + responses={ + status.HTTP_200_OK: GroupSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[_default_group_example] + ) + def retrieve(self, request: HttpRequest, id: int) -> HttpResponse: + """ + Get group information by id. + + Args: + request (HttpRequest): request object + id (int): group id + + Returns: + HttpResponse: group as json response + """ + group = self._get_group(request.user, id) + serializer = GroupSerializer(group) + return Response(serializer.data) + + @extend_schema( + responses={ + status.HTTP_201_CREATED: GroupSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[OpenApiExample( + name="Create group", + description="Create a new group.", + value={"name": "My new amazing group"}, + )] + ) + def create(self, request: HttpRequest) -> HttpResponse: + """ + Create a new group. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: new created group as json response + """ + serializer = GroupSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def _update(self, request: HttpRequest, id: int, *, partial: bool) -> HttpResponse: + """ + Update group information. + + Args: + request (HttpRequest): request object + id (int): group id + partial (bool): allow partial update + + Returns: + HttpResponse: updated group as json response + """ + group = self._get_group(request.user, id) + serializer = GroupSerializer(group, data=request.data, partial=partial) + serializer.is_valid(raise_exception=True) + serializer.save() + if getattr(group, '_prefetched_objects_cache', None): + # If 'prefetch_related' has been applied to a queryset, we need to + # forcibly invalidate the prefetch cache on the instance. + group._prefetched_objects_cache = {} + return Response(serializer.data) + + @extend_schema( + responses={ + status.HTTP_200_OK: GroupSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[ + _default_group_example, + OpenApiExample( + name="Update group", + description="Update group fields.", + value={"name": "My new amazing group is the best!"}, + ) + ] + ) + def update(self, request: HttpRequest, id: int) -> HttpResponse: + """ + Update group information. + + Args: + request (HttpRequest): request object + id (int): group id + + Returns: + HttpResponse: updated group as json response + """ + return self._update(request, id, partial=False) + + @extend_schema( + responses={ + status.HTTP_200_OK: GroupSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[ + _default_group_example, + OpenApiExample( + name="Update group partially", + description="Update only some group fields.", + value={"name": "My new amazing group is the best!"}, + ) + ] + ) + def partial_update(self, request: HttpRequest, id: int) -> HttpResponse: + """ + Update group information partially. + + Args: + request (HttpRequest): request object + id (int): group id + + Returns: + HttpResponse: updated group as json response + """ + return self._update(request, id, partial=True) + + @extend_schema( + responses={ + status.HTTP_204_NO_CONTENT: None, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[_default_group_example] + ) + def destroy(self, request: HttpRequest, id: int) -> HttpResponse: + """ + Remove group by id. + + Args: + request (HttpRequest): request object + id (int): group id + + Returns: + HttpResponse: 204 NO CONTENT + """ + group = self._get_group(request.user, id) + group.delete() + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/fl_server_api/views/inference.py b/fl_server_api/views/inference.py new file mode 100644 index 0000000..f0c7595 --- /dev/null +++ b/fl_server_api/views/inference.py @@ -0,0 +1,118 @@ +from django.http import HttpRequest, HttpResponse +from drf_spectacular.utils import inline_serializer, extend_schema, OpenApiExample +import json +import pickle +from rest_framework import status +from rest_framework.exceptions import APIException, UnsupportedMediaType, ValidationError +from rest_framework.fields import ListField, DictField, FloatField, CharField +import torch +from typing import Any, Dict, Tuple, Type + +from fl_server_core.exceptions import TorchDeserializationException +from fl_server_core.models import Model +from fl_server_ai.uncertainty import get_uncertainty_class, UncertaintyBase +from ..serializers.generic import ErrorSerializer + +from .base import ViewSet +from ..utils import get_entity + + +class Inference(ViewSet): + + serializer_class = inline_serializer("InferenceSerializer", fields={ + "inference": ListField(child=ListField(child=FloatField())), + "uncertainty": DictField(child=FloatField()) + }) + + @extend_schema( + request=inline_serializer( + "InferenceJsonSerializer", + fields={ + "model_id": CharField(), + "model_input": ListField(child=ListField(child=FloatField())) + } + ), + responses={ + status.HTTP_200_OK: serializer_class, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + }, + examples=[ + OpenApiExample("JSON Example", value={ + "model_id": "mymodel", + "model_input": [ + [1.0, 2.3, -0.4, 3], + [0.01, 9.7, 5.6, 7] + ] + }, request_only=True), + ] + ) + def inference(self, request: HttpRequest) -> HttpResponse: + """ + Processes a request to do inference on a existing model. + + Note that this endpoint can process both JSON data as well as formdata with an + attached pickled input tensor. + Further note that for the provided example to run, the model "mymodel" must have been created + via the model-endpoint first, and the user must be authorized to access it. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: (pickled) results of the inference + """ + match request.content_type.lower(): + case s if s.startswith("multipart/form-data"): + return self._process_post(request) + case s if s.startswith("application/json"): + return self._process_post_json(request) + case _: + # If the content type is specified, but not supported, return 415 + self._logger.error(f"Unknown Content-Type '{request.content_type}'") + raise UnsupportedMediaType( + "Only Content-Type 'application/json' and 'multipart/form-data' is supported." + ) + + def _process_post(self, request: HttpRequest) -> HttpResponse: + try: + model_id = request.POST["model_id"] + uploaded_file = request.FILES.get("model_input") + if not uploaded_file or not uploaded_file.file: + raise ValidationError("No uploaded file 'model_input' not found.") + feature_vectors = uploaded_file.file.read() + except Exception as e: + self._logger.error(e) + raise ValidationError("Inference Request could not be interpreted!") + + model = get_entity(Model, pk=model_id) + input_tensor = pickle.loads(feature_vectors) + _, inference, uncertainty = self.do_inference(model, input_tensor) + response_bytes = pickle.dumps(dict(inference=inference, uncertainty=uncertainty)) + return HttpResponse(response_bytes, content_type="application/octet-stream") + + def _process_post_json(self, request: HttpRequest, body: Any = None) -> HttpResponse: + try: + body = body or json.loads(request.body) + model_id = body["model_id"] + model_input = body["model_input"] + except Exception as e: + self._logger.error(e) + raise ValidationError("Inference Request could not be interpreted!") + + model = get_entity(Model, pk=model_id) + input_tensor = torch.as_tensor(model_input) + uncertainty_cls, inference, uncertainty = self.do_inference(model, input_tensor) + return HttpResponse(uncertainty_cls.to_json(inference, uncertainty), content_type="application/json") + + def do_inference( + self, model: Model, input_tensor: torch.Tensor + ) -> Tuple[Type[UncertaintyBase], torch.Tensor, Dict[str, Any]]: + try: + uncertainty_cls = get_uncertainty_class(model) + inference, uncertainty = uncertainty_cls.prediction(input_tensor, model) + return uncertainty_cls, inference, uncertainty + except TorchDeserializationException as e: + raise APIException(e) + except Exception as e: + self._logger.error(e) + raise APIException("Internal Server Error occurred during inference!") diff --git a/fl_server_api/views/model.py b/fl_server_api/views/model.py new file mode 100644 index 0000000..3e34c93 --- /dev/null +++ b/fl_server_api/views/model.py @@ -0,0 +1,423 @@ +from typing import Any + +from django.db import transaction +from django.db.models import Q +from django.http import HttpRequest, HttpResponse, JsonResponse +from django.http.response import HttpResponseBase +from django.utils.datastructures import MultiValueDictKeyError +from drf_spectacular.utils import extend_schema, OpenApiExample, inline_serializer, PolymorphicProxySerializer, \ + OpenApiResponse +from rest_framework import status +from rest_framework.exceptions import APIException, NotFound, ParseError, PermissionDenied, ValidationError +from rest_framework.response import Response +from rest_framework.fields import UUIDField, CharField + +from fl_server_core.models import ( + GlobalModel as GlobalModelDB, + LocalModel as LocalModelDB, + Metric as MetricDB, + Model as ModelDB, + SWAGModel as SWAGModelDB, + User as UserDB, +) +from fl_server_core.models.training import Training, TrainingState +from fl_server_core.utils.locked_atomic_transaction import locked_atomic_transaction +from fl_server_ai.trainer.events import ModelTestFinished, SWAGRoundFinished, TrainingRoundFinished +from fl_server_ai.trainer.tasks import dispatch_trainer_task + +from .base import ViewSet +from ..utils import get_entity, get_file +from ..serializers.generic import ErrorSerializer, MetricSerializer +from ..serializers.model import ModelSerializer, load_and_create_model_request, GlobalModelSerializer, \ + MeanModelSerializer, SWAGModelSerializer, ModelSerializerNoWeights +from ..openapi import error_response_403 + + +class Model(ViewSet): + + serializer_class = PolymorphicProxySerializer( + "PolymorphicModelSerializer", + [ + GlobalModelSerializer(many=True), + MeanModelSerializer(many=True), + SWAGModelSerializer(many=True) + ], + None, + many=False + ) + + def get_models(self, request: HttpRequest) -> HttpResponse: + """ + Get a list of all models which are related to the requested user. + A model is related to an user if it is owned by the user or if the user + is the actor or a participant of the models training. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: model list as json response + """ + user_ids = Training.objects.filter( + Q(actor=request.user) | Q(participants=request.user) + ).distinct().values_list("model__id", flat=True) + models = ModelDB.objects.filter(Q(owner=request.user) | Q(id__in=user_ids)).distinct() + serializer = ModelSerializer(models, many=True) + return Response(serializer.data) + + @extend_schema( + responses={ + status.HTTP_200_OK: ModelSerializerNoWeights(), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + ) + def get_metadata(self, _request: HttpRequest, id: str) -> HttpResponse: + """ + Get model meta data. + + Args: + request (HttpRequest): request object + id (str): model uuid + + Returns: + HttpResponse: model meta data as json response + """ + model = get_entity(ModelDB, pk=id) + serializer = ModelSerializer(model) + return Response(serializer.data) + + @extend_schema( + responses={ + status.HTTP_200_OK: OpenApiResponse(response=bytes, description="Model is returned as bytes"), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + ) + def get_model(self, _request: HttpRequest, id: str) -> HttpResponseBase: + """ + Download the whole model as pickle file. + + Args: + request (HttpRequest): request object + id (str): model uuid + + Returns: + HttpResponseBase: model as file response or 404 if model not found + """ + model = get_entity(ModelDB, pk=id) + if isinstance(model, SWAGModelDB) and model.swag_first_moment is not None: + if model.swag_second_moment is None: + raise APIException(f"Model {model.id} is in inconsistent state!") + raise NotImplementedError( + "SWAG models need to be returned in 3 parts: model architecture, first moment, second moment" + ) + # NOTE: FileResponse does strange stuff with bytes + # and in case of sqlite the weights will be bytes and not a memoryview + response = HttpResponse(model.weights, content_type="application/octet-stream") + response["Content-Disposition"] = f'filename="model-{id}.pkl"' + return response + + @extend_schema( + request={ + "multipart/form-data": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "description": {"type": "string"}, + "model_file": {"type": "string", "format": "binary"}}, + }, + }, + responses={ + status.HTTP_200_OK: inline_serializer("ModelUploadSerializer", fields={ + "detail": CharField(default="Model Upload Accepted"), + "model_id": UUIDField(), + }), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + ) + def create_model(self, request: HttpRequest) -> HttpResponse: + """ + Upload a global model file. + + The file should be a pickled torch.nn.Module. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: upload success message as json response + """ + model = load_and_create_model_request(request) + return JsonResponse({ + "detail": "Model Upload Accepted", + "model_id": str(model.id), + }, status=status.HTTP_201_CREATED) + + @extend_schema( + responses={ + status.HTTP_200_OK: MetricSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + ) + def get_model_metrics(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Reports all metrics for the selected model. + + Args: + request (HttpRequest): request object + id (str): model UUID + + Returns: + HttpResponse: Metrics as JSON Array + """ + model = get_entity(ModelDB, pk=id) + metrics = MetricDB.objects.filter(model=model).all() + return Response(MetricSerializer(metrics, many=True).data) + + @extend_schema( + request={ + "multipart/form-data": { + "type": "object", + "properties": { + "metric_names": {"type": "list"}, + "metric_values": {"type": "list"}, + }, + }, + }, + responses={ + status.HTTP_200_OK: inline_serializer("MetricUploadResponseSerializer", fields={ + "detail": CharField(default="Model Metrics Upload Accepted"), + "model_id": UUIDField(), + }), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[ + OpenApiExample("Example", value={ + "metric_names": ["accuracy", "training loss"], + "metric_values": [0.6, 0.04] + }, media_type="multipart/form-data") + ] + ) + def create_model_metrics(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Upload model metrics. + + Args: + request (HttpRequest): request object + id (str): model uuid + + Returns: + HttpResponse: upload success message as json response + """ + model = get_entity(ModelDB, pk=id) + formdata = dict(request.POST) + + with locked_atomic_transaction(MetricDB): + self._metric_upload(formdata, model, request.user) + + if isinstance(model, GlobalModelDB): + n_metrics = MetricDB.objects.filter(model=model, step=model.round).distinct("reporter").count() + training = model.get_training() + if training: + if n_metrics == training.participants.count(): + dispatch_trainer_task(training, ModelTestFinished, False) + else: + self._logger.warning(f"Global model {id} is not connected to any training.") + + return JsonResponse({ + "detail": "Model Metrics Upload Accepted", + "model_id": str(model.id), + }, status=status.HTTP_201_CREATED) + + @extend_schema( + request={ + "multipart/form-data": { + "type": "object", + "properties": { + "owner": {"type": "string"}, + "round": {"type": "int"}, + "sample_size": {"type": "int"}, + "metric_names": {"type": "list[string]"}, + "metric_values": {"type": "list[float]"}, + "model_file": {"type": "string", "format": "binary"}, + }, + }, + }, + responses={ + status.HTTP_200_OK: ModelSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + ) + def create_local_model(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Upload a partial trained model file from client. + + Args: + request (HttpRequest): request object + id (str): model uuid of the model, which was used for training + + Returns: + HttpResponse: upload success message as json response + """ + try: + formdata = dict(request.POST) + (round_num,) = formdata["round"] + (sample_size,) = formdata["sample_size"] + round_num, sample_size = int(round_num), int(sample_size) + client = request.user + model_file = get_file(request, "model_file") + global_model = get_entity(GlobalModelDB, pk=id) + + # ensure that a training process coresponding to the model exists, else the process will error out + training = Training.objects.get(model=global_model) + self._verify_valid_update(client, training, round_num, TrainingState.ONGOING) + + local_model = LocalModelDB.objects.create( + base_model=global_model, weights=model_file, + round=round_num, owner=client, sample_size=sample_size + ) + self._metric_upload(formdata, local_model, client, metrics_required=False) + + updates = LocalModelDB.objects.filter(base_model=global_model, round=round_num) + if updates.count() == training.participants.count(): + dispatch_trainer_task(training, TrainingRoundFinished, True) + + return JsonResponse({"detail": "Model Update Accepted"}, status=status.HTTP_201_CREATED) + except Training.DoesNotExist: + raise NotFound(f"Model with ID {id} does not have a training process running") + except (MultiValueDictKeyError, KeyError) as e: + raise ParseError(e) + + @extend_schema( + request={ + "multipart/form-data": { + "type": "object", + "properties": { + "round": {"type": "int"}, + "sample_size": {"type": "int"}, + "first_moment_file": {"type": "string", "format": "binary"}, + "second_moment_file": {"type": "string", "format": "binary"} + }, + }, + }, + responses={ + status.HTTP_200_OK: inline_serializer("MetricUploadSerializer", fields={ + "detail": CharField(default="SWAg Statistics Accepted"), + }), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + ) + def create_swag_stats(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Upload SWAG statistics. + + Args: + request (HttpRequest): request object + id (str): global model uuid + + Raises: + APIException: internal server error + NotFound: model not found + ParseError: request data not valid + + Returns: + HttpResponse: upload success message as json response + """ + try: + client = request.user + formdata = dict(request.POST) + (round_num,) = formdata["round"] + (sample_size,) = formdata["sample_size"] + round_num, sample_size = int(round_num), int(sample_size) + fst_moment = get_file(request, "first_moment_file") + snd_moment = get_file(request, "second_moment_file") + model = get_entity(GlobalModelDB, pk=id) + + # ensure that a training process coresponding to the model exists, else the process will error out + training = Training.objects.get(model=model) + self._verify_valid_update(client, training, round_num, TrainingState.SWAG_ROUND) + + self._save_swag_stats(fst_moment, snd_moment, model, client, sample_size) + + swag_stats_first = MetricDB.objects.filter(model=model, step=model.round, key="SWAG First Moment Local") + swag_stats_second = MetricDB.objects.filter(model=model, step=model.round, key="SWAG Second Moment Local") + + if swag_stats_first.count() != swag_stats_second.count(): + training.state = TrainingState.ERROR + raise APIException("SWAG stats in inconsistent state!") + if swag_stats_first.count() == training.participants.count(): + dispatch_trainer_task(training, SWAGRoundFinished, True) + + return JsonResponse({"detail": "SWAG Statistic Accepted"}, status=status.HTTP_201_CREATED) + except Training.DoesNotExist: + raise NotFound(f"Model with ID {id} does not have a training process running") + except (MultiValueDictKeyError, KeyError) as e: + raise ParseError(e) + except Exception as e: + raise APIException(e) + + @staticmethod + def _save_swag_stats(fst_moment: bytes, snd_moment: bytes, + model: GlobalModelDB, client: UserDB, sample_size: int): + MetricDB.objects.create( + model=model, + key="SWAG First Moment Local", + value_binary=fst_moment, + step=model.round, + reporter=client + ).save() + MetricDB.objects.create( + model=model, + key="SWAG Second Moment Local", + value_binary=snd_moment, + step=model.round, + reporter=client + ).save() + MetricDB.objects.create( + model=model, + key="SWAG Sample Size Local", + value_float=sample_size, + step=model.round, + reporter=client + ).save() + + @transaction.atomic() + def _metric_upload(self, formdata: dict, model: ModelDB, client: UserDB, metrics_required: bool = True): + if "metric_names" not in formdata or "metric_values" not in formdata: + if metrics_required or ("metric_names" in formdata) != ("metric_values" in formdata): + raise ParseError("Metric names or values are missing") + return + if len(formdata["metric_names"]) != len(formdata["metric_values"]): + if metrics_required: + raise ParseError("Metric names and values must have the same length") + return + + for key, value in zip(formdata["metric_names"], formdata["metric_values"]): + try: + metric_float = float(value) + metric_binary = None + except Exception: + metric_float = None + metric_binary = bytes(value, encoding="utf-8") + MetricDB.objects.create( + model=model, + key=key, + value_float=metric_float, + value_binary=metric_binary, + step=model.round, + reporter=client + ).save() + + def _verify_valid_update(self, client: UserDB, train: Training, round_num: int, expected_state: tuple[str, Any]): + if client.id not in [p.id for p in train.participants.all()]: + raise PermissionDenied(f"You are not a participant of training {train.id}!") + if train.state != expected_state: + raise ValidationError(f"Training with ID {train.id} is in state {train.state}") + if int(round_num) != train.model.round: + raise ValidationError(f"Training with ID {train.id} is not currently in round {round_num}") diff --git a/fl_server_api/views/training.py b/fl_server_api/views/training.py new file mode 100644 index 0000000..1741966 --- /dev/null +++ b/fl_server_api/views/training.py @@ -0,0 +1,268 @@ +from django.http import HttpRequest, HttpResponse, JsonResponse +import json +from marshmallow import Schema +from marshmallow.exceptions import ValidationError as MarshmallowValidationError +from rest_framework import status +from rest_framework.exceptions import ParseError, PermissionDenied +from rest_framework.response import Response +from uuid import UUID + +from fl_server_core.models import ( + Model as ModelDB, + Training as TrainingDB, + User as UserDB, +) +from fl_server_core.models.model import clone_model +from fl_server_core.models.training import TrainingState +from fl_server_ai.trainer import ModelTrainer + +from .base import ViewSet +from ..utils import get_entity +from ..serializers.generic import TrainingSerializer +from ..serializers.training import ( + CreateTrainingRequest, CreateTrainingRequestSchema, + ClientAdministrationBody, ClientAdministrationBodySchema +) +from drf_spectacular.utils import extend_schema, inline_serializer +from rest_framework.fields import UUIDField, CharField, IntegerField, ListField +from ..openapi import error_response_403 +from ..serializers.generic import ErrorSerializer + + +class Training(ViewSet): + """ + Federated Learning Platform's API trainings endpoint `/api/trainings`. + This endpoint is used to create and manage trainings. + """ + + serializer_class = TrainingSerializer + + def _check_user_permission_for_training(self, user: UserDB, training_id: UUID | str) -> TrainingDB: + if isinstance(training_id, str): + training_id = UUID(training_id) + training = get_entity(TrainingDB, pk=training_id) + if training.actor != user and user not in training.participants.all(): + raise PermissionDenied() + return training + + def _get_clients_from_body(self, body_raw: bytes) -> list[UserDB]: + body: ClientAdministrationBody = self._load_marshmallow_request(ClientAdministrationBodySchema(), body_raw) + return self._get_clients_from_uuid_list(body.clients) + + def _get_clients_from_uuid_list(self, uuids: list[UUID]) -> list[UserDB]: + if uuids is None or len(uuids) == 0: + return [] + # Note: filter "in" does not raise UserDB.DoesNotExist exceptions + clients = UserDB.objects.filter(id__in=uuids) + if len(clients) != len(uuids): + raise ParseError("Not all provided users were found!") + return clients + + def _load_marshmallow_request(self, schema: Schema, json_data: str | bytes | bytearray): + try: + return schema.load(json.loads(json_data)) # should `schema.loads` be used instead? + except MarshmallowValidationError as e: + raise ParseError(e.messages) + + @extend_schema(responses={ + status.HTTP_200_OK: TrainingSerializer(many=True), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }) + def get_trainings(self, request: HttpRequest) -> HttpResponse: + """ + Get information about all owned trainings. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: list of training data as json response + """ + trainings = TrainingDB.objects.filter(actor=request.user) + serializer = TrainingSerializer(trainings, many=True) + return Response(serializer.data) + + def get_training(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Get information about the selected training. + + Args: + request (HttpRequest): request object + id (str): training uuid + + Returns: + HttpResponse: training data as json response + """ + train = self._check_user_permission_for_training(request.user, id) + serializer = TrainingSerializer(train) + return Response(serializer.data) + + @extend_schema( + request=inline_serializer("EmptyBodySerializer", fields={}), + responses={ + status.HTTP_200_OK: inline_serializer( + "SuccessSerializer", + fields={ + "detail": CharField(default="Training started!") + } + ), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + } + ) + def start_training(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Start training. Will check if at least one participant is registered. + Should be called by an POST request with an empty body. + + Args: + request (HttpRequest): request object + id (str): training uuid + + Returns: + HttpResponse: training data as json response + """ + training = self._check_user_permission_for_training(request.user, id) + if training.participants.count() == 0: + raise ParseError("At least one participant must be registered!") + if training.state != TrainingState.INITIAL: + raise ParseError(f"Training {training.id} is not in state INITIAL!") + ModelTrainer(training).start() + return JsonResponse({"detail": "Training started!"}, status=status.HTTP_202_ACCEPTED) + + @extend_schema( + request=inline_serializer( + "RegisterClientsSerializer", + fields={ + "clients": ListField(child=UUIDField()) + } + ), + responses={ + status.HTTP_200_OK: inline_serializer( + "RegisteredClientsSuccessSerializer", + fields={ + "detail": CharField(default="Users registered as participants!") + } + ), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + } + ) + def register_clients(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Register one or more clients for the training. + Should be called by POST with a json body of the form. + Should be called once before the training is started. + + ```json + {"clients": []} + ``` + + Will check if all the selected clients are registered. + + Args: + request (HttpRequest): request object + id (str): training uuid + + Returns: + HttpResponse: 202 Response if clients were registered, else corresponding error code + """ + train = self._check_user_permission_for_training(request.user, id) + clients = self._get_clients_from_body(request.body) + train.participants.add(*clients) + return JsonResponse({"detail": "Users registered as participants!"}, status=status.HTTP_202_ACCEPTED) + + @extend_schema( + request=inline_serializer( + "RemoveClientsSerializer", + fields={ + "clients": ListField(child=UUIDField()) + } + ), + responses={ + status.HTTP_200_OK: inline_serializer( + "RemovedClientsSuccessSerializer", + fields={ + "detail": CharField(default="Users removed from training participants!") + } + ), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + } + ) + def remove_clients(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Remove clients from the list of registered clients for a training. + This is meant for modification of an already existing training process. + + Args: + request (HttpRequest): request object + id (str): training uuid + + Returns: + HttpResponse: 200 Response if clients were removed, else corresponding error code + """ + train = self._check_user_permission_for_training(request.user, id) + clients = self._get_clients_from_body(request.body) + train.participants.remove(*clients) + return JsonResponse({"detail": "Users removed from training participants!"}) + + @extend_schema( + request=inline_serializer( + name="TrainingCreationSerializer", + fields={ + "model_id": CharField(), + "target_num_updates": IntegerField(), + "metric_names": ListField(child=CharField()), + "aggregation_method": CharField(), + "clients": ListField(child=UUIDField()) + } + ), + responses={ + status.HTTP_200_OK: inline_serializer("TrainingCreatedSerializer", fields={ + "detail": CharField(default="Training created successfully!"), + "model_id": UUIDField(), + }), + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + } + ) + def create_training(self, request: HttpRequest) -> HttpResponse: + """ + Creates a training process. + Should be called by POST according to `CreateTrainingRequestSchema` and + should have a model file (the initial model) as attached FILE. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: 201 if training could be registered + """ + parsed_request: CreateTrainingRequest = self._load_marshmallow_request( + CreateTrainingRequestSchema(), + request.body.decode("utf-8") + ) + model = get_entity(ModelDB, pk=parsed_request.model_id) + if model.owner != request.user: + raise PermissionDenied() + if TrainingDB.objects.filter(model=model).exists(): + # the selected model is already referenced by another training, so we need to copy it + model = clone_model(model) + + clients = self._get_clients_from_uuid_list(parsed_request.clients) + train = TrainingDB.objects.create( + model=model, + actor=request.user, + target_num_updates=parsed_request.target_num_updates, + state=TrainingState.INITIAL, + uncertainty_method=parsed_request.uncertainty_method.value, + aggregation_method=parsed_request.aggregation_method.value, + options=parsed_request.options + ) + train.participants.add(*clients) + return JsonResponse({ + "detail": "Training created successfully!", + "training_id": train.id + }, status=status.HTTP_201_CREATED) diff --git a/fl_server_api/views/user.py b/fl_server_api/views/user.py new file mode 100644 index 0000000..bf3efcf --- /dev/null +++ b/fl_server_api/views/user.py @@ -0,0 +1,149 @@ +from django.db.models import Q +from django.http import HttpRequest, HttpResponse +from drf_spectacular.utils import extend_schema, OpenApiExample, OpenApiParameter +from rest_framework import decorators, status +from rest_framework.response import Response + +from fl_server_core.models import User as UserModel, Training as TrainingModel + +from .base import ViewSet +from ..utils import get_entity +from ..openapi import error_response_403 +from ..serializers.generic import ErrorSerializer, GroupSerializer, TrainingSerializer +from ..serializers.user import UserSerializer + + +class User(ViewSet): + + serializer_class = UserSerializer + + @extend_schema( + responses={ + status.HTTP_200_OK: UserSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + } + ) + def get_users(self, request: HttpRequest) -> HttpResponse: + """ + Get current user information as list. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: user list as json response + """ + serializer = UserSerializer([request.user], many=True) + return Response(serializer.data) + + @extend_schema( + responses={ + status.HTTP_200_OK: UserSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[ + OpenApiExample( + name="Get user by id", + description="Retrieve user data by user ID.", + value="88a9f11a-846b-43b5-bd15-367fc332ba59", + parameter_only=("id", OpenApiParameter.PATH) + ) + ] + ) + def get_user(self, request: HttpRequest, id: str) -> HttpResponse: + """ + Get user information. + + Args: + request (HttpRequest): request object + id (str): user uuid + + Returns: + HttpResponse: user as json response + """ + serializer = UserSerializer(get_entity(UserModel, pk=id), context={"request_user_id": request.user.id}) + return Response(serializer.data) + + @decorators.authentication_classes([]) + @decorators.permission_classes([]) + @extend_schema( + responses={ + status.HTTP_200_OK: UserSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + }, + examples=[ + OpenApiExample("Jane Doe", value={ + "message_endpoint": "http://example.com/", + "actor": True, + "client": True, + "username": "jane", + "first_name": "Jane", + "last_name": "Doe", + "email": "jane.doe@example.com", + "password": "my-super-secret-password" + }) + ] + ) + def create_user(self, request: HttpRequest) -> HttpResponse: + """ + Create a new user. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: new created user as json response + """ + user = UserSerializer().create(request.data) + serializer = UserSerializer(user, context={"request_user_id": user.id}) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + @extend_schema( + responses={ + status.HTTP_200_OK: GroupSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + }, + examples=[ + OpenApiExample( + name="User uuid", + value="88a9f11a-846b-43b5-bd15-367fc332ba59", + parameter_only=("id", OpenApiParameter.PATH) + ) + ] + ) + def get_user_groups(self, request: HttpRequest) -> HttpResponse: + """ + Get user groups. + + Args: + request (HttpRequest): request object + id (str): user uuid + + Returns: + HttpResponse: user groups as json response + """ + serializer = GroupSerializer(request.user.groups, many=True) + return Response(serializer.data) + + @extend_schema( + responses={ + status.HTTP_200_OK: TrainingSerializer, + status.HTTP_400_BAD_REQUEST: ErrorSerializer, + status.HTTP_403_FORBIDDEN: error_response_403, + } + ) + def get_user_trainings(self, request: HttpRequest) -> HttpResponse: + """ + Get user trainings. + + Args: + request (HttpRequest): request object + + Returns: + HttpResponse: user trainings as json response + """ + trainings = TrainingModel.objects.filter(Q(actor=request.user) | Q(participants=request.user)).distinct() + serializer = TrainingSerializer(trainings, many=True) + return Response(serializer.data) diff --git a/fl_server_core/__init__.py b/fl_server_core/__init__.py new file mode 100644 index 0000000..71a9214 --- /dev/null +++ b/fl_server_core/__init__.py @@ -0,0 +1,3 @@ +""" +Core Features +""" diff --git a/fl_server_core/admin.py b/fl_server_core/admin.py new file mode 100644 index 0000000..45d7b0b --- /dev/null +++ b/fl_server_core/admin.py @@ -0,0 +1,46 @@ +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter + +from .models import ( + GlobalModel, + LocalModel, + Metric, + Model, + Training, + User, +) + + +admin.site.register(User, UserAdmin) +admin.site.register(Training) +admin.site.register(Metric) + + +# Flexible and customizable registration + +# @admin.register(ModelUpdate) +# class ModelUpdateAdmin(admin.ModelAdmin): +# pass + + +class ModelChildAdmin(PolymorphicChildModelAdmin): + base_model = Model + + +@admin.register(GlobalModel) +class GlobalModelAdmin(ModelChildAdmin): + base_model = GlobalModel + + +@admin.register(LocalModel) +class LocalModelAdmin(ModelChildAdmin): + base_model = LocalModel + + +@admin.register(Model) +class ModelParentAdmin(PolymorphicParentModelAdmin): + """The parent model admin""" + base_model = Model + child_models = (GlobalModel, LocalModel) + list_filter = (PolymorphicChildModelFilter,) diff --git a/fl_server_core/apps.py b/fl_server_core/apps.py new file mode 100644 index 0000000..34d549f --- /dev/null +++ b/fl_server_core/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class FlServerCoreConfig(AppConfig): + name = "fl_server_core" + verbose_name = "Federated Learning Demonstrator" diff --git a/fl_server_core/exceptions.py b/fl_server_core/exceptions.py new file mode 100644 index 0000000..73e36e5 --- /dev/null +++ b/fl_server_core/exceptions.py @@ -0,0 +1,2 @@ +class TorchDeserializationException(Exception): + pass diff --git a/fl_server_core/migrations/0001_initial.py b/fl_server_core/migrations/0001_initial.py new file mode 100644 index 0000000..736f5be --- /dev/null +++ b/fl_server_core/migrations/0001_initial.py @@ -0,0 +1,123 @@ +# Generated by Django 4.0.10 on 2023-07-13 12:46 + +from django.conf import settings +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import fl_server_core.models.user +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('actor', models.BooleanField(default=False)), + ('client', models.BooleanField(default=False)), + ('message_endpoint', models.URLField()), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + bases=(models.Model, fl_server_core.models.user.NotificationReceiver), + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='Model', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('round', models.IntegerField()), + ('weights', models.BinaryField()), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')), + ], + options={ + 'abstract': False, + 'base_manager_name': 'objects', + }, + ), + migrations.CreateModel( + name='GlobalModel', + fields=[ + ('model_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='fl_server_core.model')), + ('name', models.CharField(max_length=256)), + ('description', models.TextField()), + ('swag_first_moment', models.BinaryField(blank=True, null=True)), + ('swag_second_moment', models.BinaryField(blank=True, null=True)), + ], + options={ + 'abstract': False, + 'base_manager_name': 'objects', + }, + bases=('fl_server_core.model',), + ), + migrations.CreateModel( + name='Training', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('state', models.CharField(choices=[('I', 'Initial'), ('O', 'Ongoing'), ('C', 'Completed'), ('E', 'Error'), ('S', 'SwagRound')], max_length=1)), + ('target_num_updates', models.IntegerField()), + ('last_update', models.DateTimeField(auto_now=True)), + ('uncertainty_method', models.CharField(choices=[('NONE', 'None'), ('SWAG', 'SWAG'), ('ENSEMBLE_LOCAL', 'Ensemble Local'), ('ENSEMBLE_GLOBAL', 'Ensemble Global'), ('MC_DROPOUT', 'MC Dropout')], default='NONE', max_length=32)), + ('aggregation_method', models.CharField(choices=[('AVG', 'Average')], max_length=3)), + ('locked', models.BooleanField(default=False)), + ('actor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='actors', to=settings.AUTH_USER_MODEL)), + ('model', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='fl_server_core.model')), + ('participants', models.ManyToManyField(to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Metric', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('identifier', models.CharField(blank=True, max_length=64, null=True)), + ('key', models.CharField(max_length=32)), + ('value_float', models.FloatField(blank=True, null=True)), + ('value_binary', models.BinaryField(blank=True, null=True)), + ('step', models.IntegerField(blank=True, null=True)), + ('model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fl_server_core.model')), + ('reporter', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='LocalModel', + fields=[ + ('model_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='fl_server_core.model')), + ('sample_size', models.IntegerField()), + ('base_model', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fl_server_core.globalmodel')), + ], + options={ + 'abstract': False, + 'base_manager_name': 'objects', + }, + bases=('fl_server_core.model',), + ), + ] diff --git a/fl_server_core/migrations/0002_remove_globalmodel_swag_first_moment_and_more.py b/fl_server_core/migrations/0002_remove_globalmodel_swag_first_moment_and_more.py new file mode 100644 index 0000000..7f754a0 --- /dev/null +++ b/fl_server_core/migrations/0002_remove_globalmodel_swag_first_moment_and_more.py @@ -0,0 +1,47 @@ +# Generated by Django 4.0.10 on 2023-07-18 09:51 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('fl_server_core', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='globalmodel', + name='swag_first_moment', + ), + migrations.RemoveField( + model_name='globalmodel', + name='swag_second_moment', + ), + migrations.CreateModel( + name='SWAGModel', + fields=[ + ('globalmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='fl_server_core.globalmodel')), + ('swag_first_moment', models.BinaryField()), + ('swag_second_moment', models.BinaryField()), + ], + options={ + 'abstract': False, + 'base_manager_name': 'objects', + }, + bases=('fl_server_core.globalmodel',), + ), + migrations.CreateModel( + name='MeanModel', + fields=[ + ('globalmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='fl_server_core.globalmodel')), + ('models', models.ManyToManyField(related_name='mean_models', to='fl_server_core.globalmodel')), + ], + options={ + 'abstract': False, + 'base_manager_name': 'objects', + }, + bases=('fl_server_core.globalmodel',), + ), + ] diff --git a/fl_server_core/migrations/0003_alter_training_uncertainty_method.py b/fl_server_core/migrations/0003_alter_training_uncertainty_method.py new file mode 100644 index 0000000..63e1a43 --- /dev/null +++ b/fl_server_core/migrations/0003_alter_training_uncertainty_method.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.10 on 2023-07-19 14:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fl_server_core', '0002_remove_globalmodel_swag_first_moment_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='training', + name='uncertainty_method', + field=models.CharField(choices=[('NONE', 'None'), ('SWAG', 'SWAG'), ('ENSEMBLE', 'Ensemble'), ('MC_DROPOUT', 'MC Dropout')], default='NONE', max_length=32), + ), + ] diff --git a/fl_server_core/migrations/0004_training_uncertainty_options.py b/fl_server_core/migrations/0004_training_uncertainty_options.py new file mode 100644 index 0000000..4d9d6ab --- /dev/null +++ b/fl_server_core/migrations/0004_training_uncertainty_options.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0.10 on 2023-07-24 13:43 + +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fl_server_core', '0003_alter_training_uncertainty_method'), + ] + + operations = [ + migrations.AddField( + model_name='training', + name='uncertainty_options', + field=models.JSONField(default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), + ), + ] diff --git a/fl_server_core/migrations/0005_alter_training_aggregation_method_and_more.py b/fl_server_core/migrations/0005_alter_training_aggregation_method_and_more.py new file mode 100644 index 0000000..5f951f0 --- /dev/null +++ b/fl_server_core/migrations/0005_alter_training_aggregation_method_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.0.10 on 2023-08-07 08:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fl_server_core', '0004_training_uncertainty_options'), + ] + + operations = [ + migrations.AlterField( + model_name='training', + name='aggregation_method', + field=models.CharField(choices=[('FedAvg', 'FedAvg'), ('FedDC', 'FedDC'), ('FedProx', 'FedProx')], default='FedAvg', max_length=32), + ), + migrations.AlterField( + model_name='training', + name='uncertainty_method', + field=models.CharField(choices=[('NONE', 'None'), ('ENSEMBLE', 'Ensemble'), ('MC_DROPOUT', 'MC Dropout'), ('SWAG', 'SWAG')], default='NONE', max_length=32), + ), + ] diff --git a/fl_server_core/migrations/0006_rename_uncertainty_options_training_options.py b/fl_server_core/migrations/0006_rename_uncertainty_options_training_options.py new file mode 100644 index 0000000..0bc88ef --- /dev/null +++ b/fl_server_core/migrations/0006_rename_uncertainty_options_training_options.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.10 on 2023-09-27 06:18 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('fl_server_core', '0005_alter_training_aggregation_method_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='training', + old_name='uncertainty_options', + new_name='options', + ), + ] diff --git a/fl_server_core/migrations/0007_globalmodel_input_shape.py b/fl_server_core/migrations/0007_globalmodel_input_shape.py new file mode 100644 index 0000000..cb53dcc --- /dev/null +++ b/fl_server_core/migrations/0007_globalmodel_input_shape.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0.10 on 2024-02-21 08:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fl_server_core', '0006_rename_uncertainty_options_training_options'), + ] + + operations = [ + migrations.AddField( + model_name='globalmodel', + name='input_shape', + field=models.CharField(default=None, max_length=100), + preserve_default=False, + ), + ] diff --git a/fl_server_core/migrations/0008_alter_globalmodel_input_shape.py b/fl_server_core/migrations/0008_alter_globalmodel_input_shape.py new file mode 100644 index 0000000..8549121 --- /dev/null +++ b/fl_server_core/migrations/0008_alter_globalmodel_input_shape.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.10 on 2024-02-21 08:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('fl_server_core', '0007_globalmodel_input_shape'), + ] + + operations = [ + migrations.AlterField( + model_name='globalmodel', + name='input_shape', + field=models.CharField(max_length=100, null=True), + ), + ] diff --git a/fl_server_core/migrations/__init__.py b/fl_server_core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fl_server_core/models/__init__.py b/fl_server_core/models/__init__.py new file mode 100644 index 0000000..ee0e01a --- /dev/null +++ b/fl_server_core/models/__init__.py @@ -0,0 +1,16 @@ +from .metric import Metric +from .model import GlobalModel, LocalModel, MeanModel, Model, SWAGModel +from .training import Training +from .user import User + + +__all__ = [ + "GlobalModel", + "LocalModel", + "Metric", + "MeanModel", + "Model", + "SWAGModel", + "Training", + "User" +] diff --git a/fl_server_core/models/metric.py b/fl_server_core/models/metric.py new file mode 100644 index 0000000..ae9ae7f --- /dev/null +++ b/fl_server_core/models/metric.py @@ -0,0 +1,50 @@ +from django.db import models +from django.db.models import BinaryField, CASCADE, CharField, FloatField, ForeignKey, IntegerField +from torch import Tensor +from torch.nn import Module + +from ..utils.torch_pickle import from_torch_module_or_tensor, to_torch_module_or_tensor + +from .model import Model +from .user import User + + +class Metric(models.Model): + model: ForeignKey = ForeignKey(Model, on_delete=CASCADE) + identifier: CharField = CharField(max_length=64, null=True, blank=True) + key: CharField = CharField(max_length=32) + value_float: FloatField = FloatField(null=True, blank=True) + value_binary: BinaryField = BinaryField(null=True, blank=True) + step: IntegerField = IntegerField(null=True, blank=True) + reporter: ForeignKey = ForeignKey(User, null=True, blank=True, on_delete=CASCADE) + + @property + def value(self) -> float | bytes: + if self.is_float(): + return self.value_float + return self.value_binary + + @value.setter + def value(self, value: float | int | bytes | Module | Tensor): + if isinstance(value, float): + self.value_float = value + elif isinstance(value, int): + self.value_float = float(value) + elif isinstance(value, (Module, Tensor)): + self.value_binary = from_torch_module_or_tensor(value) + else: + self.value_binary = value + + @value.deleter + def value(self): + self.value_float = None + self.value_binary = None + + def is_float(self) -> bool: + return self.value_float is not None + + def is_binary(self) -> bool: + return self.value_binary is not None + + def to_torch(self) -> Module | Tensor: + return to_torch_module_or_tensor(self.value_binary) diff --git a/fl_server_core/models/model.py b/fl_server_core/models/model.py new file mode 100644 index 0000000..c839bdd --- /dev/null +++ b/fl_server_core/models/model.py @@ -0,0 +1,125 @@ +from django.db.models import ( + BinaryField, CASCADE, CharField, ForeignKey, IntegerField, ManyToManyField, TextField, UUIDField +) +from polymorphic.models import PolymorphicModel +import torch +from torch import Tensor +from torch.nn import Module +from typing import Optional, Sequence, TypeVar +from uuid import uuid4 +from copy import copy + +from ..utils.torch_pickle import ( + from_torch_module, to_torch_module, + from_torch_tensor, to_torch_tensor +) + +from .. import models as models +from .user import User + + +class Model(PolymorphicModel): + id: UUIDField = UUIDField(primary_key=True, editable=False, default=uuid4) + owner: ForeignKey = ForeignKey(User, on_delete=CASCADE) + round: IntegerField = IntegerField() + weights: BinaryField = BinaryField() + + def is_global_model(self): + return isinstance(self, GlobalModel) + + def is_local_model(self): + return isinstance(self, LocalModel) + + def get_torch_model(self) -> Module: + return to_torch_module(self.weights) + + def set_torch_model(self, value: Module): + self.weights = from_torch_module(value) + + def get_training(self) -> Optional["models.Training"]: + return models.Training.objects.filter(model=self).first() + + +class GlobalModel(Model): + name: CharField = CharField(max_length=256) + description: TextField = TextField() + input_shape: CharField = CharField(max_length=100, null=True) + + +class SWAGModel(GlobalModel): + swag_first_moment: BinaryField = BinaryField() + swag_second_moment: BinaryField = BinaryField() + + @property + def first_moment(self) -> Tensor: + return to_torch_tensor(self.swag_first_moment) + + @first_moment.setter + def first_moment(self, value: Tensor): + self.swag_first_moment = from_torch_tensor(value) + + @property + def second_moment(self) -> Tensor: + return to_torch_tensor(self.swag_second_moment) + + @second_moment.setter + def second_moment(self, value: Tensor): + self.swag_second_moment = from_torch_tensor(value) + + +class MeanModel(GlobalModel): + models: ManyToManyField = ManyToManyField(GlobalModel, related_name="mean_models") + + def get_torch_model(self) -> Module: + return MeanModule([model.get_torch_model() for model in self.models.all()]) + + def set_torch_model(self, value: Module): + raise NotImplementedError() + + +class LocalModel(Model): + base_model: ForeignKey = ForeignKey(GlobalModel, on_delete=CASCADE) + sample_size: IntegerField = IntegerField() + + def get_training(self) -> Optional["models.Training"]: + return models.Training.objects.filter(model=self.base_model).first() + + +TModel = TypeVar("TModel", bound=Model) + + +class MeanModule(Module): + + def __init__(self, models: Sequence[Model]): + super().__init__() + self.models = models + + def forward(self, input: Tensor) -> Tensor: + return torch.stack([model(input) for model in self.models], dim=0).mean(dim=0) + + +def clone_model(model: Model) -> Model: + """ + Copies a model instance in the database + See https://docs.djangoproject.com/en/5.0/topics/db/queries/#copying-model-instances + and stackoverflow.com/questions/4733609/how-do-i-clone-a-django-model-instance-object-and-save-it-to-the-database + + Args: + model (Model): the model to be copied + + Returns: + Model: New Model instance that is a copy of the old one + """ + model.save() + new_model = copy(model) + new_model.pk = None + new_model.id = None + new_model._state.adding = True + try: + delattr(new_model, '_prefetched_objects_cache') + except AttributeError: + pass + new_model.save() + new_model.owner = model.owner + new_model.save() + return new_model diff --git a/fl_server_core/models/training.py b/fl_server_core/models/training.py new file mode 100644 index 0000000..dca48c7 --- /dev/null +++ b/fl_server_core/models/training.py @@ -0,0 +1,71 @@ +from django.core.serializers.json import DjangoJSONEncoder +from django.db import models +from django.db.models import ( + CASCADE, CharField, ForeignKey, IntegerField, JSONField, ManyToManyField, + OneToOneField, UUIDField, BooleanField +) +from django.db.models.signals import post_save +from django.dispatch import receiver +from django.utils.translation import gettext_lazy as _ +from uuid import uuid4 + +from .model import Model +from .user import User + + +class TrainingState(models.TextChoices): + INITIAL = "I", _("Initial") + ONGOING = "O", _("Ongoing") + COMPLETED = "C", _("Completed") + ERROR = "E", _("Error") + SWAG_ROUND = "S", _("SwagRound") + + +class AggregationMethod(models.TextChoices): + FED_AVG = "FedAvg", _("FedAvg") + FED_DC = "FedDC", _("FedDC") + FED_PROX = "FedProx", _("FedProx") + + +class UncertaintyMethod(models.TextChoices): + NONE = "NONE", _("None") + ENSEMBLE = "ENSEMBLE", _("Ensemble") + MC_DROPOUT = "MC_DROPOUT", _("MC Dropout") + SWAG = "SWAG", _("SWAG") + + +class Training(models.Model): + id: UUIDField = UUIDField(primary_key=True, editable=False, default=uuid4) + model: OneToOneField = OneToOneField(Model, on_delete=CASCADE) + actor: ForeignKey = ForeignKey(User, on_delete=CASCADE, related_name="actors") + participants: ManyToManyField = ManyToManyField(User) + state: CharField = CharField(max_length=1, choices=TrainingState.choices) + target_num_updates: IntegerField = IntegerField() + last_update = models.DateTimeField(auto_now=True) + uncertainty_method: CharField = CharField( + max_length=32, choices=UncertaintyMethod.choices, default=UncertaintyMethod.NONE + ) + aggregation_method: CharField = CharField( + max_length=32, choices=AggregationMethod.choices, default=AggregationMethod.FED_AVG + ) + # HINT: https://docs.djangoproject.com/en/4.2/topics/db/queries/#querying-jsonfield + options: JSONField = JSONField(default=dict, encoder=DjangoJSONEncoder) + locked: BooleanField = BooleanField(default=False) + + +@receiver(post_save, sender=Training) +def post_save_training(sender, instance, created, *args, **kwargs): + """ + Ensure the correct `target_num_updates` is set. + + This method is called after saving a training instance. + It is used to set the `target_num_updates` to the correct value if this training instance is newly created + and daisy chaining is enabled. + """ + if not created: + return + daisy_chain_period = instance.options.get("daisy_chain_period", 0) + if daisy_chain_period <= 0: + return + instance.target_num_updates = instance.target_num_updates * daisy_chain_period + instance.save() diff --git a/fl_server_core/models/user.py b/fl_server_core/models/user.py new file mode 100644 index 0000000..760f6f5 --- /dev/null +++ b/fl_server_core/models/user.py @@ -0,0 +1,25 @@ +from django.conf import settings +from django.contrib.auth.models import AbstractUser +from django.db.models import BooleanField, URLField, UUIDField +from django.db.models.signals import post_save +from django.dispatch import receiver +from rest_framework.authtoken.models import Token +from uuid import UUID, uuid4 + + +class NotificationReceiver(): + id: UUID + message_endpoint: str + + +class User(AbstractUser, NotificationReceiver): + id: UUIDField = UUIDField(primary_key=True, editable=False, default=uuid4) + actor: BooleanField = BooleanField(default=False) + client: BooleanField = BooleanField(default=False) + message_endpoint: URLField = URLField() + + +@receiver(post_save, sender=settings.AUTH_USER_MODEL) +def create_auth_token(sender, instance=None, created=False, **kwargs): + if created: + Token.objects.create(user=instance) diff --git a/fl_server_core/tests/__init__.py b/fl_server_core/tests/__init__.py new file mode 100644 index 0000000..b4c88c3 --- /dev/null +++ b/fl_server_core/tests/__init__.py @@ -0,0 +1,4 @@ +from .dummy import BASE_URL, Dummy + + +__all__ = ["BASE_URL", "Dummy"] diff --git a/fl_server_core/tests/dummy.py b/fl_server_core/tests/dummy.py new file mode 100644 index 0000000..584473e --- /dev/null +++ b/fl_server_core/tests/dummy.py @@ -0,0 +1,162 @@ +import base64 +from django.contrib.auth.models import Group +from django.test import Client +from faker import Faker +from logging import getLogger +import pickle +import random +import torch +from typing import Type +from uuid import uuid4 + +from fl_server_core.models import GlobalModel, LocalModel, Metric, Model, Training, User +from fl_server_core.models.training import AggregationMethod, TrainingState, UncertaintyMethod + + +BASE_URL: str = "http://127.0.0.1:8000/api" + + +class Dummy: + + fake = Faker("en_US") + _logger = getLogger("fl.server.core") + + @classmethod + def create_model(cls, model_cls: Type[Model] = GlobalModel, **kwargs) -> GlobalModel: + args = dict( + name=f"{cls.fake.company()} Model", + description=f"Model created for {cls.fake.catch_phrase()}.", + round=0, + weights=pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + ) + args.update(kwargs) + if "owner" not in args: + args["owner"] = cls.create_user() + model = model_cls.objects.create(**args) + cls._logger.debug(f"Creating Dummy Model with id {model.id}") + return model + + @classmethod + def create_model_update(cls, **kwargs) -> LocalModel: + args = dict( + round=1, + weights=pickle.dumps(torch.nn.Sequential( + torch.nn.Linear(3, 1), + torch.nn.Sigmoid() + )), + sample_size=10, + ) + args.update(kwargs) + args["base_model"] = args["base_model"] if args.__contains__("base_model") else cls.create_model() + args["owner"] = args["owner"] if args.__contains__("owner") else cls.create_client() + model = LocalModel.objects.create(**args) + cls._logger.debug(f"Creating Dummy Model Update with id {model.id}") + return model + + @classmethod + def create_broken_model(cls, **kwargs): + args = dict(weights=pickle.dumps("I am not a torch.nn.Module!")) + args.update(kwargs) + return cls.create_model(**args) + + @classmethod + def create_training(cls, **kwargs): + args = dict( + state=TrainingState.INITIAL, + target_num_updates=0, + uncertainty_method=UncertaintyMethod.NONE, + aggregation_method=AggregationMethod.FED_AVG, + ) + args.update(kwargs) + if args.__contains__("actor"): + model_kwargs = {"owner": args["actor"]} + else: + args["actor"] = cls.create_actor() + model_kwargs = {} + + args["model"] = args["model"] if args.__contains__("model") else cls.create_model(**model_kwargs) + participants = args.pop("participants", [cls.create_client(), cls.create_client()]) + training = Training.objects.create(**args) + cls._logger.debug(f"Creating Dummy Training with id {training.id}") + for participant in participants: + training.participants.add(participant) + training.save() + return training + + @classmethod + def _create_user(cls, **kwargs) -> User: + user = User.objects.create(**kwargs) + user.set_password(kwargs["password"]) + user.save() + cls._logger.debug(f"Creating Dummy User with id {user.id}") + return user + + @classmethod + def create_user(cls, **kwargs): + args = dict( + message_endpoint="https://" + cls.fake.safe_email().replace("@", "."), + actor=False, + client=False, + username=cls.fake.user_name(), + first_name=cls.fake.first_name(), + last_name=cls.fake.last_name(), + email=cls.fake.safe_email(), + password="secret", + ) + args.update(kwargs) + return cls._create_user(**args) + + @classmethod + def create_actor(cls, **kwargs): + kwargs["actor"] = True + kwargs["client"] = False + return cls.create_user(**kwargs) + + @classmethod + def create_client(cls, **kwargs): + kwargs["actor"] = False + kwargs["client"] = True + return cls.create_user(**kwargs) + + @classmethod + def create_user_and_authenticate(cls, client: Client, **kwargs): + args = dict( + username=cls.fake.user_name(), + password="secret", + ) + args.update(kwargs) + credentials = base64.b64encode( + f'{args["username"]}:{args["password"]}'.encode("utf-8") + ).decode("utf-8") + client.defaults["HTTP_AUTHORIZATION"] = "Basic " + credentials + return cls._create_user(**args) + + @classmethod + def create_group(cls, **kwargs): + args = dict( + name=cls.fake.catch_phrase(), + ) + args.update(kwargs) + group = Group.objects.create(**args) + cls._logger.debug(f"Creating Dummy Group with id {group.id}") + return group + + @classmethod + def create_metric(cls, **kwargs): + epoch = random.randint(0, 100) + args = dict( + identifier=str(uuid4()).split("-")[0], + key="NLLoss", + step=epoch, + ) + args.update(kwargs) + if not args.__contains__("value_float") and not args.__contains__("value_binary"): + args["value_float"] = 27.354/(epoch+1) + random.randint(0, 100) / 100 + args["model"] = args["model"] if args.__contains__("model") else cls.create_model() + args["reporter"] = args["reporter"] if args.__contains__("reporter") else cls.create_client() + metric = Metric.objects.create(**args) + cls._logger.debug(f"Creating Dummy Metric with id {metric.id}") + return metric diff --git a/fl_server_core/tests/test_metric.py b/fl_server_core/tests/test_metric.py new file mode 100644 index 0000000..6792e3e --- /dev/null +++ b/fl_server_core/tests/test_metric.py @@ -0,0 +1,75 @@ +from django.test import TestCase + +from .dummy import Dummy + + +class MetricTest(TestCase): + + def test_value_property_for_float(self): + value = 0.42 + metric = Dummy.create_metric(value_float=value) + self.assertTrue(metric.is_float()) + self.assertFalse(metric.is_binary()) + self.assertEqual(value, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(None, metric.value_binary) + value = 0.84 + metric.value_float = value + self.assertEqual(value, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(None, metric.value_binary) + value = 0.98 + metric.value = value + self.assertEqual(value, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(None, metric.value_binary) + del metric.value + self.assertEqual(None, metric.value_float) + self.assertEqual(None, metric.value) + self.assertEqual(None, metric.value_binary) + + def test_value_property_for_integer(self): + value = 42 + metric = Dummy.create_metric(value_float=value) + self.assertTrue(metric.is_float()) + self.assertFalse(metric.is_binary()) + self.assertEqual(value, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(None, metric.value_binary) + value = 98 + metric.value_float = value + self.assertEqual(value, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(None, metric.value_binary) + value = 4711 + metric.value = value + self.assertEqual(value, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(None, metric.value_binary) + del metric.value + self.assertEqual(None, metric.value_float) + self.assertEqual(None, metric.value) + self.assertEqual(None, metric.value_binary) + + def test_value_property_for_binary(self): + value = b"Hello World!" + metric = Dummy.create_metric(value_binary=value) + self.assertFalse(metric.is_float()) + self.assertTrue(metric.is_binary()) + self.assertEqual(None, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(value, metric.value_binary) + value = b"You are looking especially amazing today!" + metric.value_binary = value + self.assertEqual(None, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(value, metric.value_binary) + value = b"Chuck Norris can take a screenshot of his blue screen." + metric.value = value + self.assertEqual(None, metric.value_float) + self.assertEqual(value, metric.value) + self.assertEqual(value, metric.value_binary) + del metric.value + self.assertEqual(None, metric.value_float) + self.assertEqual(None, metric.value) + self.assertEqual(None, metric.value_binary) diff --git a/fl_server_core/tests/test_model.py b/fl_server_core/tests/test_model.py new file mode 100644 index 0000000..eb3c0ee --- /dev/null +++ b/fl_server_core/tests/test_model.py @@ -0,0 +1,30 @@ +from django.test import TestCase + +from ..models.model import clone_model +from .dummy import Dummy + + +class ModelTest(TestCase): + + def test_is_global_model(self): + model = Dummy.create_model() + self.assertTrue(model.is_global_model()) + self.assertFalse(model.is_local_model()) + + def test_is_local_model(self): + model = Dummy.create_model_update() + self.assertFalse(model.is_global_model()) + self.assertTrue(model.is_local_model()) + + def test_clone_model(self): + model1 = Dummy.create_model() + model2 = clone_model(model1) + model2.description = "This Model was duplicated" + model1.description = "This is the original" + + self.assertEqual(model1.name, model2.name) + self.assertEqual(model2.description, "This Model was duplicated") + self.assertEqual(model1.description, "This is the original") + self.assertEqual(model1.owner, model2.owner) + self.assertEqual(model1.round, model2.round) + self.assertEqual(model1.weights, model2.weights) diff --git a/fl_server_core/tests/test_training.py b/fl_server_core/tests/test_training.py new file mode 100644 index 0000000..c4eed4b --- /dev/null +++ b/fl_server_core/tests/test_training.py @@ -0,0 +1,14 @@ +from django.test import TestCase + +from .dummy import Dummy + + +class TrainingTest(TestCase): + + def test_target_num_updates_without_daisy_chain_period(self): + training = Dummy.create_training(target_num_updates=42) + self.assertEqual(42, training.target_num_updates) + + def test_target_num_updates_with_daisy_chain_period(self): + training = Dummy.create_training(target_num_updates=42, options=dict(daisy_chain_period=5)) + self.assertEqual(42 * 5, training.target_num_updates) diff --git a/fl_server_core/utils/locked_atomic_transaction.py b/fl_server_core/utils/locked_atomic_transaction.py new file mode 100644 index 0000000..462fd38 --- /dev/null +++ b/fl_server_core/utils/locked_atomic_transaction.py @@ -0,0 +1,31 @@ +from contextlib import contextmanager +from django.db import transaction +from django.db.models import Model +from django.db.transaction import get_connection + + +@contextmanager +def locked_atomic_transaction(*models: Model): + """ + Create a locked atomic transaction for a model. + + Opens an atomic transaction and locks a specific table until the context is closed. + Original code taken from: + + Attention: "LOCK TABLE" is not available in SQLite, so this function will not work with SQLite. + A possible fix would be to skip the "LOCK TABLE" part for SQLite since transactions in SQLite + lock the whole database anyway. At least if "BEGIN IMMEDIATE TRANSACTION" or + "BEGIN EXCLUSIVE TRANSACTION" is used. The default "BEGIN TRANSACTION" or "BEGIN DEFERRED TRANSACTION" + does not lock the database until the first database access. + + Args: + model (Model): database model + """ + with transaction.atomic(): + tables = ", ".join(map(lambda model: model._meta.db_table, models)) + cursor = get_connection().cursor() + cursor.execute(f"LOCK TABLE {tables}") + try: + yield + finally: + cursor.close() diff --git a/fl_server_core/utils/strings.py b/fl_server_core/utils/strings.py new file mode 100644 index 0000000..9f8033b --- /dev/null +++ b/fl_server_core/utils/strings.py @@ -0,0 +1,30 @@ +from typing import Optional + + +def str2bool(value: Optional[str], fallback: Optional[bool] = None) -> bool: + """ + Convert string to boolean. + + Sources: + + Args: + value (str): value to convert + fallback (Optional[bool], optional): Fallback if value can not be converted. + If None raise ValueError. Defaults to None. + + Raises: + ValueError: value can not be converted and no fallback is specified + + Returns: + bool: boolean interpretation of value + """ + if value is not None: + if isinstance(value, bool): + return value + if value.lower() in ("yes", "true", "t", "y", "1"): + return True + elif value.lower() in ("no", "false", "f", "n", "0"): + return False + if fallback is None: + raise ValueError(f"Can not convert '{value}' to boolean.") + return fallback diff --git a/fl_server_core/utils/torch_pickle.py b/fl_server_core/utils/torch_pickle.py new file mode 100644 index 0000000..9213c2a --- /dev/null +++ b/fl_server_core/utils/torch_pickle.py @@ -0,0 +1,46 @@ +from logging import getLogger +import pickle +from torch import Tensor +from torch.nn import Module +from typing import Any, Tuple, Type, TypeVar + +from ..exceptions import TorchDeserializationException + + +T = TypeVar("T") + + +def to_torch(obj: Any, supported_types: Type[T] | Tuple[Type[T], ...]): + t_obj = pickle.loads(obj) + if isinstance(t_obj, supported_types): + return t_obj + getLogger("fl.server").error("Unpickled object is not a torch object.") + raise TorchDeserializationException("Unpickled object is not a torch object.") + + +def from_torch(obj: Any, *args, **kwargs) -> bytes: + return pickle.dumps(obj, *args, **kwargs) + + +def to_torch_module_or_tensor(obj: Any) -> Module | Tensor: + return to_torch(obj, (Module, Tensor)) + + +def from_torch_module_or_tensor(obj: Module | Tensor, *args, **kwargs) -> bytes: + return from_torch(obj, *args, **kwargs) + + +def to_torch_module(obj: Any) -> Module: + return to_torch(obj, Module) + + +def from_torch_module(obj: Module, *args, **kwargs) -> bytes: + return from_torch(obj, *args, **kwargs) + + +def to_torch_tensor(obj: Any) -> Tensor: + return to_torch(obj, Tensor) + + +def from_torch_tensor(obj: Tensor, *args, **kwargs) -> bytes: + return from_torch(obj, *args, **kwargs) diff --git a/licenses/license.txt b/licenses/license.txt new file mode 100644 index 0000000..4044b4e --- /dev/null +++ b/licenses/license.txt @@ -0,0 +1,10915 @@ +Django +4.0.10 +BSD License +Copyright (c) Django Software Foundation and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Django nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Faker +20.1.0 +MIT License +Copyright (c) 2012 Daniele Faraglia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Jinja2 +3.1.3 +BSD License +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +MarkupSafe +2.1.4 +BSD License +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +PyYAML +6.0.1 +MIT License +Copyright (c) 2017-2021 Ingy döt Net +Copyright (c) 2006-2016 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +amqp +5.2.0 +BSD License +Copyright (c) 2015-2016 Ask Solem & contributors. All rights reserved. +Copyright (c) 2012-2014 GoPivotal, Inc. All rights reserved. +Copyright (c) 2009, 2010, 2011, 2012 Ask Solem, and individual contributors. All rights reserved. +Copyright (C) 2007-2008 Barry Pederson . All rights reserved. + +py-amqp is licensed under The BSD License (3 Clause, also known as +the new BSD license). The license is an OSI approved Open Source +license and is GPL-compatible(1). + +The license text can also be found here: +http://www.opensource.org/licenses/BSD-3-Clause + +License +======= + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Ask Solem, nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ask Solem OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +Footnotes +========= +(1) A GPL-compatible license makes it possible to + combine Celery with other software that is released + under the GPL, it does not mean that we're distributing + Celery under the GPL license. The BSD license, unlike the GPL, + let you distribute a modified version without making your + changes open source. + + +ansi +0.3.7 +MIT License +Copyright (c) 2015 Wijnand Modderman-Lenstra + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +asgiref +3.7.2 +BSD License +Copyright (c) Django Software Foundation and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Django nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +async-timeout +4.0.3 +Apache Software License +Copyright 2016-2020 aio-libs collaboration. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +attrs +23.2.0 +MIT License +The MIT License (MIT) + +Copyright (c) 2015 Hynek Schlawack and the attrs contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +billiard +4.2.0 +BSD License +Copyright (c) 2006-2008, R Oudkerk and Contributors + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of author nor the names of any contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + + + +celery +5.3.6 +BSD License +Copyright (c) 2017-2026 Asif Saif Uddin, core team & contributors. All rights reserved. +Copyright (c) 2015-2016 Ask Solem & contributors. All rights reserved. +Copyright (c) 2012-2014 GoPivotal, Inc. All rights reserved. +Copyright (c) 2009, 2010, 2011, 2012 Ask Solem, and individual contributors. All rights reserved. + +Celery is licensed under The BSD License (3 Clause, also known as +the new BSD license). The license is an OSI approved Open Source +license and is GPL-compatible(1). + +The license text can also be found here: +http://www.opensource.org/licenses/BSD-3-Clause + +License +======= + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Ask Solem, nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ask Solem OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +Documentation License +===================== + +The documentation portion of Celery (the rendered contents of the +"docs" directory of a software distribution or checkout) is supplied +under the "Creative Commons Attribution-ShareAlike 4.0 +International" (CC BY-SA 4.0) License as described by +https://creativecommons.org/licenses/by-sa/4.0/ + +Footnotes +========= +(1) A GPL-compatible license makes it possible to + combine Celery with other software that is released + under the GPL, it does not mean that we're distributing + Celery under the GPL license. The BSD license, unlike the GPL, + let you distribute a modified version without making your + changes open source. + + +certifi +2023.11.17 +Mozilla Public License 2.0 (MPL 2.0) +This package contains a modified version of ca-bundle.crt: + +ca-bundle.crt -- Bundle of CA Root Certificates + +This is a bundle of X.509 certificates of public Certificate Authorities +(CA). These were automatically extracted from Mozilla's root certificates +file (certdata.txt). This file can be found in the mozilla source tree: +https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt +It contains the certificates in PEM format and therefore +can be directly used with curl / libcurl / php_curl, or with +an Apache+mod_ssl webserver for SSL client authentication. +Just configure this file as the SSLCACertificateFile.# + +***** BEGIN LICENSE BLOCK ***** +This Source Code Form is subject to the terms of the Mozilla Public License, +v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain +one at http://mozilla.org/MPL/2.0/. + +***** END LICENSE BLOCK ***** +@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ + + +charset-normalizer +3.3.2 +MIT License +MIT License + +Copyright (c) 2019 TAHRI Ahmed R. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +click +8.1.7 +BSD License +Copyright 2014 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +click-didyoumean +0.3.0 +MIT License +Copyright (c) 2016 Timo Furrer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +click-plugins +1.1.1 +BSD License +New BSD License + +Copyright (c) 2015-2019, Kevin D. Wurster, Sean C. Gillies +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither click-plugins nor the names of its contributors may not be used to + endorse or promote products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +click-repl +0.3.0 +MIT +Copyright (c) 2014-2015 Markus Unterwaditzer & contributors. +Copyright (c) 2016-2026 Asif Saif Uddin & contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +cmake +3.28.1 +Apache Software License; BSD License +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +django-cors-headers +4.1.0 +MIT License +MIT License + +Copyright (c) 2017 Otto Yiu (https://ottoyiu.com) and other contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +django-polymorphic +3.1.0 +BSD License +Copyright (c) 2009 or later by the individual contributors. +Please see the AUTHORS file. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +django-redis +5.2.0 +BSD License +Copyright (c) 2011-2016 Andrey Antukh +Copyright (c) 2011 Sean Bleier + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS`` AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +djangorestframework +3.14.0 +BSD License +# License + +Copyright © 2011-present, [Encode OSS Ltd](https://www.encode.io/). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +dlr-logging +0.0.3.dev0 +Apache Software License + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +docstring-parser +0.15 +MIT License +The MIT License (MIT) + +Copyright (c) 2018 Marcin Kurczewski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +drf-spectacular +0.26.5 +BSD License +Copyright © 2011-present, Encode OSS Ltd. +Copyright © 2019-2021, T. Franzel , Cashlink Technologies GmbH. +Copyright © 2021-present, T. Franzel . + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +filelock +3.13.1 +The Unlicense (Unlicense) +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + + +fl-demonstrator +0.0.1.dev2 +Apache Software License + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +idna +3.6 +BSD License +BSD 3-Clause License + +Copyright (c) 2013-2023, Kim Davies and contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +inflection +0.5.1 +MIT License +Copyright (C) 2012-2020 Janne Vanhala + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +jsonschema +4.21.1 +MIT License +Copyright (c) 2013 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +jsonschema-specifications +2023.12.1 +MIT License +Copyright (c) 2022 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +kombu +5.3.5 +BSD License +Copyright (c) 2015-2016 Ask Solem & contributors. All rights reserved. +Copyright (c) 2012-2014 GoPivotal Inc & contributors. All rights reserved. +Copyright (c) 2009-2012, Ask Solem & contributors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Ask Solem nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ask Solem OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +lit +17.0.6 +Apache Software License +============================================================================== +The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +============================================================================== +Software from third parties included in the LLVM Project: +============================================================================== +The LLVM Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + + + +marshmallow +3.19.0 +MIT License +Copyright 2021 Steven Loria and contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +mpmath +1.3.0 +BSD License +Copyright (c) 2005-2021 Fredrik Johansson and mpmath contributors + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + + +networkx +3.2.1 +BSD License +NetworkX is distributed with the 3-clause BSD license. + +:: + + Copyright (C) 2004-2023, NetworkX Developers + Aric Hagberg + Dan Schult + Pieter Swart + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the NetworkX Developers nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +numpy +1.24.4 +BSD License +Copyright (c) 2005-2022, NumPy Developers. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the NumPy Developers nor the names of any + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---- + +This binary distribution of NumPy also bundles the following software: + + +Name: OpenBLAS +Files: .libs/libopenb*.so +Description: bundled as a dynamically linked library +Availability: https://github.com/xianyi/OpenBLAS/ +License: 3-clause BSD + Copyright (c) 2011-2014, The OpenBLAS Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. Neither the name of the OpenBLAS project nor the names of + its contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Name: LAPACK +Files: .libs/libopenb*.so +Description: bundled in OpenBLAS +Availability: https://github.com/xianyi/OpenBLAS/ +License 3-clause BSD + Copyright (c) 1992-2013 The University of Tennessee and The University + of Tennessee Research Foundation. All rights + reserved. + Copyright (c) 2000-2013 The University of California Berkeley. All + rights reserved. + Copyright (c) 2006-2013 The University of Colorado Denver. All rights + reserved. + + $COPYRIGHT$ + + Additional copyrights may follow + + $HEADER$ + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer listed + in this license in the documentation and/or other materials + provided with the distribution. + + - Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + The copyright holders provide no reassurances that the source code + provided does not infringe any patent, copyright, or any other + intellectual property rights of third parties. The copyright holders + disclaim any liability to any recipient for claims brought against + recipient by any third party for infringement of that parties + intellectual property rights. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Name: GCC runtime library +Files: .libs/libgfortran*.so +Description: dynamically linked to files compiled with gcc +Availability: https://gcc.gnu.org/viewcvs/gcc/ +License: GPLv3 + runtime exception + Copyright (C) 2002-2017 Free Software Foundation, Inc. + + Libgfortran is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + Libgfortran is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . + +---- + +Full text of license texts referred to above follows (that they are +listed below does not necessarily imply the conditions apply to the +present binary release): + +---- + +GCC RUNTIME LIBRARY EXCEPTION + +Version 3.1, 31 March 2009 + +Copyright (C) 2009 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +This GCC Runtime Library Exception ("Exception") is an additional +permission under section 7 of the GNU General Public License, version +3 ("GPLv3"). It applies to a given file (the "Runtime Library") that +bears a notice placed by the copyright holder of the file stating that +the file is governed by GPLv3 along with this Exception. + +When you use GCC to compile a program, GCC may combine portions of +certain GCC header files and runtime libraries with the compiled +program. The purpose of this Exception is to allow compilation of +non-GPL (including proprietary) programs to use, in this way, the +header files and runtime libraries covered by this Exception. + +0. Definitions. + +A file is an "Independent Module" if it either requires the Runtime +Library for execution after a Compilation Process, or makes use of an +interface provided by the Runtime Library, but is not otherwise based +on the Runtime Library. + +"GCC" means a version of the GNU Compiler Collection, with or without +modifications, governed by version 3 (or a specified later version) of +the GNU General Public License (GPL) with the option of using any +subsequent versions published by the FSF. + +"GPL-compatible Software" is software whose conditions of propagation, +modification and use would permit combination with GCC in accord with +the license of GCC. + +"Target Code" refers to output from any compiler for a real or virtual +target processor architecture, in executable form or suitable for +input to an assembler, loader, linker and/or execution +phase. Notwithstanding that, Target Code does not include data in any +format that is used as a compiler intermediate representation, or used +for producing a compiler intermediate representation. + +The "Compilation Process" transforms code entirely represented in +non-intermediate languages designed for human-written code, and/or in +Java Virtual Machine byte code, into Target Code. Thus, for example, +use of source code generators and preprocessors need not be considered +part of the Compilation Process, since the Compilation Process can be +understood as starting with the output of the generators or +preprocessors. + +A Compilation Process is "Eligible" if it is done using GCC, alone or +with other GPL-compatible software, or if it is done without using any +work based on GCC. For example, using non-GPL-compatible Software to +optimize any GCC intermediate representations would not qualify as an +Eligible Compilation Process. + +1. Grant of Additional Permission. + +You have permission to propagate a work of Target Code formed by +combining the Runtime Library with Independent Modules, even if such +propagation would otherwise violate the terms of GPLv3, provided that +all Target Code was generated by Eligible Compilation Processes. You +may then convey such a combination under terms of your choice, +consistent with the licensing of the Independent Modules. + +2. No Weakening of GCC Copyleft. + +The availability of this Exception does not imply any general +presumption that third-party software is unaffected by the copyleft +requirements of the license of GCC. + +---- + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + + +nvidia-cublas-cu11 +11.10.3.66 +Other/Proprietary License +UNKNOWN + +nvidia-cuda-cupti-cu11 +11.7.101 +Other/Proprietary License +UNKNOWN + +nvidia-cuda-nvrtc-cu11 +11.7.99 +Other/Proprietary License +UNKNOWN + +nvidia-cuda-runtime-cu11 +11.7.99 +Other/Proprietary License +UNKNOWN + +nvidia-cudnn-cu11 +8.5.0.96 +Other/Proprietary License +UNKNOWN + +nvidia-cufft-cu11 +10.9.0.58 +Other/Proprietary License +UNKNOWN + +nvidia-curand-cu11 +10.2.10.91 +Other/Proprietary License +UNKNOWN + +nvidia-cusolver-cu11 +11.4.0.1 +Other/Proprietary License +UNKNOWN + +nvidia-cusparse-cu11 +11.7.4.91 +Other/Proprietary License +UNKNOWN + +nvidia-nccl-cu11 +2.14.3 +Other/Proprietary License +UNKNOWN + +nvidia-nvtx-cu11 +11.7.91 +Other/Proprietary License +UNKNOWN + +packaging +23.2 +Apache Software License; BSD License +This software is made available under the terms of *either* of the licenses +found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made +under the terms of *both* these licenses. + + +prompt-toolkit +3.0.43 +BSD License +Copyright (c) 2014, Jonathan Slenders +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +* Neither the name of the {organization} nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +psycopg2-binary +2.9.9 +GNU Library or Lesser General Public License (LGPL) +psycopg2 and the LGPL +--------------------- + +psycopg2 is free software: you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +psycopg2 is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +In addition, as a special exception, the copyright holders give +permission to link this program with the OpenSSL library (or with +modified versions of OpenSSL that use the same license as OpenSSL), +and distribute linked combinations including the two. + +You must obey the GNU Lesser General Public License in all respects for +all of the code used other than OpenSSL. If you modify file(s) with this +exception, you may extend this exception to your version of the file(s), +but you are not obligated to do so. If you do not wish to do so, delete +this exception statement from your version. If you delete this exception +statement from all source files in the program, then also delete it here. + +You should have received a copy of the GNU Lesser General Public License +along with psycopg2 (see the doc/ directory.) +If not, see . + + +Alternative licenses +-------------------- + +The following BSD-like license applies (at your option) to the files following +the pattern ``psycopg/adapter*.{h,c}`` and ``psycopg/microprotocol*.{h,c}``: + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product documentation + would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. + + +python-dateutil +2.8.2 +Apache Software License; BSD License +Copyright 2017- Paul Ganssle +Copyright 2017- dateutil contributors (see AUTHORS file) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +The above license applies to all contributions after 2017-12-01, as well as +all contributions that have been re-licensed (see AUTHORS file for the list of +contributors who have re-licensed their code). +-------------------------------------------------------------------------------- +dateutil - Extensions to the standard Python datetime module. + +Copyright (c) 2003-2011 - Gustavo Niemeyer +Copyright (c) 2012-2014 - Tomi Pieviläinen +Copyright (c) 2014-2016 - Yaron de Leeuw +Copyright (c) 2015- - Paul Ganssle +Copyright (c) 2015- - dateutil contributors (see AUTHORS file) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The above BSD License Applies to all code, even that also covered by Apache 2.0. + +pytz +2023.3.post1 +MIT License +Copyright (c) 2003-2019 Stuart Bishop + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +redis +5.0.1 +MIT License +MIT License + +Copyright (c) 2022-2023, Redis, inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +referencing +0.32.1 +MIT License +Copyright (c) 2022 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +requests +2.31.0 +Apache Software License + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + +rpds-py +0.17.1 +MIT License +Copyright (c) 2023 Julian Berman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +six +1.16.0 +MIT License +Copyright (c) 2010-2020 Benjamin Peterson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +sqlparse +0.4.4 +BSD License +Copyright (c) 2016, Andi Albrecht +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the authors nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +sympy +1.12 +BSD License +Copyright (c) 2006-2023 SymPy Development Team + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of SymPy nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +-------------------------------------------------------------------------------- + +Patches that were taken from the Diofant project (https://github.com/diofant/diofant) +are licensed as: + +Copyright (c) 2006-2018 SymPy Development Team, + 2013-2023 Sergey B Kirpichev + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of Diofant or SymPy nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +-------------------------------------------------------------------------------- + +Submodules taken from the multipledispatch project (https://github.com/mrocklin/multipledispatch) +are licensed as: + +Copyright (c) 2014 Matthew Rocklin + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of multipledispatch nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +-------------------------------------------------------------------------------- + +The files under the directory sympy/parsing/autolev/tests/pydy-example-repo +are directly copied from PyDy project and are licensed as: + +Copyright (c) 2009-2023, PyDy Authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of this project nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL PYDY AUTHORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------------------- + +The files under the directory sympy/parsing/latex +are directly copied from latex2sympy project and are licensed as: + +Copyright 2016, latex2sympy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +torch +2.0.1 +BSD License +From PyTorch: + +Copyright (c) 2016- Facebook, Inc (Adam Paszke) +Copyright (c) 2014- Facebook, Inc (Soumith Chintala) +Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) +Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) +Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) +Copyright (c) 2011-2013 NYU (Clement Farabet) +Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) +Copyright (c) 2006 Idiap Research Institute (Samy Bengio) +Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + +From Caffe2: + +Copyright (c) 2016-present, Facebook Inc. All rights reserved. + +All contributions by Facebook: +Copyright (c) 2016 Facebook Inc. + +All contributions by Google: +Copyright (c) 2015 Google Inc. +All rights reserved. + +All contributions by Yangqing Jia: +Copyright (c) 2015 Yangqing Jia +All rights reserved. + +All contributions by Kakao Brain: +Copyright 2019-2020 Kakao Brain + +All contributions by Cruise LLC: +Copyright (c) 2022 Cruise LLC. +All rights reserved. + +All contributions from Caffe: +Copyright(c) 2013, 2014, 2015, the respective contributors +All rights reserved. + +All other contributions: +Copyright(c) 2015, 2016 the respective contributors +All rights reserved. + +Caffe2 uses a copyright model similar to Caffe: each contributor holds +copyright over their contributions to Caffe2. The project versioning records +all such contribution and copyright details. If a contributor wants to further +mark their specific copyright on a particular contribution, they should +indicate their copyright solely in the commit message of the change when it is +committed. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +The Pytorch repository and source distributions bundle several libraries that are +compatibly licensed. We list these here. + +Name: DCGM +License: Apache-2.0 +Files: third_party/kineto/libkineto/third_party/dynolog/third_party/DCGM + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/third_party/DCGM/LICENSE + +Name: FP16 +License: MIT +Files: third_party/FP16 + For details, see the files concatenated below: third_party/FP16/LICENSE + +Name: FXdiv +License: MIT +Files: third_party/FXdiv + For details, see the files concatenated below: third_party/FXdiv/LICENSE + +Name: NNPACK +License: BSD-2-Clause +Files: third_party/NNPACK + For details, see the files concatenated below: third_party/NNPACK/LICENSE + +Name: QNNPACK +License: BSD-3-Clause +Files: third_party/QNNPACK + For details, see the files concatenated below: third_party/QNNPACK/LICENSE + +Name: VulkanMemoryAllocator +License: MIT +Files: third_party/VulkanMemoryAllocator + For details, see the files concatenated below: third_party/VulkanMemoryAllocator/LICENSE.txt + +Name: XNNPACK +License: BSD-3-Clause +Files: third_party/XNNPACK + For details, see the files concatenated below: third_party/XNNPACK/LICENSE + +Name: benchmark +License: Apache-2.0 +Files: third_party/benchmark, + third_party/onnx/third_party/benchmark, + third_party/onnx-tensorrt/third_party/onnx/third_party/benchmark, + third_party/protobuf/third_party/benchmark + For details, see the files concatenated below: third_party/benchmark/LICENSE, + third_party/onnx/third_party/benchmark/LICENSE, + third_party/onnx-tensorrt/third_party/onnx/third_party/benchmark/LICENSE, + third_party/protobuf/third_party/benchmark/LICENSE + +Name: clog +License: BSD-2-Clause +Files: third_party/QNNPACK/deps/clog, + third_party/cpuinfo/deps/clog, + third_party/fbgemm/third_party/cpuinfo/deps/clog + For details, see the files concatenated below: third_party/QNNPACK/deps/clog/LICENSE, + third_party/cpuinfo/deps/clog/LICENSE, + third_party/fbgemm/third_party/cpuinfo/deps/clog/LICENSE + +Name: colorama +License: BSD-3-Clause +Files: third_party/kineto/libkineto/third_party/dynolog/third_party/DCGM/testing/python3/libs_3rdparty/colorama + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/third_party/DCGM/testing/python3/libs_3rdparty/colorama/LICENSE.txt + +Name: cpplint +License: BSD-3-Clause +Files: third_party/kineto/libkineto/third_party/dynolog/third_party/json/third_party/cpplint, + third_party/nlohmann/tools/cpplint + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/third_party/json/third_party/cpplint/LICENSE, + third_party/nlohmann/tools/cpplint/LICENSE + +Name: cpr +License: MIT +Files: third_party/kineto/libkineto/third_party/dynolog/third_party/cpr + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/third_party/cpr/LICENSE + +Name: cpuinfo +License: BSD-2-Clause +Files: third_party/cpuinfo, + third_party/fbgemm/third_party/cpuinfo + For details, see the files concatenated below: third_party/cpuinfo/LICENSE, + third_party/fbgemm/third_party/cpuinfo/LICENSE + +Name: cudnn_frontend +License: MIT +Files: third_party/cudnn_frontend + For details, see the files concatenated below: third_party/cudnn_frontend/LICENSE.txt + +Name: cutlass +License: BSD-3-Clause +Files: third_party/cutlass, + third_party/fbgemm/third_party/cutlass + For details, see the files concatenated below: third_party/cutlass/LICENSE.txt, + third_party/fbgemm/third_party/cutlass/LICENSE.txt + +Name: dart +License: Apache-2.0 +Files: third_party/flatbuffers/dart + For details, see the files concatenated below: third_party/flatbuffers/dart/LICENSE + +Name: doctest +License: MIT +Files: third_party/kineto/libkineto/third_party/dynolog/third_party/json/test/thirdparty/doctest, + third_party/nlohmann/tests/thirdparty/doctest + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/third_party/json/test/thirdparty/doctest/LICENSE.txt, + third_party/nlohmann/tests/thirdparty/doctest/LICENSE.txt + +Name: dynolog +License: MIT +Files: third_party/kineto/libkineto/third_party/dynolog + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/LICENSE + +Name: eigen +License: BSD-3-Clause +Files: third_party/eigen + For details, see the files concatenated below: third_party/eigen/COPYING.BSD + +Name: enum +License: BSD-3-Clause +Files: third_party/python-enum/enum + For details, see the files concatenated below: third_party/python-enum/enum/LICENSE + +Name: fbgemm +License: BSD-3-Clause +Files: third_party/fbgemm + For details, see the files concatenated below: third_party/fbgemm/LICENSE + +Name: flatbuffers +License: Apache-2.0 +Files: third_party/flatbuffers + For details, see the files concatenated below: third_party/flatbuffers/LICENSE.txt + +Name: fmt +License: MIT with exception +Files: third_party/fmt, + third_party/kineto/libkineto/third_party/dynolog/third_party/fmt, + third_party/kineto/libkineto/third_party/fmt + For details, see the files concatenated below: third_party/fmt/LICENSE.rst, + third_party/kineto/libkineto/third_party/dynolog/third_party/fmt/LICENSE.rst, + third_party/kineto/libkineto/third_party/fmt/LICENSE.rst + +Name: foxi +License: MIT +Files: third_party/foxi + For details, see the files concatenated below: third_party/foxi/LICENSE + +Name: gemmlowp +License: Apache-2.0 +Files: third_party/gemmlowp/gemmlowp + For details, see the files concatenated below: third_party/gemmlowp/gemmlowp/LICENSE + +Name: generator +License: Apache-2.0 +Files: third_party/fbgemm/third_party/googletest/googlemock/scripts/generator, + third_party/googletest/googlemock/scripts/generator, + third_party/kineto/libkineto/third_party/googletest/googlemock/scripts/generator, + third_party/protobuf/third_party/googletest/googlemock/scripts/generator, + third_party/tensorpipe/third_party/googletest/googlemock/scripts/generator + For details, see the files concatenated below: third_party/fbgemm/third_party/googletest/googlemock/scripts/generator/LICENSE, + third_party/googletest/googlemock/scripts/generator/LICENSE, + third_party/kineto/libkineto/third_party/googletest/googlemock/scripts/generator/LICENSE, + third_party/protobuf/third_party/googletest/googlemock/scripts/generator/LICENSE, + third_party/tensorpipe/third_party/googletest/googlemock/scripts/generator/LICENSE + +Name: gloo +License: BSD-3-Clause +Files: third_party/gloo + For details, see the files concatenated below: third_party/gloo/LICENSE + +Name: googlemock +License: BSD-3-Clause +Files: third_party/fbgemm/third_party/googletest/googlemock, + third_party/kineto/libkineto/third_party/googletest/googlemock, + third_party/protobuf/third_party/googletest/googlemock, + third_party/tensorpipe/third_party/googletest/googlemock + For details, see the files concatenated below: third_party/fbgemm/third_party/googletest/googlemock/LICENSE, + third_party/kineto/libkineto/third_party/googletest/googlemock/LICENSE, + third_party/protobuf/third_party/googletest/googlemock/LICENSE, + third_party/tensorpipe/third_party/googletest/googlemock/LICENSE + +Name: googletest +License: BSD-3-Clause +Files: third_party/fbgemm/third_party/googletest, + third_party/fbgemm/third_party/googletest/googletest, + third_party/googletest, + third_party/kineto/libkineto/third_party/dynolog/third_party/googletest, + third_party/kineto/libkineto/third_party/googletest, + third_party/kineto/libkineto/third_party/googletest/googletest, + third_party/protobuf/third_party/googletest, + third_party/protobuf/third_party/googletest/googletest, + third_party/tensorpipe/third_party/googletest, + third_party/tensorpipe/third_party/googletest/googletest + For details, see the files concatenated below: third_party/fbgemm/third_party/googletest/LICENSE, + third_party/fbgemm/third_party/googletest/googletest/LICENSE, + third_party/googletest/LICENSE, + third_party/kineto/libkineto/third_party/dynolog/third_party/googletest/LICENSE, + third_party/kineto/libkineto/third_party/googletest/LICENSE, + third_party/kineto/libkineto/third_party/googletest/googletest/LICENSE, + third_party/protobuf/third_party/googletest/LICENSE, + third_party/protobuf/third_party/googletest/googletest/LICENSE, + third_party/tensorpipe/third_party/googletest/LICENSE, + third_party/tensorpipe/third_party/googletest/googletest/LICENSE + +Name: gtest +License: BSD-3-Clause +Files: third_party/ideep/mkl-dnn/tests/gtest, + third_party/ideep/mkl-dnn/third_party/oneDNN/tests/gtests/gtest + For details, see the files concatenated below: third_party/ideep/mkl-dnn/tests/gtest/LICENSE, + third_party/ideep/mkl-dnn/third_party/oneDNN/tests/gtests/gtest/LICENSE + +Name: hipify_torch +License: MIT +Files: third_party/fbgemm/third_party/hipify_torch + For details, see the files concatenated below: third_party/fbgemm/third_party/hipify_torch/LICENSE.txt + +Name: ideep +License: MIT +Files: third_party/ideep + For details, see the files concatenated below: third_party/ideep/LICENSE + +Name: ios-cmake +License: BSD-3-Clause +Files: third_party/ios-cmake + For details, see the files concatenated below: third_party/ios-cmake/LICENSE + +Name: json +License: MIT +Files: third_party/cudnn_frontend/include/contrib/nlohmann/json + For details, see the files concatenated below: third_party/cudnn_frontend/include/contrib/nlohmann/json/LICENSE.txt + +Name: kineto +License: BSD-3-Clause +Files: third_party/kineto + For details, see the files concatenated below: third_party/kineto/LICENSE + +Name: libnop +License: Apache-2.0 +Files: third_party/tensorpipe/third_party/libnop + For details, see the files concatenated below: third_party/tensorpipe/third_party/libnop/LICENSE + +Name: libuv +License: MIT +Files: third_party/tensorpipe/third_party/libuv + For details, see the files concatenated below: third_party/tensorpipe/third_party/libuv/LICENSE + +Name: miniz-2.1.0 +License: MIT +Files: third_party/miniz-2.1.0 + For details, see the files concatenated below: third_party/miniz-2.1.0/LICENSE + +Name: mkl-dnn +License: Apache-2.0 +Files: third_party/ideep/mkl-dnn + For details, see the files concatenated below: third_party/ideep/mkl-dnn/LICENSE + +Name: nccl +License: BSD-3-Clause +Files: third_party/nccl/nccl + For details, see the files concatenated below: third_party/nccl/nccl/LICENSE.txt + +Name: neon2sse +License: BSD-Source-Code +Files: third_party/neon2sse + For details, see the files concatenated below: third_party/neon2sse/LICENSE + +Name: oneDNN +License: Apache-2.0 +Files: third_party/ideep/mkl-dnn/third_party/oneDNN + For details, see the files concatenated below: third_party/ideep/mkl-dnn/third_party/oneDNN/LICENSE + +Name: onnx +License: Apache-2.0 +Files: third_party/onnx + For details, see the files concatenated below: third_party/onnx/LICENSE + +Name: onnx +License: MIT +Files: third_party/onnx-tensorrt/third_party/onnx + For details, see the files concatenated below: third_party/onnx-tensorrt/third_party/onnx/LICENSE + +Name: onnx-tensorrt +License: MIT +Files: third_party/onnx-tensorrt + For details, see the files concatenated below: third_party/onnx-tensorrt/LICENSE + +Name: pfs +License: Apache-2.0 +Files: third_party/kineto/libkineto/third_party/dynolog/third_party/pfs + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/third_party/pfs/LICENSE + +Name: protobuf +License: BSD-3-Clause +Files: third_party/protobuf + For details, see the files concatenated below: third_party/protobuf/LICENSE + +Name: psimd +License: MIT +Files: third_party/psimd + For details, see the files concatenated below: third_party/psimd/LICENSE + +Name: pthreadpool +License: BSD-2-Clause +Files: third_party/pthreadpool + For details, see the files concatenated below: third_party/pthreadpool/LICENSE + +Name: pybind11 +License: BSD-3-Clause +Files: third_party/onnx/third_party/pybind11, + third_party/onnx-tensorrt/third_party/onnx/third_party/pybind11, + third_party/pybind11, + third_party/tensorpipe/third_party/pybind11 + For details, see the files concatenated below: third_party/onnx/third_party/pybind11/LICENSE, + third_party/onnx-tensorrt/third_party/onnx/third_party/pybind11/LICENSE, + third_party/pybind11/LICENSE, + third_party/tensorpipe/third_party/pybind11/LICENSE + +Name: python-peachpy +License: BSD-2-Clause +Files: third_party/python-peachpy + For details, see the files concatenated below: third_party/python-peachpy/LICENSE.rst + +Name: python-six +License: MIT +Files: third_party/python-six + For details, see the files concatenated below: third_party/python-six/LICENSE + +Name: sleef +License: BSL-1.0 +Files: third_party/sleef + For details, see the files concatenated below: third_party/sleef/LICENSE.txt + +Name: swift +License: Apache-2.0 +Files: third_party/flatbuffers/swift + For details, see the files concatenated below: third_party/flatbuffers/swift/LICENSE + +Name: tb_plugin +License: BSD-3-Clause +Files: third_party/kineto/tb_plugin + For details, see the files concatenated below: third_party/kineto/tb_plugin/LICENSE + +Name: tbb +License: Apache-2.0 +Files: third_party/tbb + For details, see the files concatenated below: third_party/tbb/LICENSE + +Name: tensorpipe +License: BSD-3-Clause +Files: third_party/tensorpipe + For details, see the files concatenated below: third_party/tensorpipe/LICENSE.txt + +Name: test +License: MIT with exception +Files: third_party/kineto/libkineto/third_party/dynolog/third_party/cpr/test + For details, see the files concatenated below: third_party/kineto/libkineto/third_party/dynolog/third_party/cpr/test/LICENSE + +Name: zstd +License: BSD-3-Clause +Files: third_party/zstd + For details, see the files concatenated below: third_party/zstd/LICENSE + +third_party/kineto/libkineto/third_party/dynolog/third_party/DCGM/LICENSE +------------------------------------------------------------------------- +Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +third_party/FP16/LICENSE +------------------------ +The MIT License (MIT) + +Copyright (c) 2017 Facebook Inc. +Copyright (c) 2017 Georgia Institute of Technology +Copyright 2019 Google LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +third_party/FXdiv/LICENSE +------------------------- +The MIT License (MIT) + +Copyright (c) 2017 Facebook Inc. +Copyright (c) 2016-2017 Marat Dukhan + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +third_party/NNPACK/LICENSE +-------------------------- +Copyright (c) 2017 Facebook Inc. +Copyright (c) 2015-2017, Georgia Institute of Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/QNNPACK/LICENSE +--------------------------- +BSD License + +For QNNPACK software + +Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/VulkanMemoryAllocator/LICENSE.txt +--------------------------------------------- +Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +third_party/XNNPACK/LICENSE +--------------------------- +BSD License + +For XNNPACK software + +Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +Copyright 2019 Google LLC + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/benchmark/LICENSE +----------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/onnx/third_party/benchmark/LICENSE +---------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/onnx-tensorrt/third_party/onnx/third_party/benchmark/LICENSE +------------------------------------------------------------------------ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/protobuf/third_party/benchmark/LICENSE +-------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/QNNPACK/deps/clog/LICENSE +------------------------------------- +Copyright (C) 2018 Marat Dukhan +Copyright (c) 2017-2018 Facebook Inc. +Copyright (c) 2017 Georgia Institute of Technology + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/cpuinfo/deps/clog/LICENSE +------------------------------------- +Copyright (C) 2018 Marat Dukhan +Copyright (c) 2017-2018 Facebook Inc. +Copyright (c) 2017 Georgia Institute of Technology + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/third_party/cpuinfo/deps/clog/LICENSE +-------------------------------------------------------- +Copyright (C) 2018 Marat Dukhan +Copyright (c) 2017-2018 Facebook Inc. +Copyright (c) 2017 Georgia Institute of Technology + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/kineto/libkineto/third_party/dynolog/third_party/DCGM/testing/python3/libs_3rdparty/colorama/LICENSE.txt +-------------------------------------------------------------------------------------------------------------------- +Copyright (c) 2010 Jonathan Hartley + +Released under the New BSD license (reproduced below), or alternatively you may +use this software under any OSI approved open source license such as those at +http://opensource.org/licenses/alphabetical + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name(s) of the copyright holders, nor those of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +third_party/kineto/libkineto/third_party/dynolog/third_party/json/third_party/cpplint/LICENSE +--------------------------------------------------------------------------------------------- +cpplint.py and its corresponding unit tests are Copyright (C) 2009 Google Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/nlohmann/tools/cpplint/LICENSE +------------------------------------------ +cpplint.py and its corresponding unit tests are Copyright (C) 2009 Google Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/kineto/libkineto/third_party/dynolog/third_party/cpr/LICENSE +------------------------------------------------------------------------ +This license applies to everything except the contents of the "test" +directory and its subdirectories. + +MIT License + +Copyright (c) 2017-2021 Huu Nguyen +Copyright (c) 2022 libcpr and many other contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +third_party/cpuinfo/LICENSE +--------------------------- +Copyright (c) 2019 Google LLC +Copyright (c) 2017-2018 Facebook Inc. +Copyright (C) 2012-2017 Georgia Institute of Technology +Copyright (C) 2010-2012 Marat Dukhan + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/third_party/cpuinfo/LICENSE +---------------------------------------------- +Copyright (c) 2019 Google LLC +Copyright (c) 2017-2018 Facebook Inc. +Copyright (C) 2012-2017 Georgia Institute of Technology +Copyright (C) 2010-2012 Marat Dukhan + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/cudnn_frontend/LICENSE.txt +-------------------------------------- +/* + * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +third_party/cutlass/LICENSE.txt +------------------------------- +Copyright (c) 2017 - 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/third_party/cutlass/LICENSE.txt +-------------------------------------------------- +Copyright (c) 2017 - 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/flatbuffers/dart/LICENSE +------------------------------------ +The code in lib/flat_buffers.dart is based on code that was releases under the +following license: + +Copyright 2012, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +To the extent permissible, the changes to that code and the other assets in +this package are licensed under the Apache2 license: + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2014 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/kineto/libkineto/third_party/dynolog/third_party/json/test/thirdparty/doctest/LICENSE.txt +----------------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2016-2021 Viktor Kirilov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +third_party/nlohmann/tests/thirdparty/doctest/LICENSE.txt +--------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2016-2021 Viktor Kirilov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +third_party/kineto/libkineto/third_party/dynolog/LICENSE +-------------------------------------------------------- +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +third_party/eigen/COPYING.BSD +----------------------------- +/* + Copyright (c) 2011, Intel Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +third_party/python-enum/enum/LICENSE +------------------------------------ +Copyright (c) 2013, Ethan Furman. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + + Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + Neither the name Ethan Furman nor the names of any + contributors may be used to endorse or promote products + derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/LICENSE +-------------------------- +BSD License + +For FBGEMM software + +Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/flatbuffers/LICENSE.txt +----------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/fmt/LICENSE.rst +--------------------------- +Copyright (c) 2012 - present, Victor Zverovich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. + + +third_party/kineto/libkineto/third_party/dynolog/third_party/fmt/LICENSE.rst +---------------------------------------------------------------------------- +Copyright (c) 2012 - present, Victor Zverovich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. + + +third_party/kineto/libkineto/third_party/fmt/LICENSE.rst +-------------------------------------------------------- +Copyright (c) 2012 - present, Victor Zverovich + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- Optional exception to the license --- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into a machine-executable object form of such +source code, you may redistribute such embedded portions in such object form +without including the above copyright and permission notices. + + +third_party/foxi/LICENSE +------------------------ +MIT License + +Copyright (c) 2019 Lu Fang + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +third_party/gemmlowp/gemmlowp/LICENSE +------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/fbgemm/third_party/googletest/googlemock/scripts/generator/LICENSE +------------------------------------------------------------------------------ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2007] Neal Norwitz + Portions Copyright [2007] Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/googletest/googlemock/scripts/generator/LICENSE +----------------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2007] Neal Norwitz + Portions Copyright [2007] Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/kineto/libkineto/third_party/googletest/googlemock/scripts/generator/LICENSE +---------------------------------------------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2007] Neal Norwitz + Portions Copyright [2007] Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/protobuf/third_party/googletest/googlemock/scripts/generator/LICENSE +-------------------------------------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2007] Neal Norwitz + Portions Copyright [2007] Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/tensorpipe/third_party/googletest/googlemock/scripts/generator/LICENSE +---------------------------------------------------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2007] Neal Norwitz + Portions Copyright [2007] Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/gloo/LICENSE +------------------------ +BSD License + +For Gloo software + +Copyright (c) 2017-present, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/third_party/googletest/googlemock/LICENSE +------------------------------------------------------------ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/kineto/libkineto/third_party/googletest/googlemock/LICENSE +---------------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/protobuf/third_party/googletest/googlemock/LICENSE +-------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/tensorpipe/third_party/googletest/googlemock/LICENSE +---------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/third_party/googletest/LICENSE +------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/third_party/googletest/googletest/LICENSE +------------------------------------------------------------ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/googletest/LICENSE +------------------------------ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/kineto/libkineto/third_party/dynolog/third_party/googletest/LICENSE +------------------------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/kineto/libkineto/third_party/googletest/LICENSE +----------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/kineto/libkineto/third_party/googletest/googletest/LICENSE +---------------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/protobuf/third_party/googletest/LICENSE +--------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/protobuf/third_party/googletest/googletest/LICENSE +-------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/tensorpipe/third_party/googletest/LICENSE +----------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/tensorpipe/third_party/googletest/googletest/LICENSE +---------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/ideep/mkl-dnn/tests/gtest/LICENSE +--------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/ideep/mkl-dnn/third_party/oneDNN/tests/gtests/gtest/LICENSE +----------------------------------------------------------------------- +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/fbgemm/third_party/hipify_torch/LICENSE.txt +------------------------------------------------------- +MIT License + +Copyright (c) 2017 AMD Compute Libraries + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +third_party/ideep/LICENSE +------------------------- +Copyright (c) 2018 Intel Corporation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +third_party/ios-cmake/LICENSE +----------------------------- +Copyright (c) 2011-2014, Andrew Fischer +Copyright (c) 2016, Bogdan Cristea +Copyright (c) 2017, Yangqing Jia + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/cudnn_frontend/include/contrib/nlohmann/json/LICENSE.txt +-------------------------------------------------------------------- +MIT License + +Copyright (c) 2013-2021 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +third_party/kineto/LICENSE +-------------------------- +BSD License + +For Kineto software + +Copyright (c) Meta Platforms, Inc. and affiliates. + +All contributions by Microsoft: +Copyright (c) Microsoft Corporation. (The Azure AI Platform team) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Meta nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/tensorpipe/third_party/libnop/LICENSE +------------------------------------------------- +Copyright 2017 The Native Object Protocols Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +third_party/tensorpipe/third_party/libuv/LICENSE +------------------------------------------------ +libuv is licensed for use as follows: + +==== +Copyright (c) 2015-present libuv project contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +==== + +This license applies to parts of libuv originating from the +https://github.com/joyent/libuv repository: + +==== + +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +==== + +This license applies to all parts of libuv that are not externally +maintained libraries. + +The externally maintained libraries used by libuv are: + + - tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license. + + - inet_pton and inet_ntop implementations, contained in src/inet.c, are + copyright the Internet Systems Consortium, Inc., and licensed under the ISC + license. + + - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three + clause BSD license. + + - pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB. + Three clause BSD license. + + - android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design + Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement + n° 289016). Three clause BSD license. + + +third_party/miniz-2.1.0/LICENSE +------------------------------- +Copyright 2013-2014 RAD Game Tools and Valve Software +Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +third_party/ideep/mkl-dnn/LICENSE +--------------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +third_party/nccl/nccl/LICENSE.txt +--------------------------------- + + Copyright (c) 2015-2020, NVIDIA CORPORATION. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of NVIDIA CORPORATION, Lawrence Berkeley National + Laboratory, the U.S. Department of Energy, nor the names of their + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + The U.S. Department of Energy funded the development of this software + under subcontract 7078610 with Lawrence Berkeley National Laboratory. + + +This code also includes files from the NVIDIA Tools Extension SDK project. + +See: + + https://github.com/NVIDIA/NVTX + +for more information and license details. + + +third_party/neon2sse/LICENSE +---------------------------- +created by Victoria Zhislina, the Senior Application Engineer, Intel Corporation, victoria.zhislina@intel.com + +*** Copyright (C) 2012-2016 Intel Corporation. All rights reserved. + +IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. + +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, copy or use the software. + + License Agreement +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * The name of the copyright holders may not be used to endorse or promote products + derived from this software without specific prior written permission. + +This software is provided by the copyright holders and contributors "as is" and +any express or implied warranties, including, but not limited to, the implied +warranties of merchantability and fitness for a particular purpose are disclaimed. +In no event shall the Intel Corporation or contributors be liable for any direct, +indirect, incidental, special, exemplary, or consequential damages +(including, but not limited to, procurement of substitute goods or services; +loss of use, data, or profits; or business interruption) however caused +and on any theory of liability, whether in contract, strict liability, +or tort (including negligence or otherwise) arising in any way out of +the use of this software, even if advised of the possibility of such damage. + + +third_party/ideep/mkl-dnn/third_party/oneDNN/LICENSE +---------------------------------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + ============================================================================ + + Copyright 2016-2021 Intel Corporation + Copyright 2018 YANDEX LLC + Copyright 2019-2021 FUJITSU LIMITED + Copyright 2020 Arm Limited and affiliates + Copyright 2020 Codeplay Software Limited + Copyright 2021 Alanna Tempest + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + This distribution includes third party software ("third party programs"). + This third party software, even if included with the distribution of + the Intel software, may be governed by separate license terms, including + without limitation, third party license terms, other Intel software license + terms, and open source software license terms. These separate license terms + govern your use of the third party programs as set forth in the + "THIRD-PARTY-PROGRAMS" file. + + +third_party/onnx/LICENSE +------------------------ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/onnx-tensorrt/third_party/onnx/LICENSE +-------------------------------------------------- +Open Neural Network Exchange + +Copyright (c) Facebook, Inc. and Microsoft Corporation. +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +third_party/onnx-tensorrt/LICENSE +--------------------------------- +MIT License + +Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. +Copyright (c) 2018 Open Neural Network Exchange + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +third_party/kineto/libkineto/third_party/dynolog/third_party/pfs/LICENSE +------------------------------------------------------------------------ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2020-present Daniel Trugman + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/protobuf/LICENSE +---------------------------- +Copyright 2008 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. + + +third_party/psimd/LICENSE +------------------------- +The MIT License (MIT) + +Copyright (c) 2017 Facebook Inc. +Copyright (c) 2014-2017 Georgia Institute of Technology +Copyright 2019 Google LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +third_party/pthreadpool/LICENSE +------------------------------- +Copyright 2019 Google LLC +Copyright (c) 2017 Facebook Inc. +Copyright (c) 2015-2017 Georgia Institute of Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +third_party/onnx/third_party/pybind11/LICENSE +--------------------------------------------- +Copyright (c) 2016 Wenzel Jakob , All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of +external contributions to this project including patches, pull requests, etc. + + +third_party/onnx-tensorrt/third_party/onnx/third_party/pybind11/LICENSE +----------------------------------------------------------------------- +Copyright (c) 2016 Wenzel Jakob , All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +You are under no obligation whatsoever to provide any bug fixes, patches, or +upgrades to the features, functionality or performance of the source code +("Enhancements") to anyone; however, if you choose to make your Enhancements +available either publicly, or directly to the author of this software, without +imposing a separate written license agreement for such Enhancements, then you +hereby grant the following license: a non-exclusive, royalty-free perpetual +license to install, use, modify, prepare derivative works, incorporate into +other computer software, distribute, and sublicense such enhancements or +derivative works thereof, in binary and source code form. + + +third_party/pybind11/LICENSE +---------------------------- +Copyright (c) 2016 Wenzel Jakob , All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Please also refer to the file .github/CONTRIBUTING.md, which clarifies licensing of +external contributions to this project including patches, pull requests, etc. + + +third_party/tensorpipe/third_party/pybind11/LICENSE +--------------------------------------------------- +Copyright (c) 2016 Wenzel Jakob , All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Please also refer to the file CONTRIBUTING.md, which clarifies licensing of +external contributions to this project including patches, pull requests, etc. + + +third_party/python-peachpy/LICENSE.rst +-------------------------------------- +============================== +PeachPy license (2-clause BSD) +============================== + +Copyright (c) 2017, Facebook Inc. +Copyright (c) 2013-2017, Georgia Institute of Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/python-six/LICENSE +------------------------------ +Copyright (c) 2010-2017 Benjamin Peterson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +third_party/sleef/LICENSE.txt +----------------------------- +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +third_party/flatbuffers/swift/LICENSE +------------------------------------- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/kineto/tb_plugin/LICENSE +------------------------------------ +BSD License + +For Kineto software + +Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. + +All contributions by Microsoft: +Copyright (c) Microsoft Corporation. (The Azure AI Platform team) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/tbb/LICENSE +----------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +third_party/tensorpipe/LICENSE.txt +---------------------------------- +BSD License + +For TensorPipe software + +Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Meta nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +third_party/kineto/libkineto/third_party/dynolog/third_party/cpr/test/LICENSE +----------------------------------------------------------------------------- +This license applies to everything inside this directory and all +subdirectories. + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + +third_party/zstd/LICENSE +------------------------ +BSD License + +For Zstandard software + +Copyright (c) 2016-present, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +triton +2.0.0 +MIT License +UNKNOWN + +typing_extensions +4.9.0 +Python Software Foundation License +A. HISTORY OF THE SOFTWARE +========================== + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations, which became +Zope Corporation. In 2001, the Python Software Foundation (PSF, see +https://www.python.org/psf/) was formed, a non-profit organization +created specifically to own Python-related Intellectual Property. +Zope Corporation was a sponsoring member of the PSF. + +All Python releases are Open Source (see https://opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases. + + Release Derived Year Owner GPL- + from compatible? (1) + + 0.9.0 thru 1.2 1991-1995 CWI yes + 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes + 1.6 1.5.2 2000 CNRI no + 2.0 1.6 2000 BeOpen.com no + 1.6.1 1.6 2001 CNRI yes (2) + 2.1 2.0+1.6.1 2001 PSF no + 2.0.1 2.0+1.6.1 2001 PSF yes + 2.1.1 2.1+2.0.1 2001 PSF yes + 2.1.2 2.1.1 2002 PSF yes + 2.1.3 2.1.2 2002 PSF yes + 2.2 and above 2.1.1 2001-now PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, + because its license has a choice of law clause. According to + CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 + is "not incompatible" with the GPL. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation; +All Rights Reserved" are retained in Python alone or in any derivative version +prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 +------------------------------------------- + +BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 + +1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an +office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the +Individual or Organization ("Licensee") accessing and otherwise using +this software in source or binary form and its associated +documentation ("the Software"). + +2. Subject to the terms and conditions of this BeOpen Python License +Agreement, BeOpen hereby grants Licensee a non-exclusive, +royalty-free, world-wide license to reproduce, analyze, test, perform +and/or display publicly, prepare derivative works, distribute, and +otherwise use the Software alone or in any derivative version, +provided, however, that the BeOpen Python License is retained in the +Software, alone or in any derivative version prepared by Licensee. + +3. BeOpen is making the Software available to Licensee on an "AS IS" +basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE +SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS +AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY +DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +5. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +6. This License Agreement shall be governed by and interpreted in all +respects by the law of the State of California, excluding conflict of +law provisions. Nothing in this License Agreement shall be deemed to +create any relationship of agency, partnership, or joint venture +between BeOpen and Licensee. This License Agreement does not grant +permission to use BeOpen trademarks or trade names in a trademark +sense to endorse or promote products or services of Licensee, or any +third party. As an exception, the "BeOpen Python" logos available at +http://www.pythonlabs.com/logos.html may be used according to the +permissions granted on that web page. + +7. By copying, installing or otherwise using the software, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. + + +CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 +--------------------------------------- + +1. This LICENSE AGREEMENT is between the Corporation for National +Research Initiatives, having an office at 1895 Preston White Drive, +Reston, VA 20191 ("CNRI"), and the Individual or Organization +("Licensee") accessing and otherwise using Python 1.6.1 software in +source or binary form and its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, CNRI +hereby grants Licensee a nonexclusive, royalty-free, world-wide +license to reproduce, analyze, test, perform and/or display publicly, +prepare derivative works, distribute, and otherwise use Python 1.6.1 +alone or in any derivative version, provided, however, that CNRI's +License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) +1995-2001 Corporation for National Research Initiatives; All Rights +Reserved" are retained in Python 1.6.1 alone or in any derivative +version prepared by Licensee. Alternately, in lieu of CNRI's License +Agreement, Licensee may substitute the following text (omitting the +quotes): "Python 1.6.1 is made available subject to the terms and +conditions in CNRI's License Agreement. This Agreement together with +Python 1.6.1 may be located on the internet using the following +unique, persistent identifier (known as a handle): 1895.22/1013. This +Agreement may also be obtained from a proxy server on the internet +using the following URL: http://hdl.handle.net/1895.22/1013". + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python 1.6.1 or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python 1.6.1. + +4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" +basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. This License Agreement shall be governed by the federal +intellectual property law of the United States, including without +limitation the federal copyright law, and, to the extent such +U.S. federal law does not apply, by the law of the Commonwealth of +Virginia, excluding Virginia's conflict of law provisions. +Notwithstanding the foregoing, with regard to derivative works based +on Python 1.6.1 that incorporate non-separable material that was +previously distributed under the GNU General Public License (GPL), the +law of the Commonwealth of Virginia shall govern this License +Agreement only as to issues arising under or with respect to +Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this +License Agreement shall be deemed to create any relationship of +agency, partnership, or joint venture between CNRI and Licensee. This +License Agreement does not grant permission to use CNRI trademarks or +trade name in a trademark sense to endorse or promote products or +services of Licensee, or any third party. + +8. By clicking on the "ACCEPT" button where indicated, or by copying, +installing or otherwise using Python 1.6.1, Licensee agrees to be +bound by the terms and conditions of this License Agreement. + + ACCEPT + + +CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 +-------------------------------------------------- + +Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, +The Netherlands. All rights reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + + +tzdata +2023.4 +Apache Software License +Apache Software License 2.0 + +Copyright (c) 2020, Paul Ganssle (Google) + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +uritemplate +4.1.1 +Apache Software License; BSD License +This software is made available under the terms of *either* of the licenses +found in LICENSE.APACHE or LICENSE.BSD. Contributions to uritemplate are +made under the terms of *both* these licenses. + + +urllib3 +2.1.0 +MIT License +MIT License + +Copyright (c) 2008-2020 Andrey Petrov and contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +vine +5.1.0 +BSD License +Copyright (c) 2015-2016 Ask Solem & contributors. All rights reserved. + +Vine is licensed under The BSD License (3 Clause, also known as +the new BSD license). The license is an OSI approved Open Source +license and is GPL-compatible(1). + +The license text can also be found here: +http://www.opensource.org/licenses/BSD-3-Clause + +License +======= + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Ask Solem, nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ask Solem OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +Documentation License +===================== + +The documentation portion of Vine (the rendered contents of the +"docs" directory of a software distribution or checkout) is supplied +under the "Creative Commons Attribution-ShareAlike 4.0 +International" (CC BY-SA 4.0) License as described by +http://creativecommons.org/licenses/by-sa/4.0/ + +Footnotes +========= +(1) A GPL-compatible license makes it possible to + combine Vine with other software that is released + under the GPL, it does not mean that we're distributing + Vine under the GPL license. The BSD license, unlike the GPL, + let you distribute a modified version without making your + changes open source. + + diff --git a/licenses/license_info.csv b/licenses/license_info.csv new file mode 100644 index 0000000..18dd45b --- /dev/null +++ b/licenses/license_info.csv @@ -0,0 +1,69 @@ +"Name","Version","License" +"Django","4.0.10","BSD License" +"Faker","20.1.0","MIT License" +"Jinja2","3.1.3","BSD License" +"MarkupSafe","2.1.4","BSD License" +"PyYAML","6.0.1","MIT License" +"amqp","5.2.0","BSD License" +"ansi","0.3.7","MIT License" +"asgiref","3.7.2","BSD License" +"async-timeout","4.0.3","Apache Software License" +"attrs","23.2.0","MIT License" +"billiard","4.2.0","BSD License" +"celery","5.3.6","BSD License" +"certifi","2023.11.17","Mozilla Public License 2.0 (MPL 2.0)" +"charset-normalizer","3.3.2","MIT License" +"click","8.1.7","BSD License" +"click-didyoumean","0.3.0","MIT License" +"click-plugins","1.1.1","BSD License" +"click-repl","0.3.0","MIT" +"cmake","3.28.1","Apache Software License; BSD License" +"django-cors-headers","4.1.0","MIT License" +"django-polymorphic","3.1.0","BSD License" +"django-redis","5.2.0","BSD License" +"djangorestframework","3.14.0","BSD License" +"dlr-logging","0.0.3.dev0","Apache Software License" +"docstring-parser","0.15","MIT License" +"drf-spectacular","0.26.5","BSD License" +"filelock","3.13.1","The Unlicense (Unlicense)" +"fl-demonstrator","0.0.1.dev2","Apache Software License" +"idna","3.6","BSD License" +"inflection","0.5.1","MIT License" +"jsonschema","4.21.1","MIT License" +"jsonschema-specifications","2023.12.1","MIT License" +"kombu","5.3.5","BSD License" +"lit","17.0.6","Apache Software License" +"marshmallow","3.19.0","MIT License" +"mpmath","1.3.0","BSD License" +"networkx","3.2.1","BSD License" +"numpy","1.24.4","BSD License" +"nvidia-cublas-cu11","11.10.3.66","Other/Proprietary License" +"nvidia-cuda-cupti-cu11","11.7.101","Other/Proprietary License" +"nvidia-cuda-nvrtc-cu11","11.7.99","Other/Proprietary License" +"nvidia-cuda-runtime-cu11","11.7.99","Other/Proprietary License" +"nvidia-cudnn-cu11","8.5.0.96","Other/Proprietary License" +"nvidia-cufft-cu11","10.9.0.58","Other/Proprietary License" +"nvidia-curand-cu11","10.2.10.91","Other/Proprietary License" +"nvidia-cusolver-cu11","11.4.0.1","Other/Proprietary License" +"nvidia-cusparse-cu11","11.7.4.91","Other/Proprietary License" +"nvidia-nccl-cu11","2.14.3","Other/Proprietary License" +"nvidia-nvtx-cu11","11.7.91","Other/Proprietary License" +"packaging","23.2","Apache Software License; BSD License" +"prompt-toolkit","3.0.43","BSD License" +"psycopg2-binary","2.9.9","GNU Library or Lesser General Public License (LGPL)" +"python-dateutil","2.8.2","Apache Software License; BSD License" +"pytz","2023.3.post1","MIT License" +"redis","5.0.1","MIT License" +"referencing","0.32.1","MIT License" +"requests","2.31.0","Apache Software License" +"rpds-py","0.17.1","MIT License" +"six","1.16.0","MIT License" +"sqlparse","0.4.4","BSD License" +"sympy","1.12","BSD License" +"torch","2.0.1","BSD License" +"triton","2.0.0","MIT License" +"typing_extensions","4.9.0","Python Software Foundation License" +"tzdata","2023.4","Apache Software License" +"uritemplate","4.1.1","Apache Software License; BSD License" +"urllib3","2.1.0","MIT License" +"vine","5.1.0","BSD License" diff --git a/licenses/license_info.json b/licenses/license_info.json new file mode 100644 index 0000000..7ecdec1 --- /dev/null +++ b/licenses/license_info.json @@ -0,0 +1,342 @@ +[ + { + "License": "BSD License", + "Name": "Django", + "Version": "4.0.10" + }, + { + "License": "MIT License", + "Name": "Faker", + "Version": "20.1.0" + }, + { + "License": "BSD License", + "Name": "Jinja2", + "Version": "3.1.3" + }, + { + "License": "BSD License", + "Name": "MarkupSafe", + "Version": "2.1.4" + }, + { + "License": "MIT License", + "Name": "PyYAML", + "Version": "6.0.1" + }, + { + "License": "BSD License", + "Name": "amqp", + "Version": "5.2.0" + }, + { + "License": "MIT License", + "Name": "ansi", + "Version": "0.3.7" + }, + { + "License": "BSD License", + "Name": "asgiref", + "Version": "3.7.2" + }, + { + "License": "Apache Software License", + "Name": "async-timeout", + "Version": "4.0.3" + }, + { + "License": "MIT License", + "Name": "attrs", + "Version": "23.2.0" + }, + { + "License": "BSD License", + "Name": "billiard", + "Version": "4.2.0" + }, + { + "License": "BSD License", + "Name": "celery", + "Version": "5.3.6" + }, + { + "License": "Mozilla Public License 2.0 (MPL 2.0)", + "Name": "certifi", + "Version": "2023.11.17" + }, + { + "License": "MIT License", + "Name": "charset-normalizer", + "Version": "3.3.2" + }, + { + "License": "BSD License", + "Name": "click", + "Version": "8.1.7" + }, + { + "License": "MIT License", + "Name": "click-didyoumean", + "Version": "0.3.0" + }, + { + "License": "BSD License", + "Name": "click-plugins", + "Version": "1.1.1" + }, + { + "License": "MIT", + "Name": "click-repl", + "Version": "0.3.0" + }, + { + "License": "Apache Software License; BSD License", + "Name": "cmake", + "Version": "3.28.1" + }, + { + "License": "MIT License", + "Name": "django-cors-headers", + "Version": "4.1.0" + }, + { + "License": "BSD License", + "Name": "django-polymorphic", + "Version": "3.1.0" + }, + { + "License": "BSD License", + "Name": "django-redis", + "Version": "5.2.0" + }, + { + "License": "BSD License", + "Name": "djangorestframework", + "Version": "3.14.0" + }, + { + "License": "Apache Software License", + "Name": "dlr-logging", + "Version": "0.0.3.dev0" + }, + { + "License": "MIT License", + "Name": "docstring-parser", + "Version": "0.15" + }, + { + "License": "BSD License", + "Name": "drf-spectacular", + "Version": "0.26.5" + }, + { + "License": "The Unlicense (Unlicense)", + "Name": "filelock", + "Version": "3.13.1" + }, + { + "License": "Apache Software License", + "Name": "fl-demonstrator", + "Version": "0.0.1.dev2" + }, + { + "License": "BSD License", + "Name": "idna", + "Version": "3.6" + }, + { + "License": "MIT License", + "Name": "inflection", + "Version": "0.5.1" + }, + { + "License": "MIT License", + "Name": "jsonschema", + "Version": "4.21.1" + }, + { + "License": "MIT License", + "Name": "jsonschema-specifications", + "Version": "2023.12.1" + }, + { + "License": "BSD License", + "Name": "kombu", + "Version": "5.3.5" + }, + { + "License": "Apache Software License", + "Name": "lit", + "Version": "17.0.6" + }, + { + "License": "MIT License", + "Name": "marshmallow", + "Version": "3.19.0" + }, + { + "License": "BSD License", + "Name": "mpmath", + "Version": "1.3.0" + }, + { + "License": "BSD License", + "Name": "networkx", + "Version": "3.2.1" + }, + { + "License": "BSD License", + "Name": "numpy", + "Version": "1.24.4" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cublas-cu11", + "Version": "11.10.3.66" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cuda-cupti-cu11", + "Version": "11.7.101" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cuda-nvrtc-cu11", + "Version": "11.7.99" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cuda-runtime-cu11", + "Version": "11.7.99" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cudnn-cu11", + "Version": "8.5.0.96" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cufft-cu11", + "Version": "10.9.0.58" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-curand-cu11", + "Version": "10.2.10.91" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cusolver-cu11", + "Version": "11.4.0.1" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cusparse-cu11", + "Version": "11.7.4.91" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-nccl-cu11", + "Version": "2.14.3" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-nvtx-cu11", + "Version": "11.7.91" + }, + { + "License": "Apache Software License; BSD License", + "Name": "packaging", + "Version": "23.2" + }, + { + "License": "BSD License", + "Name": "prompt-toolkit", + "Version": "3.0.43" + }, + { + "License": "GNU Library or Lesser General Public License (LGPL)", + "Name": "psycopg2-binary", + "Version": "2.9.9" + }, + { + "License": "Apache Software License; BSD License", + "Name": "python-dateutil", + "Version": "2.8.2" + }, + { + "License": "MIT License", + "Name": "pytz", + "Version": "2023.3.post1" + }, + { + "License": "MIT License", + "Name": "redis", + "Version": "5.0.1" + }, + { + "License": "MIT License", + "Name": "referencing", + "Version": "0.32.1" + }, + { + "License": "Apache Software License", + "Name": "requests", + "Version": "2.31.0" + }, + { + "License": "MIT License", + "Name": "rpds-py", + "Version": "0.17.1" + }, + { + "License": "MIT License", + "Name": "six", + "Version": "1.16.0" + }, + { + "License": "BSD License", + "Name": "sqlparse", + "Version": "0.4.4" + }, + { + "License": "BSD License", + "Name": "sympy", + "Version": "1.12" + }, + { + "License": "BSD License", + "Name": "torch", + "Version": "2.0.1" + }, + { + "License": "MIT License", + "Name": "triton", + "Version": "2.0.0" + }, + { + "License": "Python Software Foundation License", + "Name": "typing_extensions", + "Version": "4.9.0" + }, + { + "License": "Apache Software License", + "Name": "tzdata", + "Version": "2023.4" + }, + { + "License": "Apache Software License; BSD License", + "Name": "uritemplate", + "Version": "4.1.1" + }, + { + "License": "MIT License", + "Name": "urllib3", + "Version": "2.1.0" + }, + { + "License": "BSD License", + "Name": "vine", + "Version": "5.1.0" + } +] diff --git a/licenses/license_info.md b/licenses/license_info.md new file mode 100644 index 0000000..ea113cb --- /dev/null +++ b/licenses/license_info.md @@ -0,0 +1,70 @@ +| Name | Version | License | +|---------------------------|--------------|-----------------------------------------------------| +| Django | 4.0.10 | BSD License | +| Faker | 20.1.0 | MIT License | +| Jinja2 | 3.1.3 | BSD License | +| MarkupSafe | 2.1.4 | BSD License | +| PyYAML | 6.0.1 | MIT License | +| amqp | 5.2.0 | BSD License | +| ansi | 0.3.7 | MIT License | +| asgiref | 3.7.2 | BSD License | +| async-timeout | 4.0.3 | Apache Software License | +| attrs | 23.2.0 | MIT License | +| billiard | 4.2.0 | BSD License | +| celery | 5.3.6 | BSD License | +| certifi | 2023.11.17 | Mozilla Public License 2.0 (MPL 2.0) | +| charset-normalizer | 3.3.2 | MIT License | +| click | 8.1.7 | BSD License | +| click-didyoumean | 0.3.0 | MIT License | +| click-plugins | 1.1.1 | BSD License | +| click-repl | 0.3.0 | MIT | +| cmake | 3.28.1 | Apache Software License; BSD License | +| django-cors-headers | 4.1.0 | MIT License | +| django-polymorphic | 3.1.0 | BSD License | +| django-redis | 5.2.0 | BSD License | +| djangorestframework | 3.14.0 | BSD License | +| dlr-logging | 0.0.3.dev0 | Apache Software License | +| docstring-parser | 0.15 | MIT License | +| drf-spectacular | 0.26.5 | BSD License | +| filelock | 3.13.1 | The Unlicense (Unlicense) | +| fl-demonstrator | 0.0.1.dev2 | Apache Software License | +| idna | 3.6 | BSD License | +| inflection | 0.5.1 | MIT License | +| jsonschema | 4.21.1 | MIT License | +| jsonschema-specifications | 2023.12.1 | MIT License | +| kombu | 5.3.5 | BSD License | +| lit | 17.0.6 | Apache Software License | +| marshmallow | 3.19.0 | MIT License | +| mpmath | 1.3.0 | BSD License | +| networkx | 3.2.1 | BSD License | +| numpy | 1.24.4 | BSD License | +| nvidia-cublas-cu11 | 11.10.3.66 | Other/Proprietary License | +| nvidia-cuda-cupti-cu11 | 11.7.101 | Other/Proprietary License | +| nvidia-cuda-nvrtc-cu11 | 11.7.99 | Other/Proprietary License | +| nvidia-cuda-runtime-cu11 | 11.7.99 | Other/Proprietary License | +| nvidia-cudnn-cu11 | 8.5.0.96 | Other/Proprietary License | +| nvidia-cufft-cu11 | 10.9.0.58 | Other/Proprietary License | +| nvidia-curand-cu11 | 10.2.10.91 | Other/Proprietary License | +| nvidia-cusolver-cu11 | 11.4.0.1 | Other/Proprietary License | +| nvidia-cusparse-cu11 | 11.7.4.91 | Other/Proprietary License | +| nvidia-nccl-cu11 | 2.14.3 | Other/Proprietary License | +| nvidia-nvtx-cu11 | 11.7.91 | Other/Proprietary License | +| packaging | 23.2 | Apache Software License; BSD License | +| prompt-toolkit | 3.0.43 | BSD License | +| psycopg2-binary | 2.9.9 | GNU Library or Lesser General Public License (LGPL) | +| python-dateutil | 2.8.2 | Apache Software License; BSD License | +| pytz | 2023.3.post1 | MIT License | +| redis | 5.0.1 | MIT License | +| referencing | 0.32.1 | MIT License | +| requests | 2.31.0 | Apache Software License | +| rpds-py | 0.17.1 | MIT License | +| six | 1.16.0 | MIT License | +| sqlparse | 0.4.4 | BSD License | +| sympy | 1.12 | BSD License | +| torch | 2.0.1 | BSD License | +| triton | 2.0.0 | MIT License | +| typing_extensions | 4.9.0 | Python Software Foundation License | +| tzdata | 2023.4 | Apache Software License | +| uritemplate | 4.1.1 | Apache Software License; BSD License | +| urllib3 | 2.1.0 | MIT License | +| vine | 5.1.0 | BSD License | diff --git a/licenses/license_info.no_versions.csv b/licenses/license_info.no_versions.csv new file mode 100644 index 0000000..6801383 --- /dev/null +++ b/licenses/license_info.no_versions.csv @@ -0,0 +1,69 @@ +"Name","License" +"Django","BSD License" +"Faker","MIT License" +"Jinja2","BSD License" +"MarkupSafe","BSD License" +"PyYAML","MIT License" +"amqp","BSD License" +"ansi","MIT License" +"asgiref","BSD License" +"async-timeout","Apache Software License" +"attrs","MIT License" +"billiard","BSD License" +"celery","BSD License" +"certifi","Mozilla Public License 2.0 (MPL 2.0)" +"charset-normalizer","MIT License" +"click","BSD License" +"click-didyoumean","MIT License" +"click-plugins","BSD License" +"click-repl","MIT" +"cmake","Apache Software License; BSD License" +"django-cors-headers","MIT License" +"django-polymorphic","BSD License" +"django-redis","BSD License" +"djangorestframework","BSD License" +"dlr-logging","Apache Software License" +"docstring-parser","MIT License" +"drf-spectacular","BSD License" +"filelock","The Unlicense (Unlicense)" +"fl-demonstrator","Apache Software License" +"idna","BSD License" +"inflection","MIT License" +"jsonschema","MIT License" +"jsonschema-specifications","MIT License" +"kombu","BSD License" +"lit","Apache Software License" +"marshmallow","MIT License" +"mpmath","BSD License" +"networkx","BSD License" +"numpy","BSD License" +"nvidia-cublas-cu11","Other/Proprietary License" +"nvidia-cuda-cupti-cu11","Other/Proprietary License" +"nvidia-cuda-nvrtc-cu11","Other/Proprietary License" +"nvidia-cuda-runtime-cu11","Other/Proprietary License" +"nvidia-cudnn-cu11","Other/Proprietary License" +"nvidia-cufft-cu11","Other/Proprietary License" +"nvidia-curand-cu11","Other/Proprietary License" +"nvidia-cusolver-cu11","Other/Proprietary License" +"nvidia-cusparse-cu11","Other/Proprietary License" +"nvidia-nccl-cu11","Other/Proprietary License" +"nvidia-nvtx-cu11","Other/Proprietary License" +"packaging","Apache Software License; BSD License" +"prompt-toolkit","BSD License" +"psycopg2-binary","GNU Library or Lesser General Public License (LGPL)" +"python-dateutil","Apache Software License; BSD License" +"pytz","MIT License" +"redis","MIT License" +"referencing","MIT License" +"requests","Apache Software License" +"rpds-py","MIT License" +"six","MIT License" +"sqlparse","BSD License" +"sympy","BSD License" +"torch","BSD License" +"triton","MIT License" +"typing_extensions","Python Software Foundation License" +"tzdata","Apache Software License" +"uritemplate","Apache Software License; BSD License" +"urllib3","MIT License" +"vine","BSD License" diff --git a/licenses/license_info.no_versions.json b/licenses/license_info.no_versions.json new file mode 100644 index 0000000..776077c --- /dev/null +++ b/licenses/license_info.no_versions.json @@ -0,0 +1,274 @@ +[ + { + "License": "BSD License", + "Name": "Django" + }, + { + "License": "MIT License", + "Name": "Faker" + }, + { + "License": "BSD License", + "Name": "Jinja2" + }, + { + "License": "BSD License", + "Name": "MarkupSafe" + }, + { + "License": "MIT License", + "Name": "PyYAML" + }, + { + "License": "BSD License", + "Name": "amqp" + }, + { + "License": "MIT License", + "Name": "ansi" + }, + { + "License": "BSD License", + "Name": "asgiref" + }, + { + "License": "Apache Software License", + "Name": "async-timeout" + }, + { + "License": "MIT License", + "Name": "attrs" + }, + { + "License": "BSD License", + "Name": "billiard" + }, + { + "License": "BSD License", + "Name": "celery" + }, + { + "License": "Mozilla Public License 2.0 (MPL 2.0)", + "Name": "certifi" + }, + { + "License": "MIT License", + "Name": "charset-normalizer" + }, + { + "License": "BSD License", + "Name": "click" + }, + { + "License": "MIT License", + "Name": "click-didyoumean" + }, + { + "License": "BSD License", + "Name": "click-plugins" + }, + { + "License": "MIT", + "Name": "click-repl" + }, + { + "License": "Apache Software License; BSD License", + "Name": "cmake" + }, + { + "License": "MIT License", + "Name": "django-cors-headers" + }, + { + "License": "BSD License", + "Name": "django-polymorphic" + }, + { + "License": "BSD License", + "Name": "django-redis" + }, + { + "License": "BSD License", + "Name": "djangorestframework" + }, + { + "License": "Apache Software License", + "Name": "dlr-logging" + }, + { + "License": "MIT License", + "Name": "docstring-parser" + }, + { + "License": "BSD License", + "Name": "drf-spectacular" + }, + { + "License": "The Unlicense (Unlicense)", + "Name": "filelock" + }, + { + "License": "Apache Software License", + "Name": "fl-demonstrator" + }, + { + "License": "BSD License", + "Name": "idna" + }, + { + "License": "MIT License", + "Name": "inflection" + }, + { + "License": "MIT License", + "Name": "jsonschema" + }, + { + "License": "MIT License", + "Name": "jsonschema-specifications" + }, + { + "License": "BSD License", + "Name": "kombu" + }, + { + "License": "Apache Software License", + "Name": "lit" + }, + { + "License": "MIT License", + "Name": "marshmallow" + }, + { + "License": "BSD License", + "Name": "mpmath" + }, + { + "License": "BSD License", + "Name": "networkx" + }, + { + "License": "BSD License", + "Name": "numpy" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cublas-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cuda-cupti-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cuda-nvrtc-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cuda-runtime-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cudnn-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cufft-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-curand-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cusolver-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-cusparse-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-nccl-cu11" + }, + { + "License": "Other/Proprietary License", + "Name": "nvidia-nvtx-cu11" + }, + { + "License": "Apache Software License; BSD License", + "Name": "packaging" + }, + { + "License": "BSD License", + "Name": "prompt-toolkit" + }, + { + "License": "GNU Library or Lesser General Public License (LGPL)", + "Name": "psycopg2-binary" + }, + { + "License": "Apache Software License; BSD License", + "Name": "python-dateutil" + }, + { + "License": "MIT License", + "Name": "pytz" + }, + { + "License": "MIT License", + "Name": "redis" + }, + { + "License": "MIT License", + "Name": "referencing" + }, + { + "License": "Apache Software License", + "Name": "requests" + }, + { + "License": "MIT License", + "Name": "rpds-py" + }, + { + "License": "MIT License", + "Name": "six" + }, + { + "License": "BSD License", + "Name": "sqlparse" + }, + { + "License": "BSD License", + "Name": "sympy" + }, + { + "License": "BSD License", + "Name": "torch" + }, + { + "License": "MIT License", + "Name": "triton" + }, + { + "License": "Python Software Foundation License", + "Name": "typing_extensions" + }, + { + "License": "Apache Software License", + "Name": "tzdata" + }, + { + "License": "Apache Software License; BSD License", + "Name": "uritemplate" + }, + { + "License": "MIT License", + "Name": "urllib3" + }, + { + "License": "BSD License", + "Name": "vine" + } +] diff --git a/licenses/license_info.no_versions.md b/licenses/license_info.no_versions.md new file mode 100644 index 0000000..2dc9085 --- /dev/null +++ b/licenses/license_info.no_versions.md @@ -0,0 +1,70 @@ +| Name | License | +|---------------------------|-----------------------------------------------------| +| Django | BSD License | +| Faker | MIT License | +| Jinja2 | BSD License | +| MarkupSafe | BSD License | +| PyYAML | MIT License | +| amqp | BSD License | +| ansi | MIT License | +| asgiref | BSD License | +| async-timeout | Apache Software License | +| attrs | MIT License | +| billiard | BSD License | +| celery | BSD License | +| certifi | Mozilla Public License 2.0 (MPL 2.0) | +| charset-normalizer | MIT License | +| click | BSD License | +| click-didyoumean | MIT License | +| click-plugins | BSD License | +| click-repl | MIT | +| cmake | Apache Software License; BSD License | +| django-cors-headers | MIT License | +| django-polymorphic | BSD License | +| django-redis | BSD License | +| djangorestframework | BSD License | +| dlr-logging | Apache Software License | +| docstring-parser | MIT License | +| drf-spectacular | BSD License | +| filelock | The Unlicense (Unlicense) | +| fl-demonstrator | Apache Software License | +| idna | BSD License | +| inflection | MIT License | +| jsonschema | MIT License | +| jsonschema-specifications | MIT License | +| kombu | BSD License | +| lit | Apache Software License | +| marshmallow | MIT License | +| mpmath | BSD License | +| networkx | BSD License | +| numpy | BSD License | +| nvidia-cublas-cu11 | Other/Proprietary License | +| nvidia-cuda-cupti-cu11 | Other/Proprietary License | +| nvidia-cuda-nvrtc-cu11 | Other/Proprietary License | +| nvidia-cuda-runtime-cu11 | Other/Proprietary License | +| nvidia-cudnn-cu11 | Other/Proprietary License | +| nvidia-cufft-cu11 | Other/Proprietary License | +| nvidia-curand-cu11 | Other/Proprietary License | +| nvidia-cusolver-cu11 | Other/Proprietary License | +| nvidia-cusparse-cu11 | Other/Proprietary License | +| nvidia-nccl-cu11 | Other/Proprietary License | +| nvidia-nvtx-cu11 | Other/Proprietary License | +| packaging | Apache Software License; BSD License | +| prompt-toolkit | BSD License | +| psycopg2-binary | GNU Library or Lesser General Public License (LGPL) | +| python-dateutil | Apache Software License; BSD License | +| pytz | MIT License | +| redis | MIT License | +| referencing | MIT License | +| requests | Apache Software License | +| rpds-py | MIT License | +| six | MIT License | +| sqlparse | BSD License | +| sympy | BSD License | +| torch | BSD License | +| triton | MIT License | +| typing_extensions | Python Software Foundation License | +| tzdata | Apache Software License | +| uritemplate | Apache Software License; BSD License | +| urllib3 | MIT License | +| vine | BSD License | diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..df4f129 --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fl_server.settings.development') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..05a867a --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,87 @@ +site_name: Federated Learning Demonstrator + +repo_name: fl-demonstrator +repo_url: https://github.com/DLR-KI/fl-demonstrator +#edit_uri: blob/main/docs/ + +theme: + name: material + custom_dir: docs/.overrides + features: + - content.code.annotate + - content.code.copy + - content.tabs.link + - navigation.tabs + - navigation.sections + #- navigation.expand + - navigation.path + - navigation.indexes + - navigation.top + - search.highlight + - search.suggest + language: en + palette: + - scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + primary: teal + accent: deep purple + - scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + primary: teal + accent: blue + +markdown_extensions: + - admonition + - attr_list + - footnotes + - md_in_html + - toc: + permalink: true + - pymdownx.arithmatex: + generic: true + #- pymdownx.blocks.tab: + # alternate_style: true + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.mark + - pymdownx.snippets + - pymdownx.superfences + +plugins: + - search + - portray + +extra: + social: + - icon: dlr-logo + link: https://www.dlr.de/en + - icon: dlr-ki + link: https://www.dlr.de/ki/en + - icon: fontawesome/brands/square-gitlab + link: https://github.com/DLR-KI/fl-demonstrator + +extra_javascript: + - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.js + - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/contrib/auto-render.min.js + - javascripts/katex.js + +extra_css: + - https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.7/katex.min.css + - styles/style.css + +copyright: | + © 2024 + + DLR KI ALG + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..29cd47c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,353 @@ +[project] +# This is the name of your project. The first time you publish this +# package, this name will be registered for you. It will determine how +# users can install this project, e.g.: +# +# $ pip install fl-demonstrator +# +# And where it will live on PyPI: https://pypi.org/project/fl-demonstrator/ +# +# There are some restrictions on what makes a valid project name +# specification here: +# https://packaging.python.org/specifications/core-metadata/#name +name = "fl-demonstrator" # Required + +# Versions should comply with PEP 440: +# https://www.python.org/dev/peps/pep-0440/ +# +# For a discussion on single-sourcing the version, see +# https://packaging.python.org/guides/single-sourcing-package-version/ +version = "0.0.1.dev2" # Required + +# This is a one-line description or tagline of what your project does. This +# corresponds to the "Summary" metadata field: +# https://packaging.python.org/specifications/core-metadata/#summary +description = "Federated Learning Demonstrator" # Optional + +# This is an optional longer description of your project that represents +# the body of text which users will see when they visit PyPI. +# +# Often, this is the same as your README, so you can just read it in from +# that file directly (as we have already done above) +# +# This field corresponds to the "Description" metadata field: +# https://packaging.python.org/specifications/core-metadata/#description-optional +readme = "README.md" # Optional + +# Specify which Python versions you support. In contrast to the +# 'Programming Language' classifiers above, 'pip install' will check this +# and refuse to install the project if the version does not match. See +# https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires +requires-python = ">=3.10" + +# This is either text indicating the license for the distribution, or a file +# that contains the license +# https://packaging.python.org/en/latest/specifications/core-metadata/#license +license = {file = "LICENSE"} + +# This field adds keywords for your project which will appear on the +# project page. What does your project relate to? +# +# Note that this is a list of additional keywords, separated +# by commas, to be used to assist searching for the distribution in a +# larger catalog. +keywords = ["ai", "federated learning", "catena-x", "dlr", "demonstrator", "server"] # Optional + +# This should be your name or the name of the organization who originally +# authored the project, and a valid email address corresponding to the name +# listed. +authors = [ # Optional + {name="Benedikt Franke", email="benedikt.franke@dlr.de"}, + {name="Florian Heinrich", email="florian.heinrich@dlr.de"}, +] + +# This should be your name or the names of the organization who currently +# maintains the project, and a valid email address corresponding to the name +# listed. +maintainers = [ # Optional + # {name="Jane Doe", email="jane.doe@example.com"} +] + +# Classifiers help users find your project by categorizing it. +# +# For a list of valid classifiers, see https://pypi.org/classifiers/ +classifiers = [ # Optional + # How mature is this project? Common values are + # 3 - Alpha + # 4 - Beta + # 5 - Production/Stable + "Development Status :: 3 - Alpha", + + # Indicate who your project is intended for + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering", + "Operating System :: OS Independent", + + # Pick your license as you wish + "License :: OSI Approved :: Apache Software License", + + # Specify the Python versions you support here. In particular, ensure + # that you indicate you support Python 3. These classifiers are *not* + # checked by "pip install". See instead "python_requires" below. + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3 :: Only", +] + +# This field lists other packages that your project depends on to run. +# Any package you put here will be installed by pip when your project is +# installed, so they must be valid existing projects. +# +# For an analysis of this field vs pip's requirements files see: +# https://packaging.python.org/discussions/install-requires-vs-requirements/ +dependencies = [ # Optional + "celery~=5.3.0", + "django~=4.0.0", + "django-cors-headers~=4.1.0", + "django-polymorphic~=3.1.0", + "django-redis~=5.2.0", + "djangorestframework~=3.14.0", + "docstring-parser~=0.15", + "drf-spectacular~=0.26.3", + "dlr-logging @ git+https://github.com/DLR-KI/fl-logging-base.git@main", # noqa: E501 + "Faker~=20.1.0", # dummy data generation + "marshmallow~=3.19.0", + "numpy~=1.24.3", + "psycopg2-binary~=2.9.6", # cspell:ignore psycopg + "requests~=2.31.0", + "torch~=2.0.1", +] + +# List additional groups of dependencies here (e.g. development +# dependencies). Users will be able to install these using the "extras" +# syntax, for example: +# +# $ pip install -e ".[all]" +# +# Similar to `dependencies` above, these must be valid existing +# projects. +[project.optional-dependencies] # Optional +dev = [ + "pre-commit~=3.3.2", + "tox~=4.5.1", +] +test = [ + "autopep8~=2.0.2", + "coverage~=7.2.7", + "flake8~=6.0.0", + "flake8-pyproject~=1.2.3", + "licensecheck", # no version, install latest version + "mypy~=1.3.0", + "pytest-django~=4.5.2", + "responses~=0.23.1", + "shellcheck-py~=0.9.0.6", +] +stubs = [ + "celery-types~=0.17.0", + "types-requests~=2.31.0", + "types-tabulate~=0.9.0.3", +] +doc = [ + "portray @ git+https://github.com/HeinrichAD/portray.git@v1.8.0-dev", + #"plantuml-markdown~=3.9.2", # post-install: cp plantuml_markdown.py into markdown/extensions +] +all = ["fl-demonstrator[dev,test,stubs,doc]"] + +# List URLs that are relevant to your project +# +# This field corresponds to the "Project-URL" and "Home-Page" metadata fields: +# https://packaging.python.org/specifications/core-metadata/#project-url-multiple-use +# https://packaging.python.org/specifications/core-metadata/#home-page-optional +# +# Examples listed include a pattern for specifying where the package tracks +# issues, where the source is hosted, where to say thanks to the package +# maintainers, and where to support the project financially. The key is +# what's used to render the link text on PyPI. +[project.urls] # Optional +"Homepage" = "https://github.com/DLR-KI/fl-demonstrator" +"Bug Tracker" = "https://github.com/DLR-KI/fl-demonstrator/issues" +#"Changelog" = ""https://github.com/DLR-KI/fl-demonstrator/blob/main/CHANGELOG.md" +#"Funding" = "https://donate.pypi.org" +#"Say Thanks!" = "http://saythanks.io/to/example" +"Source" = "https://github.com/DLR-KI/fl-demonstrator" + +# The following would provide a command line executable called `fl-demonstrator` +# which executes the function `main` inside `__main__.py` from this package when invoked. +[project.scripts] # Optional +#fl-demonstrator = "???.__main__:main" + +# This is configuration specific to the `setuptools` build backend. +# If you are using a different build backend, you will need to change this. +[tool.setuptools] +# If there are data files included in your packages that need to be +# installed, specify them here. +packages = ["fl_server", "fl_server_ai", "fl_server_api", "fl_server_core"] +#package-data = { +# "fl_server" = ["py.typed"], +# "fl_server_ai" = ["py.typed"], +# "fl_server_api" = ["py.typed"], +# "fl_server_core" = ["py.typed"], +#} + +[build-system] +# These are the assumed default build requirements from pip: +# https://pip.pypa.io/en/stable/reference/pip/#pep-517-and-518-support +requires = ["setuptools>=43.0.0", "wheel"] +build-backend = "setuptools.build_meta" + +####################################################################################################################### + +# licensecheck +# https://github.com/FHPythonUtils/LicenseCheck/blob/master/README.md + +[tool.licensecheck] +using = "PEP631" +#using = "PEP631:dev;test;stubs;doc" +zero = true +ignore_packages = [ + # https://docs.nvidia.com/cuda/eula/index.html + "nvidia-cublas-cu11", + "nvidia-cuda-cupti-cu11", + "nvidia-cuda-nvrtc-cu11", + "nvidia-cuda-runtime-cu11", + "nvidia-cudnn-cu11", + "nvidia-cufft-cu11", + "nvidia-curand-cu11", + "nvidia-cusolver-cu11", + "nvidia-cusparse-cu11", + "nvidia-nccl-cu11", + "nvidia-nvtx-cu11", +] + +####################################################################################################################### + +# flake8 +# https://flake8.pycqa.org/en/latest/user/configuration.html + +[tool.flake8] +max-line-length = 120 +per-file-ignores = [ + "__init__.py: F401", + "fl_server/settings/*.py: E305,F405", + "fl_server_core/migrations/*.py: E501", +] +exclude = [ + ".build", + ".git", + ".github", + ".*_cache", + ".tox", + ".venv", + ".vscode", + "*.egg", + "*.egg-info", + "__pycache__", + "Interactive-1.interactive", + "fl_server_core/migrations", +] +#select = "E,W,F" + +####################################################################################################################### + +# mypy +# https://mypy.readthedocs.io/en/stable/config_file.html + +[tool.mypy] +# Global options +exclude = ".build" # https://mypy.readthedocs.io/en/stable/config_file.html#confval-exclude +no_implicit_optional = true +show_error_codes = true +#warn_return_any = true +#warn_unused_configs = true +#disallow_untyped_defs = true + +#plugins = +# mypy_django_plugin.main +#[mypy.plugins.django-stubs] +#django_settings_module = "fl_server.settings" + +# Per-module options + +# Ignore missing imports (missing stubs or py.typed) +[[tool.mypy.overrides]] +module = [ + "django.*", + "polymorphic.*", + "rest_framework.*", + "setuptools.*", +] +ignore_missing_imports = true + +####################################################################################################################### + +# coverage +# https://coverage.readthedocs.io/en/latest/config.html + +[tool.coverage.run] +branch = true +source = [ + "fl_server", + "fl_server_core", + "fl_server_api", + "fl_server_ai", +] +omit = [ + "manage.py", + "fl_server/**/*", + "fl_server_core/migrations/**/*", + "fl_server_api/views/johannes.py", + "**/tests/*", +] + +[tool.coverage.report] +omit = [ + "manage.py", + "fl_server/**/*", + "fl_server_core/migrations/**/*", + "fl_server_api/views/johannes.py", +] + +# Regexes for lines to exclude from consideration +exclude_lines = [ + # Have to re-enable the standard pragma + "pragma: no cover", + "@overload", + + # Don't complain about missing debug-only code: + "def __repr__", + "if self\\.debug", + + # Don't complain if tests don't hit defensive assertion code: + "raise AssertionError", + "raise NotImplementedError", + + # Don't complain if non-runnable code isn't run: + "if 0:", + "if Flase:", + "if __name__ == .__main__.:", + + # Don't complain about abstract methods, they aren't run: + "@(abc\\.)?abstractmethod", +] + +ignore_errors = true +skip_empty = true + +[tool.coverage.html] +title = "Coverage report for fl_server" + +####################################################################################################################### + +# pytest +# https://docs.pytest.org/en/latest + +[tool.pytest.ini_options] +DJANGO_SETTINGS_MODULE = "fl_server.settings.development" +testpaths = [ + "fl_server/tests", + "fl_server_core/tests", + "fl_server_api/tests", + "fl_server_ai/tests", +] +python_files = "test_*.py" diff --git a/scripts/utils.sh b/scripts/utils.sh new file mode 100644 index 0000000..e4a1f9a --- /dev/null +++ b/scripts/utils.sh @@ -0,0 +1,71 @@ +#!/bin/bash +############################################################################### +# Utility functions # +##################### +# This script contains utility functions and global variables. +############################################################################### +# Usage: +# Asuming this script is in the same directory: +# source "$(dirname "${BASH_SOURCE[0]}")/utils.sh" +# info "Hello World" +############################################################################### + + +# logging +function info { + echo -en "[\e[0;32mINFO\e[0m] " + info2 "$@" +} +function info2 { + echo "$@" +} +function warn { + echo -en "[\e[0;33mWARN\e[0m] " + warn2 "$@" +} +function warn2 { + echo "$@" +} +function error { + echo -en "[\e[0;31mERROR\e[0m] " >&2 + error2 "$@" +} +function error2 { + echo "$@" >&2 +} +function fatal { + echo -en "[\e[0;41mFATAL\e[0m] " >&2 + echo "$@" >&2 + exit 2 +} + + +# appends a command to a trap +# +# - 1st arg: code to add +# - remaining args: names of traps to modify +# +# Source: https://stackoverflow.com/a/7287873 +trap_add() { + trap_add_cmd=$1; shift || fatal "${FUNCNAME[0]} usage error" + for trap_add_name in "$@"; do + trap -- "$( + # helper fn to get existing trap command from output of trap -p + # shellcheck disable=SC2317 + extract_trap_cmd() { printf '%s\n' "$3"; } + # print existing trap command with newline + eval "extract_trap_cmd $(trap -p "${trap_add_name}")" + # print the new trap command + printf '%s\n' "${trap_add_cmd}" + )" "${trap_add_name}" \ + || fatal "unable to add to trap ${trap_add_name}" + done +} +# set the trace attribute for the above function. this is +# required to modify DEBUG or RETURN traps because functions don't +# inherit them unless the trace attribute is set +declare -f -t trap_add + +# change working diretory to project root but return later +trap_add "cd $(pwd)" EXIT SIGINT SIGQUIT SIGABRT SIGTERM +cd "$(dirname "$(dirname "$(realpath "${BASH_SOURCE[0]}")")")" || exit 99 diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..ee6ddaa --- /dev/null +++ b/tox.ini @@ -0,0 +1,61 @@ +[tox] +envlist = py{310,311} + +# Define the minimal tox version required to run; +# if the host tox is less than this the tool with create an environment and +# provision it with a tox that satisfies it under provision_tox_env. +# At least this version is needed for PEP 517/518 support. +minversion = 3.3.0 + +# Activate isolated build environment. tox will use a virtual environment +# to build a source distribution from the source tree. For build tools and +# arguments use the pyproject.toml file as specified in PEP-517 and PEP-518. +isolated_build = true + +[testenv:safety] +basepython = python +deps = + safety +;extras = all +commands = + safety check + +[testenv:licenses] +basepython = python +deps = + pip-licenses +;extras = all +commands = + pip-licenses \ + --from=mixed \ + --format=csv \ + --output-file=./licenses/license_info.csv + pip-licenses \ + --from=mixed \ + --format=json \ + --output-file=./licenses/license_info.json + pip-licenses \ + --from=mixed \ + --format=markdown \ + --output-file=./licenses/license_info.md + pip-licenses \ + --from=mixed \ + --format=csv \ + --no-version \ + --output-file=./licenses/license_info.no_versions.csv + pip-licenses \ + --from=mixed \ + --format=json \ + --no-version \ + --output-file=./licenses/license_info.no_versions.json + pip-licenses \ + --from=mixed \ + --format=markdown \ + --no-version \ + --output-file=./licenses/license_info.no_versions.md + pip-licenses \ + --from=mixed \ + --format=plain-vertical \ + --with-license-file \ + --no-license-path \ + --output-file=./licenses/license.txt