diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index 526fcd0..0000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,20 +0,0 @@ -[bumpversion] -current_version = 0.2.1 -commit = True -tag = True - -[bumpversion:file:setup.py] -search = version="{current_version}" -replace = version="{new_version}" - -[bumpversion:file:README.rst] -search = v{current_version}. -replace = v{new_version}. - -[bumpversion:file:docs/conf.py] -search = version = release = "{current_version}" -replace = version = release = "{new_version}" - -[bumpversion:file:src/omi/__init__.py] -search = __version__ = "{current_version}" -replace = __version__ = "{new_version}" diff --git a/.bumpversion.toml b/.bumpversion.toml new file mode 100644 index 0000000..62cc0de --- /dev/null +++ b/.bumpversion.toml @@ -0,0 +1,38 @@ +[tool.bumpversion] +current_version = "1.0.0" +parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" +serialize = ["{major}.{minor}.{patch}"] +search = "{current_version}" +replace = "{new_version}" +regex = false +ignore_missing_version = false +ignore_missing_files = false +tag = true +sign_tags = false +tag_name = "v{new_version}" +tag_message = "v{new_version}" +allow_dirty = false +commit = true +message = "Bump version: {current_version} → {new_version}" +commit_args = "" + +[[tool.bumpversion.files]] +filename = "pyproject.toml" + +[[tool.bumpversion.files]] +filename = "CHANGELOG.md" +search = "[Unreleased]" +replace = "[Unreleased] - {now:%Y-%m-%d}" + +[[tool.bumpversion.files]] +filename = "CHANGELOG.md" +search = "Unreleased" + +[[tool.bumpversion.files]] +filename = "README.rst" + +[[tool.bumpversion.files]] +filename = "docs/conf.py" + +[[tool.bumpversion.files]] +filename = "omi/__init__.py" diff --git a/.cookiecutterrc b/.cookiecutterrc deleted file mode 100644 index 4a6d06c..0000000 --- a/.cookiecutterrc +++ /dev/null @@ -1,56 +0,0 @@ -# This file exists so you can easily regenerate your project. -# -# `cookiepatcher` is a convenient shim around `cookiecutter` -# for regenerating projects (it will generate a .cookiecutterrc -# automatically for any template). To use it: -# -# pip install cookiepatcher -# cookiepatcher gh:ionelmc/cookiecutter-pylibrary project-path -# -# See: -# https://pypi.org/project/cookiepatcher -# -# Alternatively, you can run: -# -# cookiecutter --overwrite-if-exists --config-file=project-path/.cookiecutterrc gh:ionelmc/cookiecutter-pylibrary - -default_context: - - _extensions: ['jinja2_time.TimeExtension'] - _template: 'gh:ionelmc/cookiecutter-pylibrary' - appveyor: 'yes' - c_extension_function: 'longest' - c_extension_module: '_omi' - c_extension_optional: 'no' - c_extension_support: 'no' - codacy: 'no' - codeclimate: 'no' - codecov: 'yes' - command_line_interface: 'plain' - command_line_interface_bin_name: 'omi' - coveralls: 'no' - distribution_name: 'omi' - email: 'martinglauer89@gmail.com' - full_name: 'Martin Glauer' - github_username: 'OpenEnergyPlatform' - landscape: 'no' - license: 'AGPL-3.0' - linter: 'flake8' - package_name: 'omi' - project_name: 'omi' - project_short_description: 'A library to process and translate open energy metadata.' - release_date: 'today' - repo_name: 'omi' - requiresio: 'yes' - scrutinizer: 'no' - sphinx_docs: 'yes' - sphinx_doctest: 'yes' - sphinx_theme: 'sphinx-rtd-theme' - test_matrix_configurator: 'no' - test_matrix_separate_coverage: 'no' - test_runner: 'pytest' - travis: 'yes' - version: '0.0.0' - website: 'openenergy-platform.org' - year_from: '2019' - year_to: '2019' diff --git a/.github/ISSUE_TEMPLATE/issue_template_bug.md b/.github/ISSUE_TEMPLATE/issue_template_bug.md new file mode 100644 index 0000000..b15724e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue_template_bug.md @@ -0,0 +1,31 @@ +--- +name: Bug Issue +about: For bugs and errors +title: Your title should make sense if said after "The issue is " +labels: "bug" +assignees: '' + +--- + +## Description of the issue + +Describe the problem in as much detail as possible. +Focus on the expected and current behavior. +If necessary, create a screenshot and insert below. + +## Steps to Reproduce +1. +2. +3. + +## Ideas of solution + +Describe possible ideas for solution and evaluate advantages and disadvantages. + +## Context and Environment +* Version used: +* Operating system: +* Environment setup and (python) version: + +## Workflow checklist +- [ ] I am aware of the workflow in [CONTRIBUTING.md](https://github.com/rl-institut/super-repo/blob/develop/CONTRIBUTING.md) diff --git a/.github/ISSUE_TEMPLATE/issue_template_feature.md b/.github/ISSUE_TEMPLATE/issue_template_feature.md new file mode 100644 index 0000000..200861f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue_template_feature.md @@ -0,0 +1,19 @@ +--- +name: Feature Issue +about: For new ideas, developments and features +title: Your title should make sense if said after "The issue is " +labels: "enhancement" +assignees: '' + +--- + +## Description of the issue + +Describe the problem in as much detail as possible. + +## Ideas of solution + +Describe possible ideas for solution and evaluate advantages and disadvantages. + +## Workflow checklist +- [ ] I am aware of the workflow in [CONTRIBUTING.md](https://github.com/rl-institut/super-repo/blob/develop/CONTRIBUTING.md) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..42b42c3 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,29 @@ +## Summary of the discussion + +Describe the findings of the discussion in the issue or meeting. + +## Type of change (CHANGELOG.md) + +### Added +- Add a new class [(#)](https://github.com/rl-institut/super-repo/pull/) + +### Updated +- Update a definition [(#)](https://github.com/rl-institut/super-repo/pull/) + +### Removed +- Remove a broken link [(#)](https://github.com/rl-institut/super-repo/pull/) + + +## Workflow checklist + +### Automation +Closes # + +### PR-Assignee +- [ ] 🐙 Follow the workflow in [CONTRIBUTING.md](https://github.com/rl-institut/super-repo/blob/develop/CONTRIBUTING.md) +- [ ] 📝 Update the [CHANGELOG.md](https://github.com/rl-institut/super-repo/blob/develop/CHANGELOG.md) +- [ ] 📙 Update the documentation + +### Reviewer +- [ ] 🐙 Follow the [Reviewer Guidelines](https://github.com/rl-institut/super-repo/blob/develop/CONTRIBUTING.md#40-let-someone-else-review-your-pr) +- [ ] 🐙 Provided feedback and show sufficient appreciation for the work done diff --git a/.github/workflows/automated-testing.yml b/.github/workflows/automated-testing.yml index 6b77a8b..742f8f6 100644 --- a/.github/workflows/automated-testing.yml +++ b/.github/workflows/automated-testing.yml @@ -5,7 +5,7 @@ on: push: branches: - master - - develop + - dev pull_request: jobs: @@ -26,4 +26,4 @@ jobs: run: pip install tox - name: Run tox # Run tox using the version of Python in `PATH` - run: tox -v \ No newline at end of file + run: tox -v diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml new file mode 100644 index 0000000..219fc18 --- /dev/null +++ b/.github/workflows/linter.yml @@ -0,0 +1,35 @@ +name: CI + +# Enable Buildkit and let compose use it to speed up image building +env: + DOCKER_BUILDKIT: 1 + COMPOSE_DOCKER_CLI_BUILD: 1 + +on: + pull_request: + branches: [ "master", "dev" ] + paths-ignore: [ "docs/**" ] + + push: + branches: [ "master", "dev" ] + paths-ignore: [ "docs/**" ] + +concurrency: + group: ${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + linter: + runs-on: ubuntu-latest + steps: + + - name: Checkout Code Repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.9" + + - name: Run pre-commit + uses: pre-commit/action@v3.0.1 diff --git a/.gitignore b/.gitignore index 16a8eda..e05857e 100644 --- a/.gitignore +++ b/.gitignore @@ -80,4 +80,6 @@ docs/_build # manual testing scripts -/local_test \ No newline at end of file +/local_test +/script +/.venv/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7fc5dad..15e34db 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,36 @@ +exclude: 'docs|node_modules|vendors|migrations|.git|.tox' +default_stages: [commit] +fail_fast: true + repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-json + exclude: tests/test_data/validation/invalid_metadata/* + - id: end-of-file-fixer + - id: trailing-whitespace + - id: check-added-large-files + + - repo: https://github.com/pre-commit/mirrors-jshint + rev: v2.13.6 + hooks: + - id: jshint + - repo: https://github.com/psf/black - rev: stable + rev: 23.3.0 hooks: - id: black - language_version: python3 - - repo: https://github.com/pre-commit/mirrors-isort - rev: master + - repo: https://github.com/charliermarsh/ruff-pre-commit + # Ruff version. + rev: 'v0.0.277' + hooks: + - id: ruff + + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 hooks: - - id: isort - language_version: python3 + - id: flake8 + args: [ "--config=setup.cfg" ] + additional_dependencies: [ flake8-isort ] diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 593c416..0000000 --- a/.travis.yml +++ /dev/null @@ -1,56 +0,0 @@ -language: python -cache: pip -env: - global: - - LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so - - SEGFAULT_SIGNALS=all - matrix: - - TOXENV=check - - TOXENV=docs -matrix: - include: - - python: '3.5' - env: - - TOXENV=py35,report,codecov - - python: '3.6' - env: - - TOXENV=py36,report,codecov - - python: '3.7' - dist: xenial - env: - - TOXENV=py37,report,codecov - - python: 'pypy3' - env: - - TOXENV=pypy3,report,codecov -before_install: - - python --version - - uname -a - - lsb_release -a -install: - - pip install tox - - virtualenv --version - - easy_install --version - - pip --version - - tox --version - - pip install . - - | - set -ex - if [[ $TRAVIS_PYTHON_VERSION == 'pypy3' ]]; then - (cd $HOME - wget https://downloads.python.org/pypy/pypy3.6-v7.3.1-linux64.tar.bz2 - tar xf pypy3.*.tar.bz2 - pypy3.*/bin/pypy3 -m ensurepip - pypy3.*/bin/pypy3 -m pip install -U virtualenv) - export PATH=$(echo $HOME/pypy3.*/bin):$PATH - export TOXPYTHON=$(echo $HOME/pypy3.*/bin/pypy3) - fi - set +x -script: - - tox -v -after_failure: - - more .tox/log/* | cat - - more .tox/*/log/* | cat -notifications: - email: - on_success: never - on_failure: always diff --git a/AUTHORS.rst b/AUTHORS.rst index d11250d..249f069 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -2,5 +2,6 @@ Authors ======= -* Martin Glauer - openenergy-platform.org -* Jonas Huber - openenergy-platform.org +* Hendrik Huyskens - openenergyplatform.org +* Martin Glauer - openenergyplatform.org +* Jonas Huber - openenergyplatform.org diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 07ca0ae..63c7836 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,9 +2,15 @@ Changelog ========= -current (2024-XX-XX) +current -------------------- -* +* + + +1.0.0 (2024-10-31) +-------------------- +* Fully rewrite OMI and implement the json schema spec only, remove python class based parsing (#104)[https://github.com/OpenEnergyPlatform/omi/pull/104] +* Add a new conversion functionality to convert form v160 to v200 oemetadata [(#111)](https://github.com/rl-institut/super-repo/pull/111) 0.2.1 (2024-01-26) -------------------- @@ -30,7 +36,7 @@ current (2024-XX-XX) 0.0.9 (2022-10-31) -------------------- -* Fix bug that is raised if the input oemetadata does not contain the key _comment (PR#74) +* Fix bug that is raised if the input oemetadata does not contain the key _comment (PR#74) 0.0.8 (2022-10-20) -------------------- diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index cbba3f3..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,21 +0,0 @@ -graft docs -graft src -graft ci -graft tests -graft examples -graft scripts - -include .bumpversion.cfg -include .coveragerc -include .cookiecutterrc -include .editorconfig - -include AUTHORS.rst -include CHANGELOG.rst -include CONTRIBUTING.rst -include LICENSE -include README.rst - -include tox.ini .pre-commit-config.yaml .travis.yml appveyor.yml - -global-exclude *.py[cod] __pycache__ *.so *.dylib diff --git a/README.rst b/README.rst index 8cd7834..841b453 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,10 @@ Open Energy Family - Open Metadata Integration OMI ================================================== +A library to work with the open energy metadata. Its main features are validation, version conversion and infer data schemas from CSV to oemetadata. + +* Free software: AGPL-3.0 + Overview ======== @@ -13,8 +17,7 @@ Overview * - docs - |docs| * - tests - - | |travis| |appveyor| |requires| - | |codecov| + - | |Automated test| |codecov| * - package - | |version| |wheel| |supported-versions| |supported-implementations| | |commits-since| @@ -22,17 +25,9 @@ Overview :target: https://readthedocs.org/projects/omi :alt: Documentation Status -.. |travis| image:: https://travis-ci.org/OpenEnergyPlatform/omi.svg?branch=master - :alt: Travis-CI Build Status - :target: https://travis-ci.org/OpenEnergyPlatform/omi - -.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/OpenEnergyPlatform/omi?branch=master&svg=true - :alt: AppVeyor Build Status - :target: https://ci.appveyor.com/project/OpenEnergyPlatform/omi - -.. |requires| image:: https://requires.io/github/OpenEnergyPlatform/omi/requirements.svg?branch=master - :alt: Requirements Status - :target: https://requires.io/github/OpenEnergyPlatform/omi/requirements/?branch=master +.. |Automated test| image:: https://github.com/OpenEnergyPlatform/omi/actions/workflows/automated-testing.yml/badge.svg + :target: https://github.com/OpenEnergyPlatform/omi/actions/workflows/automated-testing.yml + :alt: Test status .. |codecov| image:: https://codecov.io/github/OpenEnergyPlatform/omi/coverage.svg?branch=master :alt: Coverage Status @@ -42,9 +37,9 @@ Overview :alt: PyPI Package latest release :target: https://pypi.org/project/omi -.. |commits-since| image:: https://img.shields.io/github/commits-since/OpenEnergyPlatform/omi/v0.2.1.svg +.. |commits-since| image:: https://img.shields.io/github/commits-since/OpenEnergyPlatform/omi/v1.0.0.svg :alt: Commits since latest release - :target: https://github.com/OpenEnergyPlatform/omi/compare/v0.2.1...master + :target: https://github.com/OpenEnergyPlatform/omi/compare/v1.0.0...master .. |wheel| image:: https://img.shields.io/pypi/wheel/omi.svg :alt: PyPI Wheel @@ -61,10 +56,6 @@ Overview .. end-badges -A library to process and translate open energy metadata. - -* Free software: AGPL-3.0 - Installation ============ @@ -75,52 +66,58 @@ Installation Documentation ============= - +Documentation for OMI versions up to 0.2: https://omi.readthedocs.io/ +Documentation for reworked OMI versions starting from 1.0 you can find in the README document. Later on we migrate the documentation to mkdocs. + Usage ===== -**Parse, Compile, Render, Convert and Validate** -Omi can read(parse), compile, Render(json compilant), convert(convert metadata from v1.4 to v1.5 structure) and validate - a json -file or object that is compliant with the oemetadata spec. This is usefull to do various operations that help to integrate with - as -well as in interact with the oemetadata. Some parts of this tool might still be volatile but the code quality is conventionsly improved -as this module is a core component of the oeplatfroms metadata integration system. +You can use omi as python module and import its functionality into your codebase or use the cli capabilities. OMI provides tooling for validation +of oemetdata JSON documents using JSON-Schema. It also include helpers to generate the tabular data resource definition to seep up the metadata +creation and helps to select a open license by checking the license identifier against the SPDX license list. -Check if omi is able to read a oemetadata file (for version 1.4 and 1.5) -CLI - oemetadata version 1.5:: +As the oemetadata is updated from time to time we provides conversion functionality to convert metadata documents that use an earlier version +of the oemetadata-specification to help users stick with the latest enhancements the latest oemetadata version offers. - omi translate -f oep-v1.5 examples/data/metadata_v15.json +**Conversion** -CLI - oemetadata version 1.4:: +To ease the conversion of oemetadata from any outdated version to the latest version, we provide a +conversion functionality. The following example shows how to convert the oemetadata from v1.6 to v2.0. - omi translate -f oep-v1.4 -t oep-v1.4 examples/data/metadata_v14.json +CLI - oemetadata conversion:: -omi is able to read a JSON file and parse it into one of the internal Python structures (depending on the oemetadata version). -The OEPMetadata Python object can then be compiled and converted back to JSON. You can manipulate a successfully parsed -OEPMetadata object. + # Not implemented yet + omi convert -i {input/path} -o {output/path} -Module usage:: +Module usage - In python scripts you can use the conversion:: - from omi.dialects.oep.dialect import OEP_V_1_3_Dialect, OEP_V_1_4_Dialect, OEP_V_1_5_Dialect - inp = '{"id":"unique_id"}' #or read from json file - dialect1_5 = OEP_V_1_5_Dialect() - parsed = dialect1_5.parse(input) - print(parsed) - parsed.identifier = "another_unique_id" - compiled = dialect1_5.compile(parsed) - print(compiled) + from omi.conversion import convert_metadata + import json -**Conversion** + # you a function like this one to read you oemetadata json file + def read_json_file(file_path: str) -> dict: + with open(file_path, "r") as file: + data = json.load(file) + return data + + # for example you can use the oemetdata example.json for version 1.6.0 + # find it here https://github.com/OpenEnergyPlatform/oemetadata/blob/develop/metadata/v160/example.json + # make sure to provide a valid path relative to where you store the python environment + file_path = "example_v16.json" -To ease the conversion of oemetadata from the outdated version 1.4 to the latest version, we provide -conversion functionality. The following example shows how to convert the oemetadata from v1.4 to v1.5 -by using a CLI command. + # read the metadata document + meta = read_json_file(file_path) -CLI - oemetadata conversion from v1.4 to v1.5:: + # use omi to convert it to the latest release + converted = convert_metadata(meta, "OEMetadata-2.0.1") + + # now you can store the result as json file + with open("result.json", "w", encoding="utf-8") as json_file: + json.dump(converted, json_file, ensure_ascii=False, indent=4) # `indent=4` makes the JSON file easier to read - omi convert -i {input/path} -o {output/path} **Validation** @@ -131,48 +128,77 @@ This will create a report.json containing information to debug possible errors. two arguments the first one is the metadata and the second optional one is the schmea. By default (if no schema is passed) the validation will try to get the matching schema for the current metadata. + +CLI - oemetadata conversion:: + + # Not implemented yet + + Module usage:: - # You can import the JSONParser directly like this: import json - from omi.dialects.oep.parser import JSONParser + from omi.validation import validate_oemetadata_licenses, validate_metadata + + + # use a function like this one to read you oemetadata json file + def read_json_file(file_path: str) -> dict: + with open(file_path, "r") as file: + data = json.load(file) + return data + + # for example you can use the oemetdata example.json for version 2.0.0 + # find it here https://github.com/OpenEnergyPlatform/oemetadata/blob/develop/metadata/v20/example.json + # make sure to provide a valid path relative to where you store the python environment + file_path = "example_v16.json" - with open("tests/data/metadata_v15.json", "r", encoding="utf-8") as f: - metadata = json.load(f) + # read the new input from file + meta = read_json_file(file_path) - parser = JSONParser() - parser.validate(metadata) - - # check if your metadata is valid for the given schmea - schema = ... get a schema or import form oemetadata module - parser.is_valid(metadata, schema) + # validate the oemetadata: This will return noting or the errors including descriptions + validate_metadata(meta) -**Additional Fields - not related to the OEMetadata specification** + # As we are prone to open data we use this license check to validate the license name that + # is available in the metadata document for each data resource/distribution. + validate_oemetadata_licenses(meta) -Sometimes it is necessary to store additional key-value pairs along with the keys included in the OEMetadata specification. -OMI's compiler methods are capable of handling additional arguments or key-value arguments, but this must be -be explicitly specified. -To add additional key-value pairs, you must: +**Inspection** + +Describing your data structure is a quite technical task. OMI offers functionality to describe your data automatically. +You need to provide yor data in tabular text based format for this, for example a CSV file. Using frictionless OMI +guesses the data schema specification you can use this you provide required fields in an oemetadata document. + +CLI - oemetadata conversion:: + + # Not implemented yet + +Module usage:: + + import json - NOTE: If you save the renderer return value in a json file and try to parse the file, the extra field is not included. - You must read the json file using Python and then add the extra field back oemetadata object as shown below. + import pathlib -1 Parse the oemetadata from json file / variable into omis internal structure:: + from omi.inspection import infer_metadata - from omi.dialects.oep.dialect import OEP_V_1_5_Dialect + CSV_DATA_FILE = pathlib.Path(__file__).parent / "data" / "data.csv" - min_inp = '{"id":"unique_id"} # or read from json file - minimal_oemetadata15 = OEP_V_1_5_Dialect.parse(min_inp) + # infer the data fields from CSV fuile and add to an empty metadata template + with CSV_DATA_FILE.open("r") as f: + metadata = infer_metadata(f, "OEP") -2 Now you can get(from json file)/define the additional data:: + # Save to a JSON file + with open("script/metadata/result_inspection.json", "w", encoding="utf-8") as json_file: + json.dump(metadata, json_file, ensure_ascii=False, indent=4) # `indent=4` makes the JSON file easier to read - data = "test" +**Additional Fields** -3 And add it to the OEMetadata object that was parsed in step 1 by ading a key-value argument:: +To be in line with the oemetadata specification we do not allow for additional properties or fields in the metadata. +We want to keep the oemetadata relatively lean and readable still linking to other documents or to +propose a new property to extend the oemetadata would be a possibility here. - compiled = OEP_V_1_5_Dialect.compile(minimal_oemetadata15, _additionalField=data) - rendered = OEP_V_1_5_Dialect.render(compiled) +Still some times it becomes necessary to add additional information then this would be a use case outside of the OpenEnergyPlatform +specifically for your own use. You are welcome to use the oemetadata as base and add new fields we are happy to integrate them +back into the oeplatform and oemetadata if they seem relevant to other users. Development =========== diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index dce598c..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,86 +0,0 @@ -version: '{branch}-{build}' -build: off -cache: - - '%LOCALAPPDATA%\pip\Cache' -environment: - global: - WITH_COMPILER: 'cmd /E:ON /V:ON /C .\ci\appveyor-with-compiler.cmd' - matrix: - - TOXENV: check - TOXPYTHON: C:\Python36\python.exe - PYTHON_HOME: C:\Python36 - PYTHON_VERSION: '3.6' - PYTHON_ARCH: '32' - - TOXENV: 'py27,report,codecov' - TOXPYTHON: C:\Python27\python.exe - PYTHON_HOME: C:\Python27 - PYTHON_VERSION: '2.7' - PYTHON_ARCH: '32' - - TOXENV: 'py27,report,codecov' - TOXPYTHON: C:\Python27-x64\python.exe - WINDOWS_SDK_VERSION: v7.0 - PYTHON_HOME: C:\Python27-x64 - PYTHON_VERSION: '2.7' - PYTHON_ARCH: '64' - - TOXENV: 'py34,report,codecov' - TOXPYTHON: C:\Python34\python.exe - PYTHON_HOME: C:\Python34 - PYTHON_VERSION: '3.4' - PYTHON_ARCH: '32' - - TOXENV: 'py34,report,codecov' - TOXPYTHON: C:\Python34-x64\python.exe - WINDOWS_SDK_VERSION: v7.1 - PYTHON_HOME: C:\Python34-x64 - PYTHON_VERSION: '3.4' - PYTHON_ARCH: '64' - - TOXENV: 'py35,report,codecov' - TOXPYTHON: C:\Python35\python.exe - PYTHON_HOME: C:\Python35 - PYTHON_VERSION: '3.5' - PYTHON_ARCH: '32' - - TOXENV: 'py35,report,codecov' - TOXPYTHON: C:\Python35-x64\python.exe - PYTHON_HOME: C:\Python35-x64 - PYTHON_VERSION: '3.5' - PYTHON_ARCH: '64' - - TOXENV: 'py36,report,codecov' - TOXPYTHON: C:\Python36\python.exe - PYTHON_HOME: C:\Python36 - PYTHON_VERSION: '3.6' - PYTHON_ARCH: '32' - - TOXENV: 'py36,report,codecov' - TOXPYTHON: C:\Python36-x64\python.exe - PYTHON_HOME: C:\Python36-x64 - PYTHON_VERSION: '3.6' - PYTHON_ARCH: '64' - - TOXENV: 'py37,report,codecov' - TOXPYTHON: C:\Python37\python.exe - PYTHON_HOME: C:\Python37 - PYTHON_VERSION: '3.7' - PYTHON_ARCH: '32' - - TOXENV: 'py37,report,codecov' - TOXPYTHON: C:\Python37-x64\python.exe - PYTHON_HOME: C:\Python37-x64 - PYTHON_VERSION: '3.7' - PYTHON_ARCH: '64' -init: - - ps: echo $env:TOXENV - - ps: ls C:\Python* -install: - - python -u ci\appveyor-bootstrap.py - - '%PYTHON_HOME%\Scripts\virtualenv --version' - - '%PYTHON_HOME%\Scripts\easy_install --version' - - '%PYTHON_HOME%\Scripts\pip --version' - - '%PYTHON_HOME%\Scripts\tox --version' -test_script: - - '%WITH_COMPILER% %PYTHON_HOME%\Scripts\tox' - -on_failure: - - ps: dir "env:" - - ps: get-content .tox\*\log\* -artifacts: - - path: dist\* - -### To enable remote debugging uncomment this (also, see: http://www.appveyor.com/docs/how-to/rdp-to-build-worker): -# on_finish: -# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/ci/appveyor-bootstrap.py b/ci/appveyor-bootstrap.py deleted file mode 100644 index dd76230..0000000 --- a/ci/appveyor-bootstrap.py +++ /dev/null @@ -1,111 +0,0 @@ -""" -AppVeyor will at least have few Pythons around so there's no point of implementing a bootstrapper in PowerShell. - -This is a port of https://github.com/pypa/python-packaging-user-guide/blob/master/source/code/install.ps1 -with various fixes and improvements that just weren't feasible to implement in PowerShell. -""" -from __future__ import print_function -from os import environ -from os.path import exists -from subprocess import check_call - -try: - from urllib.request import urlretrieve -except ImportError: - from urllib import urlretrieve - -BASE_URL = "https://www.python.org/ftp/python/" -GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" -GET_PIP_PATH = "C:\get-pip.py" -URLS = { - ("2.7", "64"): BASE_URL + "2.7.13/python-2.7.13.amd64.msi", - ("2.7", "32"): BASE_URL + "2.7.13/python-2.7.13.msi", - ("3.4", "64"): BASE_URL + "3.4.4/python-3.4.4.amd64.msi", - ("3.4", "32"): BASE_URL + "3.4.4/python-3.4.4.msi", - ("3.5", "64"): BASE_URL + "3.5.4/python-3.5.4-amd64.exe", - ("3.5", "32"): BASE_URL + "3.5.4/python-3.5.4.exe", - ("3.6", "64"): BASE_URL + "3.6.2/python-3.6.2-amd64.exe", - ("3.6", "32"): BASE_URL + "3.6.2/python-3.6.2.exe", -} -INSTALL_CMD = { - # Commands are allowed to fail only if they are not the last command. Eg: uninstall (/x) allowed to fail. - "2.7": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"], - ["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]], - "3.4": [["msiexec.exe", "/L*+!", "install.log", "/qn", "/x", "{path}"], - ["msiexec.exe", "/L*+!", "install.log", "/qn", "/i", "{path}", "TARGETDIR={home}"]], - "3.5": [["{path}", "/quiet", "TargetDir={home}"]], - "3.6": [["{path}", "/quiet", "TargetDir={home}"]], -} - - -def download_file(url, path): - print("Downloading: {} (into {})".format(url, path)) - progress = [0, 0] - - def report(count, size, total): - progress[0] = count * size - if progress[0] - progress[1] > 1000000: - progress[1] = progress[0] - print("Downloaded {:,}/{:,} ...".format(progress[1], total)) - - dest, _ = urlretrieve(url, path, reporthook=report) - return dest - - -def install_python(version, arch, home): - print("Installing Python", version, "for", arch, "bit architecture to", home) - if exists(home): - return - - path = download_python(version, arch) - print("Installing", path, "to", home) - success = False - for cmd in INSTALL_CMD[version]: - cmd = [part.format(home=home, path=path) for part in cmd] - print("Running:", " ".join(cmd)) - try: - check_call(cmd) - except Exception as exc: - print("Failed command", cmd, "with:", exc) - if exists("install.log"): - with open("install.log") as fh: - print(fh.read()) - else: - success = True - if success: - print("Installation complete!") - else: - print("Installation failed") - - -def download_python(version, arch): - for _ in range(3): - try: - return download_file(URLS[version, arch], "installer.exe") - except Exception as exc: - print("Failed to download:", exc) - print("Retrying ...") - - -def install_pip(home): - pip_path = home + "/Scripts/pip.exe" - python_path = home + "/python.exe" - if exists(pip_path): - print("pip already installed.") - else: - print("Installing pip...") - download_file(GET_PIP_URL, GET_PIP_PATH) - print("Executing:", python_path, GET_PIP_PATH) - check_call([python_path, GET_PIP_PATH]) - - -def install_packages(home, *packages): - cmd = [home + "/Scripts/pip.exe", "install"] - cmd.extend(packages) - check_call(cmd) - - -if __name__ == "__main__": - install_python(environ['PYTHON_VERSION'], environ['PYTHON_ARCH'], environ['PYTHON_HOME']) - install_pip(environ['PYTHON_HOME']) - install_packages(environ['PYTHON_HOME'], "setuptools>=18.0.1", "wheel", "tox", "virtualenv>=13.1.0") diff --git a/ci/appveyor-download.py b/ci/appveyor-download.py deleted file mode 100755 index c119bd6..0000000 --- a/ci/appveyor-download.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python -""" -Use the AppVeyor API to download Windows artifacts. - -Taken from: https://bitbucket.org/ned/coveragepy/src/tip/ci/download_appveyor.py -# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 -# For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt -""" -from __future__ import unicode_literals - -import argparse -import os -import zipfile - -import requests - - -def make_auth_headers(): - """Make the authentication headers needed to use the Appveyor API.""" - path = os.path.expanduser("~/.appveyor.token") - if not os.path.exists(path): - raise RuntimeError( - "Please create a file named `.appveyor.token` in your home directory. " - "You can get the token from https://ci.appveyor.com/api-token" - ) - with open(path) as f: - token = f.read().strip() - - headers = { - 'Authorization': 'Bearer {}'.format(token), - } - return headers - - -def download_latest_artifacts(account_project, build_id): - """Download all the artifacts from the latest build.""" - if build_id is None: - url = "https://ci.appveyor.com/api/projects/{}".format(account_project) - else: - url = "https://ci.appveyor.com/api/projects/{}/build/{}".format(account_project, build_id) - build = requests.get(url, headers=make_auth_headers()).json() - jobs = build['build']['jobs'] - print(u"Build {0[build][version]}, {1} jobs: {0[build][message]}".format(build, len(jobs))) - - for job in jobs: - name = job['name'] - print(u" {0}: {1[status]}, {1[artifactsCount]} artifacts".format(name, job)) - - url = "https://ci.appveyor.com/api/buildjobs/{}/artifacts".format(job['jobId']) - response = requests.get(url, headers=make_auth_headers()) - artifacts = response.json() - - for artifact in artifacts: - is_zip = artifact['type'] == "Zip" - filename = artifact['fileName'] - print(u" {0}, {1} bytes".format(filename, artifact['size'])) - - url = "https://ci.appveyor.com/api/buildjobs/{}/artifacts/{}".format(job['jobId'], filename) - download_url(url, filename, make_auth_headers()) - - if is_zip: - unpack_zipfile(filename) - os.remove(filename) - - -def ensure_dirs(filename): - """Make sure the directories exist for `filename`.""" - dirname = os.path.dirname(filename) - if dirname and not os.path.exists(dirname): - os.makedirs(dirname) - - -def download_url(url, filename, headers): - """Download a file from `url` to `filename`.""" - ensure_dirs(filename) - response = requests.get(url, headers=headers, stream=True) - if response.status_code == 200: - with open(filename, 'wb') as f: - for chunk in response.iter_content(16 * 1024): - f.write(chunk) - else: - print(u" Error downloading {}: {}".format(url, response)) - - -def unpack_zipfile(filename): - """Unpack a zipfile, using the names in the zip.""" - with open(filename, 'rb') as fzip: - z = zipfile.ZipFile(fzip) - for name in z.namelist(): - print(u" extracting {}".format(name)) - ensure_dirs(name) - z.extract(name) - - -parser = argparse.ArgumentParser(description='Download artifacts from AppVeyor.') -parser.add_argument('--id', - metavar='PROJECT_ID', - default='MGlauer/omi', - help='Project ID in AppVeyor.') -parser.add_argument('build', - nargs='?', - metavar='BUILD_ID', - help='Build ID in AppVeyor. Eg: master-123') - -if __name__ == "__main__": - # import logging - # logging.basicConfig(level="DEBUG") - args = parser.parse_args() - download_latest_artifacts(args.id, args.build) diff --git a/ci/appveyor-with-compiler.cmd b/ci/appveyor-with-compiler.cmd deleted file mode 100644 index 289585f..0000000 --- a/ci/appveyor-with-compiler.cmd +++ /dev/null @@ -1,23 +0,0 @@ -:: Very simple setup: -:: - if WINDOWS_SDK_VERSION is set then activate the SDK. -:: - disable the WDK if it's around. - -SET COMMAND_TO_RUN=%* -SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows -SET WIN_WDK="c:\Program Files (x86)\Windows Kits\10\Include\wdf" -ECHO SDK: %WINDOWS_SDK_VERSION% ARCH: %PYTHON_ARCH% - -IF EXIST %WIN_WDK% ( - REM See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/ - REN %WIN_WDK% 0wdf -) -IF "%WINDOWS_SDK_VERSION%"=="" GOTO main - -SET DISTUTILS_USE_SDK=1 -SET MSSdk=1 -"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% -CALL "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release - -:main -ECHO Executing: %COMMAND_TO_RUN% -CALL %COMMAND_TO_RUN% || EXIT 1 diff --git a/ci/bootstrap.py b/ci/bootstrap.py deleted file mode 100755 index a672e05..0000000 --- a/ci/bootstrap.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - -import os -import sys -from os.path import abspath -from os.path import dirname -from os.path import exists -from os.path import join - - -if __name__ == "__main__": - base_path = dirname(dirname(abspath(__file__))) - print("Project path: {0}".format(base_path)) - env_path = join(base_path, ".tox", "bootstrap") - if sys.platform == "win32": - bin_path = join(env_path, "Scripts") - else: - bin_path = join(env_path, "bin") - if not exists(env_path): - import subprocess - - print("Making bootstrap env in: {0} ...".format(env_path)) - try: - subprocess.check_call(["virtualenv", env_path]) - except subprocess.CalledProcessError: - subprocess.check_call([sys.executable, "-m", "virtualenv", env_path]) - print("Installing `jinja2` into bootstrap environment...") - subprocess.check_call([join(bin_path, "pip"), "install", "jinja2"]) - python_executable = join(bin_path, "python") - if not os.path.samefile(python_executable, sys.executable): - print("Re-executing with: {0}".format(python_executable)) - os.execv(python_executable, [python_executable, __file__]) - - import jinja2 - - import subprocess - - jinja = jinja2.Environment( - loader=jinja2.FileSystemLoader(join(base_path, "ci", "templates")), - trim_blocks=True, - lstrip_blocks=True, - keep_trailing_newline=True - ) - - tox_environments = [ - line.strip() - # WARNING: 'tox' must be installed globally or in the project'structure virtualenv - for line in subprocess.check_output(['tox', '--listenvs'], universal_newlines=True).splitlines() - ] - tox_environments = [line for line in tox_environments if line not in ['clean', 'report', 'docs', 'check']] - - for name in os.listdir(join("ci", "templates")): - with open(join(base_path, name), "w") as fh: - fh.write(jinja.get_template(name).render(tox_environments=tox_environments)) - print("Wrote {}".format(name)) - print("DONE.") diff --git a/ci/templates/.travis.yml b/ci/templates/.travis.yml deleted file mode 100644 index 6776daa..0000000 --- a/ci/templates/.travis.yml +++ /dev/null @@ -1,59 +0,0 @@ -language: python -cache: pip -env: - global: - - LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so - - SEGFAULT_SIGNALS=all - matrix: - - TOXENV=check - - TOXENV=docs -matrix: - include: -{%- for env in tox_environments %}{{ '' }} - - python: '{{ env.split("-")[0] if env.startswith("pypy") else "{0[2]}.{0[3]}".format(env) }}' -{% if env.startswith('py37') %} - dist: xenial -{% endif %} - env: - - TOXENV={{ env }},report,codecov -{%- endfor %}{{ '' }} -before_install: - - python --version - - uname -a - - lsb_release -a -install: - - pip install tox - - virtualenv --version - - easy_install --version - - pip --version - - tox --version - - | - set -ex - if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then - (cd $HOME - wget https://bitbucket.org/pypy/pypy/downloads/pypy2-v6.0.0-linux64.tar.bz2 - tar xf pypy2-*.tar.bz2 - pypy2-*/bin/pypy -m ensurepip - pypy2-*/bin/pypy -m pip install -U virtualenv) - export PATH=$(echo $HOME/pypy2-*/bin):$PATH - export TOXPYTHON=$(echo $HOME/pypy2-*/bin/pypy) - fi - if [[ $TRAVIS_PYTHON_VERSION == 'pypy3' ]]; then - (cd $HOME - wget https://bitbucket.org/pypy/pypy/downloads/pypy3-v6.0.0-linux64.tar.bz2 - tar xf pypy3-*.tar.bz2 - pypy3-*/bin/pypy3 -m ensurepip - pypy3-*/bin/pypy3 -m pip install -U virtualenv) - export PATH=$(echo $HOME/pypy3-*/bin):$PATH - export TOXPYTHON=$(echo $HOME/pypy3-*/bin/pypy3) - fi - set +x -script: - - tox -v -after_failure: - - more .tox/log/* | cat - - more .tox/*/log/* | cat -notifications: - email: - on_success: never - on_failure: always diff --git a/ci/templates/appveyor.yml b/ci/templates/appveyor.yml deleted file mode 100644 index 0006daa..0000000 --- a/ci/templates/appveyor.yml +++ /dev/null @@ -1,51 +0,0 @@ -version: '{branch}-{build}' -build: off -cache: - - '%LOCALAPPDATA%\pip\Cache' -environment: - global: - WITH_COMPILER: 'cmd /E:ON /V:ON /C .\ci\appveyor-with-compiler.cmd' - matrix: - - TOXENV: check - TOXPYTHON: C:\Python36\python.exe - PYTHON_HOME: C:\Python36 - PYTHON_VERSION: '3.6' - PYTHON_ARCH: '32' -{% for env in tox_environments %}{{ '' }}{% if env.startswith(('py2', 'py3')) %} - - TOXENV: '{{ env }},report,codecov' - TOXPYTHON: C:\Python{{ env[2:4] }}\python.exe - PYTHON_HOME: C:\Python{{ env[2:4] }} - PYTHON_VERSION: '{{ env[2] }}.{{ env[3] }}' - PYTHON_ARCH: '32' - - TOXENV: '{{ env }},report,codecov' - TOXPYTHON: C:\Python{{ env[2:4] }}-x64\python.exe - {%- if env.startswith(('py2', 'py34')) %} - - WINDOWS_SDK_VERSION: v7.{{ '1' if env.startswith('py3') else '0' }} - {%- endif %} - - PYTHON_HOME: C:\Python{{ env[2:4] }}-x64 - PYTHON_VERSION: '{{ env[2] }}.{{ env[3] }}' - PYTHON_ARCH: '64' -{% endif %}{% endfor %} -init: - - ps: echo $env:TOXENV - - ps: ls C:\Python* -install: - - python -u ci\appveyor-bootstrap.py - - '%PYTHON_HOME%\Scripts\virtualenv --version' - - '%PYTHON_HOME%\Scripts\easy_install --version' - - '%PYTHON_HOME%\Scripts\pip --version' - - '%PYTHON_HOME%\Scripts\tox --version' -test_script: - - '%WITH_COMPILER% %PYTHON_HOME%\Scripts\tox' - -on_failure: - - ps: dir "env:" - - ps: get-content .tox\*\log\* -artifacts: - - path: dist\* - -### To enable remote debugging uncomment this (also, see: http://www.appveyor.com/docs/how-to/rdp-to-build-worker): -# on_finish: -# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/docs/authors.rst b/docs/authors.rst deleted file mode 100644 index e122f91..0000000 --- a/docs/authors.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../AUTHORS.rst diff --git a/docs/changelog.rst b/docs/changelog.rst deleted file mode 100644 index 565b052..0000000 --- a/docs/changelog.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../CHANGELOG.rst diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 7100b12..0000000 --- a/docs/conf.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import os - - -extensions = [ - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.coverage", - "sphinx.ext.doctest", - "sphinx.ext.extlinks", - "sphinx.ext.ifconfig", - "sphinx.ext.napoleon", - "sphinx.ext.todo", - "sphinx.ext.viewcode", - "sphinx_click.ext", -] - -if os.getenv("SPELLCHECK"): - extensions += ("sphinxcontrib.spelling",) - spelling_show_suggestions = True - spelling_lang = "en_US" - -source_suffix = ".rst" -master_doc = "index" -project = "omi" -year = "2019" -author = "Martin Glauer" -copyright = "{0}, {1}".format(year, author) -version = release = "0.2.1" - -pygments_style = "trac" -templates_path = ["."] -extlinks = { - "issue": ("https://github.com/OpenEnergyPlatform/omi/issues/%structure", "#"), - "pr": ("https://github.com/OpenEnergyPlatform/omi/pull/%structure", "PR #"), -} -# on_rtd is whether we are on readthedocs.org -on_rtd = os.environ.get("READTHEDOCS", None) == "True" - -if not on_rtd: # only set the theme if we"re building docs locally - html_theme = "sphinx_rtd_theme" - -html_use_smartypants = True -html_last_updated_fmt = "%b %d, %Y" -html_split_index = False -html_sidebars = {"**": ["searchbox.html", "globaltoc.html", "sourcelink.html"]} -html_short_title = "%s-%s" % (project, version) - -napoleon_use_ivar = True -napoleon_use_rtype = False -napoleon_use_param = False diff --git a/docs/contributing.rst b/docs/contributing.rst deleted file mode 100644 index e582053..0000000 --- a/docs/contributing.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../CONTRIBUTING.rst diff --git a/docs/dialect.rst b/docs/dialect.rst deleted file mode 100644 index 7bdff16..0000000 --- a/docs/dialect.rst +++ /dev/null @@ -1,38 +0,0 @@ -.. _dialect: - -======== -Dialects -======== - -This section discusses the concepts of :class:`~omi.dialects.base.dialect.Parser`, :class:`~omi.dialects.base.dialect.Compiler` and -:class:`~omi.dialects.base.dialect.Dialect` - -The OMI tool handles all metadata in an internal data structure that covers the -relevant information needed to describe data. Different metadata formats -(e.g. the OEP metadata format) can be **parsed** into this structure or -**compiled** from it. - -Therefore, OMI uses the notion of **Parser** and **Compiler**. A -:class:`~omi.dialects.base.dialect.Dialect` combines the functionalities of -:class:`~omi.dialects.base.dialect.Parser`, -:class:`~omi.dialects.base.dialect.Compiler` and adds some convenience methods -to it. Each dialect has an id that can be used to call it via the :ref:`command line interface` - -.. _available_dialects: - -Available dialects are: - - `oep-v1.3` - - `oep-v1.4` - - `oep-rdf-v1.4` - - `oep-v1.5` - -.. autoclass:: omi.dialects.base.dialect.Parser - :members: - -.. autoclass:: omi.dialects.base.dialect.Compiler - :members: - -.. autoclass:: omi.dialects.base.dialect.Dialect - :members: - - diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 982cc97..0000000 --- a/docs/index.rst +++ /dev/null @@ -1,25 +0,0 @@ -======== -Contents -======== - -.. toctree:: - :maxdepth: 2 - - readme - installation - usage - reference/index - contributing - authors - changelog - internal_structure - dialect - oep_metadata - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/docs/installation.rst b/docs/installation.rst deleted file mode 100644 index 3ddbdf9..0000000 --- a/docs/installation.rst +++ /dev/null @@ -1,7 +0,0 @@ -============ -Installation -============ - -At the command line:: - - pip install omi diff --git a/docs/internal_structure.rst b/docs/internal_structure.rst deleted file mode 100644 index 87849ec..0000000 --- a/docs/internal_structure.rst +++ /dev/null @@ -1,8 +0,0 @@ -============ -OMI Metadata -============ - -.. autoclass:: omi.structure.Compilable - :members: - - .. autoattribute:: omi.structure.Compilable.__compiler_name__ diff --git a/docs/oep_metadata.rst b/docs/oep_metadata.rst deleted file mode 100644 index 05dd42e..0000000 --- a/docs/oep_metadata.rst +++ /dev/null @@ -1,55 +0,0 @@ -====================== -Translations in Python -====================== - -.. testsetup:: * - - from omi.dialects.oep.dialect import OEP_V_1_3_Dialect, OEP_V_1_4_Dialect, OEP_V_1_5_Dialect - -In order to perform the translation from one dialect to another, you need to -parse your input using the respective input dialect. As a minimal example, let's -say you have a metadata string in the outdated version 1.3 and aim to update it -to the more modern version 1.4. - -Step 1: Parse it -**************** - -Your first step is to parse the given string using :class:`omi.dialects.oep.dialect.OEP_V_1_3_Dialect`. -For starters, we use the most basic metadata string: The empty dictionary - -.. doctest:: - - >>> inp = '{}' - >>> dialect1_3 = OEP_V_1_3_Dialect() - >>> parsed = dialect1_3.parse(inp) - >>> parsed - OEPMetadata(name=None,title=None,identifier=None,description=None,languages=None,keywords=None,publication_date=None,context=None,spatial=None,temporal=None,sources=None,license=None,contributions=None,resources=None,review=None,comment=None) - -The input has been parsed into the internal structure i.e. an :class:`OEPMetadata`-object. - -Step 2: Change it -***************** - -If needed you can feel free to manipulate this string according to your use case. -Don't forget to document your changes under contributions (ToDo) ;) - -In this example, we will add an identifier, as is required by OEP-Metadata v1.4 - -.. doctest:: - - >>> parsed.identifier = "unique_id" - >>> parsed - OEPMetadata(name=None,title=None,identifier=unique_id,description=None,languages=None,keywords=None,publication_date=None,context=None,spatial=None,temporal=None,sources=None,license=None,contributions=None,resources=None,review=None,comment=None) - -Step 3: Compile it -****************** - -Now that we have an :class:`OEPMetadata`-object we are happy with, we want to translate it to the -new metadata format by using the respective dialect - -.. doctest:: - - >>> dialect1_4 = OEP_V_1_4_Dialect() - >>> dialect1_4._compiler.OMIT_NONE_FIELDS = True - >>> dialect1_4.compile(parsed) - {'id': 'unique_id', 'metaMetadata': {'metadataVersion': 'OEP-1.4.0', 'metadataLicense': {'name': 'CC0-1.0', 'title': 'Creative Commons Zero v1.0 Universal', 'path': 'https://creativecommons.org/publicdomain/zero/1.0/'}}} diff --git a/docs/readme.rst b/docs/readme.rst deleted file mode 100644 index 72a3355..0000000 --- a/docs/readme.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../README.rst diff --git a/docs/reference/index.rst b/docs/reference/index.rst deleted file mode 100644 index 7adef7f..0000000 --- a/docs/reference/index.rst +++ /dev/null @@ -1,7 +0,0 @@ -Reference -========= - -.. toctree:: - :glob: - - omi* diff --git a/docs/reference/omi.rst b/docs/reference/omi.rst deleted file mode 100644 index 2ce1117..0000000 --- a/docs/reference/omi.rst +++ /dev/null @@ -1,9 +0,0 @@ -omi -============= - -.. testsetup:: - - from omi import * - -.. automodule:: omi - :members: diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 2c15642..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -sphinx>=1.3 -sphinx-rtd-theme -sphinx-click --e . diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt deleted file mode 100644 index f95eb78..0000000 --- a/docs/spelling_wordlist.txt +++ /dev/null @@ -1,11 +0,0 @@ -builtin -builtins -classmethod -staticmethod -classmethods -staticmethods -args -kwargs -callstack -Changelog -Indices diff --git a/docs/usage.rst b/docs/usage.rst deleted file mode 100644 index 753f1c3..0000000 --- a/docs/usage.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _cli: - -===== -Usage -===== - -.. click:: omi.cli:cli - :prog: omi - :show-nested: - -A list of available dialects can be found in the :ref:`dialect segment` - -To use omi in a project:: - - import omi diff --git a/examples/data/metadata_v14.json b/examples/data/metadata_v14.json deleted file mode 100644 index b32323b..0000000 --- a/examples/data/metadata_v14.json +++ /dev/null @@ -1,247 +0,0 @@ -{ - "name": "oep_metadata_table_example_v14", - "title": "Good example title", - "id": "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14", - "description": "example metadata for example data", - "language": [ - "en-GB", - "en-US", - "de-DE", - "fr-FR" - ], - "keywords": [ - "example", - "template", - "test" - ], - "publicationDate": "2018-06-12", - "context": { - "homepage": "https://reiner-lemoine-institut.de/szenariendb/", - "documentation": "https://github.com/OpenEnergyPlatform/organisation/wiki/metadata", - "sourceCode": "https://github.com/OpenEnergyPlatform/examples/tree/master/metadata", - "contact": "https://github.com/Ludee", - "grantNo": "03ET4057", - "fundingAgency": "Bundesministerium für Wirtschaft und Energie", - "fundingAgencyLogo": "https://www.innovation-beratung-foerderung.de/INNO/Redaktion/DE/Bilder/Titelbilder/titel_foerderlogo_bmwi.jpg?__blob=poster&v=2", - "publisherLogo": "https://reiner-lemoine-institut.de//wp-content/uploads/2015/09/rlilogo.png" - }, - "spatial": { - "extent": "europe", - "resolution": "100 m" - }, - "temporal": { - "referenceDate": "2016-01-01", - "timeseries": { - "start": "2017-01-01T00:00+01", - "end": "2017-12-31T23:00+01", - "resolution": "1 h", - "alignment": "left", - "aggregationType": "sum" - } - }, - "sources": [ - { - "title": "OpenEnergyPlatform Metadata Example", - "description": "Metadata description", - "path": "https://github.com/OpenEnergyPlatform", - "licenses": [ - { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/legalcode", - "instruction": "You are free: To Share, To Create, To Adapt", - "attribution": "© Reiner Lemoine Institut" - } - ] - }, - { - "title": "OpenStreetMap", - "description": "A collaborative project to create a free editable map of the world", - "path": "https://www.openstreetmap.org/", - "licenses": [ - { - "name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© OpenStreetMap contributors" - } - ] - } - ], - "licenses": [ - { - "name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© Reiner Lemoine Institut © OpenStreetMap contributors" - } - ], - "contributors": [ - { - "title": "Ludee", - "date": "2016-06-16", - "object": "metadata", - "comment": "Create metadata" - }, - { - "title": "Ludee", - "date": "2016-11-22", - "object": "metadata", - "comment": "Update metadata" - }, - { - "title": "Ludee", - "date": "2016-11-22", - "object": "metadata", - "comment": "Update header and license" - }, - { - "title": "Ludee", - "date": "2017-03-16", - "object": "metadata", - "comment": "Add license to source" - }, - { - "title": "Ludee", - "date": "2017-03-28", - "object": "metadata", - "comment": "Add copyright to source and license" - }, - { - "title": "Ludee", - "date": "2017-05-30", - "object": "metadata", - "comment": "Release metadata version 1.3" - }, - { - "title": "Ludee", - "date": "2017-06-26", - "object": "metadata", - "comment": "Move referenceDate into temporal and remove array" - }, - { - "title": "Ludee", - "date": "2018-07-19", - "object": "metadata", - "comment": "Start metadata version 1.4" - }, - { - "title": "Ludee", - "date": "2018-07-26", - "object": "data", - "comment": "Rename table and files" - }, - { - "title": "Ludee", - "date": "2018-10-18", - "object": "metadata", - "comment": "Add contribution object" - }, - { - "title": "christian-rli", - "date": "2018-10-18", - "object": "metadata", - "comment": "Add datapackage compatibility" - }, - { - "title": "Ludee", - "date": "2018-11-02", - "object": "metadata", - "comment": "Release metadata version 1.4" - }, - { - "title": "christian-rli", - "date": "2019-02-05", - "object": "metadata", - "comment": "Apply template structure to example" - }, - { - "title": "Ludee", - "date": "2019-03-22", - "object": "metadata", - "comment": "Hotfix foreignKeys" - }, - { - "title": "Ludee", - "date": "2019-07-09", - "object": "metadata", - "comment": "Release metadata version OEP-1.3.0" - } - ], - "resources": [ - { - "profile": "tabular-data-resource", - "name": "model_draft.oep_metadata_table_example_v14", - "path": "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14", - "format": "PostgreSQL", - "encoding": "UTF-8", - "schema": { - "fields": [ - { - "name": "id", - "description": "Unique identifier", - "type": "serial" - }, - { - "name": "year", - "description": "Reference year", - "type": "integer" - }, - { - "name": "value", - "description": "Example value", - "type": "double precision", - "unit": "MW" - }, - { - "name": "geom", - "description": "Geometry", - "type": "geometry(Point, 4326)" - } - ], - "primaryKey": [ - "id" - ], - "foreignKeys": [ - { - "fields": [ - "year" - ], - "reference": { - "resource": "schema.table", - "fields": [ - "year" - ] - } - } - ] - }, - "dialect": { - "decimalSeparator": "." - } - } - ], - "review": { - "path": "https://github.com/OpenEnergyPlatform/data-preprocessing/wiki", - "badge": "platin" - }, - "metaMetadata": { - "metadataVersion": "OEP-1.4.0", - "metadataLicense": { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/" - } - }, - "_comment": { - "metadata": "Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/organisation/wiki/metadata)", - "dates": "Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - "units": "Use a space between numbers and units (100 m)", - "languages": "Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - "licenses": "License name must follow the SPDX License List (https://spdx.org/licenses/)", - "review": "Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/wiki)", - "null": "If not applicable use (null)" - } -} \ No newline at end of file diff --git a/examples/snippets/oeps_current_metadata_validation_using_omi.py b/examples/snippets/oeps_current_metadata_validation_using_omi.py deleted file mode 100644 index 7a1f1fc..0000000 --- a/examples/snippets/oeps_current_metadata_validation_using_omi.py +++ /dev/null @@ -1,106 +0,0 @@ -from omi.dialects.oep.parser import ParserException -from omi.structure import Compilable - -from omi.dialects.oep import OEP_V_1_4_Dialect, OEP_V_1_5_Dialect -from omi.dialects.oep.compiler import JSONCompiler - -import json - - -# This is a list because I copied and pasted something and normally all oemeta data versions are checked - this is not relevant for you @Jann -METADATA_PARSERS = [OEP_V_1_5_Dialect()] -METADATA_COMPILERS = [OEP_V_1_5_Dialect(), JSONCompiler()] - - -# check 1 - is metadata parseable by OMI -def try_parse_metadata(inp): - """ - - Args: - inp: string or dict or OEPMetadata - - Returns: - Tuple[OEPMetadata or None, string or None]: - The first component is the result of the parsing procedure or `None` if - the parsing failed. The second component is None, if the parsing failed, - otherwise an error message. - - Examples: - - >>> from api.actions import try_parse_metadata - >>> result, error = try_parse_metadata('{"id":"id"}') - >>> error is None - True - - """ - - if isinstance(inp, Compilable): - # already parsed - return inp, None - elif not isinstance(inp, (str, bytes)): - # in order to use the omi parsers, input needs to be str (or bytes) - try: - inp = json.dumps(inp) - except Exception: - return None, "Could not serialize json" - - last_err = None - # try all the dialects - for parser in METADATA_PARSERS: - try: - return parser.parse(inp), None - except ParserException as e: - return None, str(e) - except Exception as e: - last_err = e - return None, str(e) - # APIError(f"Metadata could not be parsed: {last_err}") - # try next dialect - - print(f"Metadata could not be parsed: {last_err}") - -# check 2 - Is metadata compilable by omi (complies with the oemetadata spec) -def try_compile_metadata(inp): - """ - - Args: - inp: OEPMetadata - result of omi.parse(dict) - - Returns: - Tuple[str or None, str or None]: - The first component is the result of the compiling procedure or `None` if - the compiling failed. The second component is None if the compiling failed, - otherwise an error message. - """ - last_err = None - # try all the dialects - for compiler in METADATA_COMPILERS: - try: - return compiler.compile(inp), None - except Exception as e: - last_err = e - # APIError(f"Metadata could not be compiled: {last_err}") - # try next dialect - - print(f"Metadata could not be compiled: {last_err}") - -# use this instead of omis validation -# this is what is happening on the oep before the metadata is saved to persistence -def check_oemetadata_is_oep_compatible(_input_file = "examples/data/metadata_v15.json"): - - with open(_input_file, "rb") as inp: - # file = inp.read() - metadata = json.load(inp) - - metadata_oep, err = try_parse_metadata(metadata) - if not err: - metadata_obj, err = try_compile_metadata(metadata_oep) - else: - raise Exception(err) - - if not err: - metadata_str = json.dumps(metadata_obj, ensure_ascii=False) - return metadata_str - else: - raise Exception(err) - diff --git a/examples/snippets/test_dialect.py b/examples/snippets/test_dialect.py deleted file mode 100644 index 3873fbb..0000000 --- a/examples/snippets/test_dialect.py +++ /dev/null @@ -1,151 +0,0 @@ -from omi.dialects.oep.dialect import OEP_V_1_3_Dialect, OEP_V_1_4_Dialect, OEP_V_1_5_Dialect -from omi.dialects.oep.parser import JSONParser -from omi.dialects.oep.parser import ParserException -from omi.structure import Compilable - -from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA - -import json - - -def parse_and_compile(): - inp = '{"id":"unique_id"}' #or read from json file - dialect1_5 = OEP_V_1_5_Dialect() - parsed = dialect1_5.parse(inp) - print(parsed) - parsed.identifier = "anotehr_unique_id" - compiled = dialect1_5.compile(parsed) - print(compiled) - -def validate_oemetadata(): - parser = JSONParser() - _input_file = "0_local_test/metadata_v15.json" - - # parser = JSONParser_1_5() - # _input_file = "tests/data/metadata_v15.json" - - with open(_input_file, "rb") as inp: - # file = inp.read() - file = json.load(inp) - - # file = parser.parse_from_file(_input_file) - # parser.validate(file, [OEMETADATA_LATEST_SCHEMA]) - return parser.is_valid(file) - - -# validate_oemetadata() - -from omi.dialects.oep import OEP_V_1_4_Dialect, OEP_V_1_5_Dialect -from omi.dialects.oep.compiler import JSONCompiler - -import pathlib - -METADATA_PARSERS = [OEP_V_1_5_Dialect(), OEP_V_1_4_Dialect()] -METADATA_COMPILERS = [OEP_V_1_5_Dialect(), OEP_V_1_4_Dialect(), JSONCompiler()] - -def try_parse_metadata(inp): - """ - - Args: - inp: string or dict or OEPMetadata - - Returns: - Tuple[OEPMetadata or None, string or None]: - The first component is the result of the parsing procedure or `None` if - the parsing failed. The second component is None, if the parsing failed, - otherwise an error message. - - Examples: - - >>> from api.actions import try_parse_metadata - >>> result, error = try_parse_metadata('{"id":"id"}') - >>> error is None - True - - """ - - if isinstance(inp, Compilable): - # already parsed - return inp, None - elif not isinstance(inp, (str, bytes)): - # in order to use the omi parsers, input needs to be str (or bytes) - try: - inp = json.dumps(inp) - except Exception: - return None, "Could not serialize json" - - last_err = None - # try all the dialects - for parser in METADATA_PARSERS: - try: - return parser.parse(inp), None - except ParserException as e: - return None, str(e) - except Exception as e: - last_err = e - return None, str(e) - # APIError(f"Metadata could not be parsed: {last_err}") - # try next dialect - - print(f"Metadata could not be parsed: {last_err}") - - -def try_compile_metadata(inp): - """ - - Args: - inp: OEPMetadata - - Returns: - Tuple[str or None, str or None]: - The first component is the result of the compiling procedure or `None` if - the compiling failed. The second component is None if the compiling failed, - otherwise an error message. - """ - last_err = None - # try all the dialects - for compiler in METADATA_COMPILERS: - try: - return compiler.compile(inp), None - except Exception as e: - last_err = e - # APIError(f"Metadata could not be compiled: {last_err}") - # try next dialect - - print(f"Metadata could not be compiled: {last_err}") - - -def set_table_metadata(metadata): - metadata_oep, err = try_parse_metadata(metadata) - if not err: - metadata_obj, err = try_compile_metadata(metadata_oep) - else: - raise Exception(err) - - if not err: - metadata_str = json.dumps(metadata_obj, ensure_ascii=False) - return metadata_str - else: - raise Exception(err) - - -def save_json(data: json, save_at: pathlib.Path = "examples/data/output/", filename: str = "omi_processed_metadata.json"): - - pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) - with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: - fp.write(data) - - -def run_oep_case(): - # _input_file = "tests/data/metadata_v15.json" - _input_file = "examples/data/metadata_v15.json" - - with open(_input_file, "rb") as inp: - # file = inp.read() - file = json.load(inp) - - jsn = set_table_metadata(file) - - save_json(data = jsn) - -run_oep_case() \ No newline at end of file diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..9fba0a6 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1452 @@ +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] + +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, +] + +[[package]] +name = "certifi" +version = "2024.7.4" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "distlib" +version = "0.3.8" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.1" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, + {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "filelock" +version = "3.14.0" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, + {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "frictionless" +version = "5.17.0" +description = "Data management framework for Python that provides functionality to describe, extract, validate, and transform tabular data" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frictionless-5.17.0-py3-none-any.whl", hash = "sha256:c7ceaf69f9430449971bd47d330f741d3d5d9513716308a2b05c56c25bdeb22d"}, + {file = "frictionless-5.17.0.tar.gz", hash = "sha256:bee4a9f076fab15e462772d09d3a496b50d73ec5ecb927d97b9307eeaefc6d3c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +chardet = ">=3.0" +humanize = ">=4.2" +isodate = ">=0.6" +jinja2 = ">=3.0" +jsonschema = ">=4.20" +marko = ">=1.0" +petl = ">=1.6" +pydantic = ">=2.0" +python-dateutil = ">=2.8" +python-slugify = ">=1.2" +pyyaml = ">=5.3" +requests = ">=2.10" +rfc3986 = ">=1.4" +simpleeval = ">=0.9.11" +stringcase = ">=1.2" +tabulate = ">=0.8.10" +typer = ">=0.12" +typing-extensions = ">=4.3" +validators = ">=0.18" + +[package.extras] +aws = ["boto3 (>=1.9)"] +bigquery = ["google-api-python-client (>=1.12.1)"] +ckan = ["frictionless-ckan-mapper (>=1.0)"] +datasette = ["datasette (>=0.64.2)"] +dev = ["hatch", "httpx", "ipython", "livemark", "moto", "neovim", "oauth2client", "pyright (==1.1.317)", "pytest", "pytest-cov", "pytest-dotenv", "pytest-lazy-fixtures", "pytest-mock", "pytest-only", "pytest-timeout", "pytest-vcr", "requests-mock", "ruff", "yattag"] +duckdb = ["duckdb (>=0.8)", "duckdb-engine (>=0.7)", "sqlalchemy (>=1.4)"] +excel = ["openpyxl (>=3.0)", "tableschema-to-template (>=0.0)", "xlrd (>=1.2)", "xlwt (>=1.2)"] +github = ["pygithub (>=1.50)"] +gsheets = ["pygsheets (>=2.0)"] +html = ["pyquery (>=1.4)"] +json = ["ijson (>=3.0)", "jsonlines (>=1.2)"] +mysql = ["pymysql (>=1.0)", "sqlalchemy (>=1.4)"] +ods = ["ezodf (>=0.3)", "lxml (>=4.0)"] +pandas = ["pandas (>=1.0)", "pyarrow (>=14.0)"] +parquet = ["fastparquet (>=0.8)"] +postgresql = ["psycopg (>=3.0)", "psycopg2 (>=2.9)", "sqlalchemy (>=1.4)"] +spss = ["savreaderwriter (>=3.0)"] +sql = ["sqlalchemy (>=1.4)"] +visidata = ["visidata (>=2.10)"] +wkt = ["tatsu (>=5.8.3)"] +zenodo = ["pyzenodo3 (>=1.0)"] + +[[package]] +name = "humanize" +version = "4.9.0" +description = "Python humanize utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "humanize-4.9.0-py3-none-any.whl", hash = "sha256:ce284a76d5b1377fd8836733b983bfb0b76f1aa1c090de2566fcf008d7f6ab16"}, + {file = "humanize-4.9.0.tar.gz", hash = "sha256:582a265c931c683a7e9b8ed9559089dea7edcf6cc95be39a3cbc2c5d5ac2bcfa"}, +] + +[package.extras] +tests = ["freezegun", "pytest", "pytest-cov"] + +[[package]] +name = "identify" +version = "2.5.36" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"}, + {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isodate" +version = "0.6.1" +description = "An ISO 8601 date/time/duration parser and formatter" +optional = false +python-versions = "*" +files = [ + {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, + {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsonschema" +version = "4.22.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"}, + {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "marko" +version = "2.0.3" +description = "A markdown parser with high extensibility." +optional = false +python-versions = ">=3.7" +files = [ + {file = "marko-2.0.3-py3-none-any.whl", hash = "sha256:7fca1c4ab1dbc09b4b3be83c22caafd7d97c99439cb4143d025727cb3df1f4d0"}, + {file = "marko-2.0.3.tar.gz", hash = "sha256:3b323dcd7dd48181871718ac09b3825bc8f74493cec378f2bacaaceec47577d4"}, +] + +[package.extras] +codehilite = ["pygments"] +repr = ["objprint"] +toc = ["python-slugify"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + +[[package]] +name = "numpy" +version = "1.26.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] + +[[package]] +name = "oemetadata" +version = "1.6.0" +description = "Open Energy Platform (OEP) - metadata schemas, examples and templates package" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oemetadata-1.6.0-py3-none-any.whl", hash = "sha256:61103a7333ed2a3482a4228fd13d74b0f08f5240e7d48a70c26e8a1901061ece"}, + {file = "oemetadata-1.6.0.tar.gz", hash = "sha256:8f57f10cded2cdeb20c9316477176d68808ff4ca74659cdd8a93cca0695f89da"}, +] + +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "pandas" +version = "2.2.2" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, + {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, + {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, + {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, + {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, + {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, + {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, + {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, + {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, + {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, + {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, + {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, + {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, + {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, + {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, + {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, + {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, + {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.22.4", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "petl" +version = "1.7.15" +description = "A Python package for extracting, transforming and loading tables of data." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "petl-1.7.15.tar.gz", hash = "sha256:8e31438380ad51552539865ad3b1ab655de1b531bd03980c871ec2cff4a8c414"}, +] + +[package.extras] +avro = ["fastavro (>=0.24.0)"] +bcolz = ["bcolz (>=1.2.1)"] +db = ["SQLAlchemy (>=1.3.6,<2.0)"] +hdf5 = ["cython (>=0.29.13)", "numexpr (>=2.6.9)", "numpy (>=1.16.4)", "tables (>=3.5.2)"] +http = ["aiohttp (>=3.6.2)", "requests"] +interval = ["intervaltree (>=3.0.2)"] +numpy = ["numpy (>=1.16.4)"] +pandas = ["pandas (>=0.24.2)"] +remote = ["fsspec (>=0.7.4)"] +smb = ["smbprotocol (>=1.0.1)"] +whoosh = ["whoosh"] +xls = ["xlrd (>=2.0.1)", "xlwt (>=1.3.0)"] +xlsx = ["openpyxl (>=2.6.2)"] +xpath = ["lxml (>=4.4.0)"] + +[[package]] +name = "platformdirs" +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "3.7.1" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"}, + {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "pydantic" +version = "2.7.2" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"}, + {file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.18.3" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.18.3" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"}, + {file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"}, + {file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"}, + {file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"}, + {file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"}, + {file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"}, + {file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"}, + {file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"}, + {file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"}, + {file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"}, + {file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"}, + {file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"}, + {file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"}, + {file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"}, + {file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"}, + {file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"}, + {file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"}, + {file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"}, + {file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"}, + {file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"}, + {file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"}, + {file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"}, + {file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"}, + {file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"}, + {file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"}, + {file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"}, + {file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"}, + {file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"}, + {file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyproject-api" +version = "1.6.1" +description = "API to interact with the python pyproject.toml based projects" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, + {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, +] + +[package.dependencies] +packaging = ">=23.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"] + +[[package]] +name = "pytest" +version = "8.2.1" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, + {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-slugify" +version = "8.0.4" +description = "A Python slugify application that also handles Unicode" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856"}, + {file = "python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8"}, +] + +[package.dependencies] +text-unidecode = ">=1.3" + +[package.extras] +unidecode = ["Unidecode (>=1.1.1)"] + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "rdflib" +version = "7.0.0" +description = "RDFLib is a Python library for working with RDF, a simple yet powerful language for representing information." +optional = false +python-versions = ">=3.8.1,<4.0.0" +files = [ + {file = "rdflib-7.0.0-py3-none-any.whl", hash = "sha256:0438920912a642c866a513de6fe8a0001bd86ef975057d6962c79ce4771687cd"}, + {file = "rdflib-7.0.0.tar.gz", hash = "sha256:9995eb8569428059b8c1affd26b25eac510d64f5043d9ce8c84e0d0036e995ae"}, +] + +[package.dependencies] +isodate = ">=0.6.0,<0.7.0" +pyparsing = ">=2.1.0,<4" + +[package.extras] +berkeleydb = ["berkeleydb (>=18.1.0,<19.0.0)"] +html = ["html5lib (>=1.0,<2.0)"] +lxml = ["lxml (>=4.3.0,<5.0.0)"] +networkx = ["networkx (>=2.0.0,<3.0.0)"] + +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, + {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rfc3986" +version = "2.0.0" +description = "Validating URI References per RFC 3986" +optional = false +python-versions = ">=3.7" +files = [ + {file = "rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd"}, + {file = "rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c"}, +] + +[package.extras] +idna2008 = ["idna"] + +[[package]] +name = "rich" +version = "13.7.1" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"}, + {file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "rpds-py" +version = "0.18.1" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53"}, + {file = "rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0"}, + {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da"}, + {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1"}, + {file = "rpds_py-0.18.1-cp310-none-win32.whl", hash = "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333"}, + {file = "rpds_py-0.18.1-cp310-none-win_amd64.whl", hash = "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8"}, + {file = "rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100"}, + {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e"}, + {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88"}, + {file = "rpds_py-0.18.1-cp311-none-win32.whl", hash = "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb"}, + {file = "rpds_py-0.18.1-cp311-none-win_amd64.whl", hash = "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3"}, + {file = "rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8"}, + {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac"}, + {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a"}, + {file = "rpds_py-0.18.1-cp312-none-win32.whl", hash = "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6"}, + {file = "rpds_py-0.18.1-cp312-none-win_amd64.whl", hash = "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74"}, + {file = "rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5"}, + {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e"}, + {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc"}, + {file = "rpds_py-0.18.1-cp38-none-win32.whl", hash = "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9"}, + {file = "rpds_py-0.18.1-cp38-none-win_amd64.whl", hash = "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93"}, + {file = "rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab"}, + {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b"}, + {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26"}, + {file = "rpds_py-0.18.1-cp39-none-win32.whl", hash = "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360"}, + {file = "rpds_py-0.18.1-cp39-none-win_amd64.whl", hash = "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c"}, + {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909"}, + {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49"}, + {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e"}, + {file = "rpds_py-0.18.1.tar.gz", hash = "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f"}, +] + +[[package]] +name = "setuptools" +version = "70.0.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"}, + {file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "shellingham" +version = "1.5.4" +description = "Tool to Detect Surrounding Shell" +optional = false +python-versions = ">=3.7" +files = [ + {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, + {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, +] + +[[package]] +name = "simpleeval" +version = "0.9.13" +description = "A simple, safe single expression evaluator library." +optional = false +python-versions = "*" +files = [ + {file = "simpleeval-0.9.13-py2.py3-none-any.whl", hash = "sha256:22a2701a5006e4188d125d34accf2405c2c37c93f6b346f2484b6422415ae54a"}, + {file = "simpleeval-0.9.13.tar.gz", hash = "sha256:4a30f9cc01825fe4c719c785e3762623e350c4840d5e6855c2a8496baaa65fac"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "stringcase" +version = "1.2.0" +description = "String case converter." +optional = false +python-versions = "*" +files = [ + {file = "stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008"}, +] + +[[package]] +name = "tabulate" +version = "0.9.0" +description = "Pretty-print tabular data" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, + {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, +] + +[package.extras] +widechars = ["wcwidth"] + +[[package]] +name = "text-unidecode" +version = "1.3" +description = "The most basic Text::Unidecode port" +optional = false +python-versions = "*" +files = [ + {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, + {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tox" +version = "4.15.0" +description = "tox is a generic virtualenv management and test command line tool" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tox-4.15.0-py3-none-any.whl", hash = "sha256:300055f335d855b2ab1b12c5802de7f62a36d4fd53f30bd2835f6a201dda46ea"}, + {file = "tox-4.15.0.tar.gz", hash = "sha256:7a0beeef166fbe566f54f795b4906c31b428eddafc0102ac00d20998dd1933f6"}, +] + +[package.dependencies] +cachetools = ">=5.3.2" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.13.1" +packaging = ">=23.2" +platformdirs = ">=4.1" +pluggy = ">=1.3" +pyproject-api = ">=1.6.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +virtualenv = ">=20.25" + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] +testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=8.0.2)", "distlib (>=0.3.8)", "flaky (>=3.7)", "hatch-vcs (>=0.4)", "hatchling (>=1.21)", "psutil (>=5.9.7)", "pytest (>=7.4.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-xdist (>=3.5)", "re-assert (>=1.1)", "time-machine (>=2.13)", "wheel (>=0.42)"] + +[[package]] +name = "typer" +version = "0.12.3" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.7" +files = [ + {file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"}, + {file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"}, +] + +[package.dependencies] +click = ">=8.0.0" +rich = ">=10.11.0" +shellingham = ">=1.3.0" +typing-extensions = ">=3.7.4.3" + +[[package]] +name = "typing-extensions" +version = "4.12.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, + {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, +] + +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + +[[package]] +name = "urllib3" +version = "2.2.2" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "validators" +version = "0.28.3" +description = "Python Data Validation for Humans™" +optional = false +python-versions = ">=3.8" +files = [ + {file = "validators-0.28.3-py3-none-any.whl", hash = "sha256:53cafa854f13850156259d9cc479b864ee901f6a96e6b109e6fc33f98f37d99f"}, + {file = "validators-0.28.3.tar.gz", hash = "sha256:c6c79840bcde9ba77b19f6218f7738188115e27830cbaff43264bc4ed24c429d"}, +] + +[[package]] +name = "virtualenv" +version = "20.26.2" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"}, + {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.9,<3.13" +content-hash = "0ee4a82f7293c59ce766ec9079900e1d13eb3ade6ae15a36fa50c7772dbe4917" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e58d855 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,80 @@ +[tool.poetry] +name = "omi" +version = "1.0.0" +description = "A library to process and translate open energy metadata." +authors = [ + "Hendrik Huyskens ", + "Jonas Huber ", + "Martin Glauer " +] +readme = "README.rst" +license = "AGPL-3.0" + +[tool.poetry.dependencies] +python = ">=3.9,<3.13" +click = "^8.1.7" +rdfLib = "^7.0.0" +python-dateutil = "^2.9.0" +jsonschema = "^4.22.0" +oemetadata = ">=1.5.2" +frictionless = "^5.17.0" +pandas = "^2.2.2" + +[tool.poetry.group.dev.dependencies] +tox = "^4.15.0" +pytest = "^8.2.1" +pre-commit = "^3.7.1" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.black] +line-length = 120 + +[tool.isort] +profile = "black" + +[tool.ruff] +line-length = 120 +select = ["ALL"] +exclude = [ + "manage.py", + "digiplan/utils/ogr_layer_mapping.py", + "config/wsgi.py", + "digiplan/contrib/*", + "merge_local_dotenvs_in_dotenv.py", + "digiplan/utils/context_processors.py" +] +ignore = [ + "I001", # Import block is un-sorted or un-formatted (done by isort) + "D203", # 1 blank line required before class docstring + "D212", # Multi-line docstring summary should start at the first line pydocstyle + "ANN101", # Missing type annotation for `self` in method + "ANN102", # Missing type annotation for `cls` in classmethod + "ANN003", # Missing type annotation for `**kwargs` + "EM102", # Exception must not use an f-string literal, assign to variable first + "TRY003", # Avoid specifying long messages outside the exception class + "S101", # Use of `assert` detected + "UP007", # Use `X | Y` for type annotations + "B905", # `zip()` without an explicit `strict=` parameter + "FIX001", # Line contains FIXME + "FIX002", # Line contains TODO + "RET504", # Unnecessary variable assignment before `return` statement + "G004", # Logging statement uses f-string + "PD011", # Use `.to_numpy()` instead of `.values` (does not work out of the box) + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + "UP038", # (non-pep604-isinstance) +] +fix = true +show-fixes = true +unfixable = ["UP007", "I001"] + +[tool.ruff.per-file-ignores] +"tests/*" = [ + "PLR2004", # Magic value used in comparison + "ANN201", # Missing return type annotation for public function +] +"*/__init__.py" = [ + "D104", # Missing docstring in public package +] diff --git a/scripts/README.md b/scripts/README.md deleted file mode 100644 index 45b9c3d..0000000 --- a/scripts/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Scripts - -Scripts are a collection of code snippets or even fully functional code modules. They have been usefull in the past or are still in use for various local tasks. - -# Currently available -- transform_oem141_oem151.py - A pure python based script to transform oemetadata version 1.4 JSON strings to the newer oemetadata version 1.5.1. \ No newline at end of file diff --git a/scripts/transform_oem141_oem151.py b/scripts/transform_oem141_oem151.py deleted file mode 100644 index 0eb7c77..0000000 --- a/scripts/transform_oem141_oem151.py +++ /dev/null @@ -1,360 +0,0 @@ -import os -import json -from copy import deepcopy - - -""" -This script transforms OEMetadata v1.4.1 (oem141) into OEMetadata v.1.5.1 (oem151). -It does so by backfilling the key-values from oem141 files into an empty oem151 template.json. -Default keys and values from oem151 are provided, if keys are not used or values are not filled in oem141. -The method applies for all key-values, except for the ‘foreignKeys‘ key, which is a direct copy of the list in oem141 -and the '_comment' and 'metaMetadata' key, which are not processed, as new oem151 information is provided - -Files are read from ./JSON/v141 -Files are saved to ./JSON/v151 - -""" - -# create directories or pass if exist -oem_versions = ["v141", "v151"] -for oem in oem_versions: - try: - os.makedirs(f"./JSON/{oem}") - except FileExistsError: - print(f"The directory: ./JSON/{oem} exists already") - pass - -# load oem141 file paths -json_path = "./JSON/v141" -json_files = os.listdir(json_path) -all_json_files_paths = [json_path + "/" + json_file for json_file in json_files] - -# oem151 template -oem151 = { - "name": None, - "title": None, - "id": None, - "description": None, - "language": [None], - "subject": [{"name": None, "path": None}], - "keywords": [None], - "publicationDate": None, - "context": { - "homepage": None, - "documentation": None, - "sourceCode": None, - "contact": None, - "grantNo": None, - "fundingAgency": None, - "fundingAgencyLogo": None, - "publisherLogo": None, - }, - "spatial": {"location": None, "extent": None, "resolution": None}, - "temporal": { - "referenceDate": None, - "timeseries": [ - { - "start": None, - "end": None, - "resolution": None, - "alignment": None, - "aggregationType": None, - }, - { - "start": None, - "end": None, - "resolution": None, - "alignment": None, - "aggregationType": None, - }, - ], - }, - "sources": [ - { - "title": None, - "description": None, - "path": None, - "licenses": [ - { - "name": None, - "title": None, - "path": None, - "instruction": None, - "attribution": None, - } - ], - }, - { - "title": None, - "description": None, - "path": None, - "licenses": [ - { - "name": None, - "title": None, - "path": None, - "instruction": None, - "attribution": None, - } - ], - }, - ], - "licenses": [ - { - "name": None, - "title": None, - "path": None, - "instruction": None, - "attribution": None, - } - ], - "contributors": [ - {"title": None, "email": None, "date": None, "object": None, "comment": None} - ], - "resources": [ - { - "profile": None, - "name": None, - "path": None, - "format": None, - "encoding": None, - "schema": { - "fields": [ - { - "name": None, - "description": None, - "type": None, - "unit": None, - "isAbout": [{"name": None, "path": None}], - "valueReference": [{"value": None, "name": None, "path": None}], - }, - { - "name": None, - "description": None, - "type": None, - "unit": None, - "isAbout": [{"name": None, "path": None}], - "valueReference": [{"value": None, "name": None, "path": None}], - }, - ], - "primaryKey": [None], - "foreignKeys": [ - { - "fields": [None], - "reference": {"resource": None, "fields": [None]}, - } - ], - }, - "dialect": {"delimiter": None, "decimalSeparator": "."}, - } - ], - "@id": None, - "@context": None, - "review": {"path": None, "badge": None}, - "metaMetadata": { - "metadataVersion": "OEP-1.5.0", - "metadataLicense": { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/", - }, - }, - "_comment": { - "metadata": "Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/oemetadata)", - "dates": "Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - "units": "Use a space between numbers and units (100 m)", - "languages": "Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - "licenses": "License name must follow the SPDX License List (https://spdx.org/licenses/)", - "review": "Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/blob/master/data-review/manual/review_manual.md)", - "null": "If not applicable use: null", - "todo": "If a value is not yet available, use: todo", - }, -} - -# create oem template with empty lists in keys: sources, temporal, licenses, contributers, resources -oem151_empty_lists = deepcopy(oem151) -keys_to_empty = ["sources", "temporal", "licenses", "contributors", "resources"] -for keys in keys_to_empty: - oem151_empty_lists[keys] = [] - -# make copy of empty oem151 template -v151_temp_backfill_clean = deepcopy(oem151_empty_lists) - -# prepare oem151 keys and dicts for later reference during backfill - -context_keys = list(oem151["context"].keys()) -spatial_keys = list(oem151["spatial"].keys()) -review_keys = list(oem151["review"].keys()) - -contributer_dict = deepcopy(oem151["contributors"][0]) - -licenses_keys = list(oem151["licenses"][0].keys()) -licenses_dict = deepcopy(oem151["licenses"][0]) - -temporal_dict = deepcopy(oem151["temporal"]) -temporal_dict["timeseries"] = [temporal_dict["timeseries"][0]] -temporal_keys = list(oem151["temporal"].keys()) -ts_keys = list(oem151["temporal"]["timeseries"][0].keys()) - -sources_dict = deepcopy(oem151["sources"][0]) -sources_licenses_keys = list(oem151["sources"][0]["licenses"][0]) -sources_licenses_dict = deepcopy(oem151["sources"][0]["licenses"][0]) - -resources_dict = deepcopy(oem151["resources"][0]) -resources_dict["schema"]["fields"] = [] -resources_schema_keys = list(oem151["resources"][0]["schema"]) -resources_dialect_dict = deepcopy(oem151["resources"][0]["dialect"]) -resources_schema_fields = deepcopy(oem151["resources"][0]["schema"]["fields"][0]) - -# backfill oem141 to oem151 for all json_files in ./JSON/v141 -for json_file in all_json_files_paths: - - # save filename for output - filename = json_file.split("/")[-1].split(".")[0] - - # open oem141 files - with open(json_file, encoding="utf-8") as json_file: - v141_file = json.load(json_file) - - # create a clean and empty 'v151_temp_backfill' for each processed oem141 JSON - v151_temp_backfill = deepcopy(v151_temp_backfill_clean) - - # start backfill - # Note: '_comment' and 'metaMetadata' are not processed, as new oem151 information is provided. - # backfill key-values on 1st level. - first_level_keys = [ - "name", - "title", - "id", - "description", - "language", - "keywords", - "publicationDate", - ] - - for key in first_level_keys: - if key in v141_file and v141_file[key] != "": - v151_temp_backfill[key] = v141_file[key] - else: - print( - f"The key:[{key}] is not present in oemetadata v141, despite being declared in the OEM v141 template " - ) - - # backfill review keys - for key in review_keys: - if key in v141_file["review"].keys() and v141_file["review"][key] != "": - v151_temp_backfill["review"][key] = v141_file["review"][key] - - # backfill context keys - for key in context_keys: - if key in v141_file["context"].keys() and v141_file["context"][key] != "": - v151_temp_backfill["context"][key] = v141_file["context"][key] - - # backfill spatial keys - for key in spatial_keys: - if key in v141_file["spatial"].keys() and v141_file["spatial"][key] != "": - v151_temp_backfill["spatial"][key] = v141_file["spatial"][key] - - # backfill contributors - for index, dict in enumerate(v141_file["contributors"]): - # add own contributer_dict for each contributer - v151_temp_backfill["contributors"].append(deepcopy(contributer_dict)) - for key, value in dict.items(): - if v141_file["contributors"][index][key] != "": - v151_temp_backfill["contributors"][index][key] = value - - # backfill licenses - for index, dict in enumerate(v141_file["licenses"]): - # add own licenses_dict for each licenses - v151_temp_backfill["licenses"].append(deepcopy(licenses_dict)) - for key, value in dict.items(): - if v141_file["licenses"][index][key] != "": - v151_temp_backfill["licenses"][index][key] = value - - # backfill temporal - # Note: in oem141 only 1 temporal_dict should exist, as the key 'temporal' is just dict and not list, as in oem151. - # add own temporal_dict for each temporal. - v151_temp_backfill["temporal"] = temporal_dict - - for key in temporal_keys: - if key == "timeseries": - for timeseries_key in ts_keys: - if v141_file["temporal"][key] is not None and timeseries_key in list( - v141_file["temporal"]["timeseries"].keys() - ): - v151_temp_backfill["temporal"][key][0][timeseries_key] = v141_file[ - "temporal" - ][key][timeseries_key] - else: - print(f"{timeseries_key} is not used and filled in oem141") - - elif key in v141_file["temporal"].keys(): - if v141_file["temporal"][key] != "": - v151_temp_backfill["temporal"][key] = v141_file["temporal"][key] - - # backfill sources - for index, dict in enumerate(v141_file["sources"]): - # add own sources_dict for each source - v151_temp_backfill["sources"].append(deepcopy(sources_dict)) - for key, value in dict.items(): - if key == "licenses" and v141_file["sources"][index]["licenses"]: - for src_lc_key in sources_licenses_keys: - if ( - src_lc_key in list(v141_file["sources"][index]["licenses"][0]) - and v141_file["sources"][index]["licenses"][0][src_lc_key] != "" - ): - v151_temp_backfill["sources"][index][key][0][ - src_lc_key - ] = value[0][src_lc_key] - - elif key == "licenses" and not v141_file["sources"][index]["licenses"]: - v151_temp_backfill["sources"][index][key][0] = sources_licenses_dict - - elif v141_file["sources"][index][key] != "": - v151_temp_backfill["sources"][index][key] = value - - # backfill resources - for index, dict in enumerate(v141_file["resources"]): - # add own resources_dict for each resource - v151_temp_backfill["resources"].append(deepcopy(resources_dict)) - for key, value in dict.items(): - if key == "schema": - if "primaryKey" in value: - v151_temp_backfill["resources"][index][key][ - "primaryKey" - ] = v141_file["resources"][index][key]["primaryKey"] - if "foreignKeys" in value: - v151_temp_backfill["resources"][index][key][ - "foreignKeys" - ] = v141_file["resources"][index][key]["foreignKeys"] - - if "fields" in value: - for index_fields, dict_fields in enumerate( - v141_file["resources"][index]["schema"]["fields"] - ): - v151_temp_backfill["resources"][index]["schema"][ - "fields" - ].append(deepcopy(resources_schema_fields)) - for key_fields, value_fields in dict_fields.items(): - v151_temp_backfill["resources"][index]["schema"]["fields"][ - index_fields - ][key_fields] = value_fields - - elif key == "dialect": - if "delimiter" in value: - v151_temp_backfill["resources"][index][key]["delimiter"] = value[ - "delimiter" - ] - elif "decimalSeparator" in value: - v151_temp_backfill["resources"][index][key][ - "decimalSeparator" - ] = value["decimalSeparator"] - - elif v141_file["resources"][index][key] != "": - v151_temp_backfill["resources"][index][key] = value - - # save backfilled oem151 template to json in ./JSON/v151 - with open( - f"./JSON/v151/{filename}.metadata_oem151.json", "w", encoding="utf-8" - ) as outfile: - json.dump(v151_temp_backfill, outfile, indent=4, ensure_ascii=False) diff --git a/setup.cfg b/setup.cfg index 935dd3a..15556f8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,9 @@ +[bumpversion] +current_version = 1.0.0 + [bdist_wheel] universal = 1 - [flake8] max-line-length = 140 exclude = */migrations/* @@ -9,18 +11,17 @@ exclude = */migrations/* [tool:pytest] testpaths = tests norecursedirs = - migrations - + migrations python_files = - test_*.py - *_test.py - tests.py + test_*.py + *_test.py + tests.py addopts = - -ra - --strict - --doctest-modules - --doctest-glob=\*.rst - --tb=short + -ra + --strict + --doctest-modules + --doctest-glob=\*.rst + --tb=short [isort] force_single_line = True diff --git a/setup.py b/setup.py deleted file mode 100644 index bd60dd0..0000000 --- a/setup.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- -from __future__ import absolute_import -from __future__ import print_function - -import io -import re -from glob import glob -from os.path import basename -from os.path import dirname -from os.path import join -from os.path import splitext - -from setuptools import find_packages -from setuptools import setup - - -def read(*names, **kwargs): - with io.open( - join(dirname(__file__), *names), encoding=kwargs.get("encoding", "utf8") - ) as fh: - return fh.read() - - -setup( - name="omi", - version="0.2.1", - license="AGPL-3.0", - description="A library to process and translate open energy metadata.", - long_description="%s\n%s" - % ( - re.compile("^.. start-badges.*^.. end-badges", re.M | re.S).sub( - "", read("README.rst") - ), - re.sub(":[a-z]+:`~?(.*?)`", r"``\1``", read("CHANGELOG.rst")), - ), - author="Martin Glauer", - author_email="martinglauer89@gmail.com", - url="https://github.com/OpenEnergyPlatform/omi", - packages=find_packages("src"), - package_dir={"": "src"}, - py_modules=[splitext(basename(path))[0] for path in glob("src/*.py")], - include_package_data=True, - zip_safe=False, - classifiers=[ - # complete classifier list: http://pypi.python.org/pypi?%3Aaction=list_classifiers - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: GNU Affero General Public License v3", - "Operating System :: Unix", - "Operating System :: POSIX", - "Operating System :: Microsoft :: Windows", - "Programming Language :: Python", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - # uncomment if you test on these interpreters: - # 'Programming Language :: Python :: Implementation :: IronPython', - # 'Programming Language :: Python :: Implementation :: Jython', - # 'Programming Language :: Python :: Implementation :: Stackless', - "Topic :: Utilities", - ], - project_urls={ - "Documentation": "https://omi.readthedocs.io/", - "Changelog": "https://omi.readthedocs.io/en/latest/changelog.html", - "Issue Tracker": "https://github.com/MGlauer/omi/issues", - }, - keywords=[ - # eg: 'keyword1', 'keyword2', 'keyword3', - ], - python_requires=">=3.5", - install_requires=["click", "rdfLib", "python-dateutil", "jsonschema", "oemetadata>=1.5.2"], - tests_require=["tox", "pytest"], - extras_require={ - "dev": ["black", "isort", "pre-commit"] - # eg: - # 'rst': ['docutils>=0.11'], - # ':python_version=="2.6"': ['argparse'], - }, - entry_points={"console_scripts": ["omi = omi.cli:main"]}, -) diff --git a/src/omi/__init__.py b/src/omi/__init__.py index 3ced358..5becc17 100644 --- a/src/omi/__init__.py +++ b/src/omi/__init__.py @@ -1 +1 @@ -__version__ = "0.2.1" +__version__ = "1.0.0" diff --git a/src/omi/__main__.py b/src/omi/__main__.py index 8343d09..de20537 100644 --- a/src/omi/__main__.py +++ b/src/omi/__main__.py @@ -1,7 +1,6 @@ """ Entrypoint module, in case you use `python -momi`. - Why does this file exist, and why __main__? For more info, read: - https://www.python.org/dev/peps/pep-0338/ diff --git a/src/omi/base.py b/src/omi/base.py new file mode 100644 index 0000000..7804a80 --- /dev/null +++ b/src/omi/base.py @@ -0,0 +1,161 @@ +"""Base functionality for OMI.""" + +from __future__ import annotations + +import json +import pathlib +from dataclasses import dataclass + +import requests +from metadata import v20, v152, v160 + +from .settings import OEP_URL + +# Order matters! First entry equals latest version of metadata format +METADATA_FORMATS = {"OEP": ["OEMetadata-2.0.1", "OEP-1.6.0", "OEP-1.5.2"], "INSPIRE": []} +METADATA_VERSIONS = {version: md_format for md_format, versions in METADATA_FORMATS.items() for version in versions} + + +class MetadataError(Exception): + """Raised when a metadata error is encountered.""" + + +@dataclass +class MetadataSpecification: + """Metadata schema class, holding JSON schema and (optional) template and example for given schema.""" + + schema: dict + template: dict | None = None + example: dict | None = None + + +def get_metadata_from_oep_table(oep_table: str, oep_schema: str = "model_draft") -> dict: + """ + Get metadata from OEP table. + + Parameters + ---------- + oep_table: str + OEP table name + oep_schema: str + OEP schema name + + Returns + ------- + dict + Metadata in OEMetadata format + """ + response = requests.get(f"{OEP_URL}/api/v0/schema/{oep_schema}/tables/{oep_table}/meta/", timeout=90) + if response.status_code != requests.codes.ok: + raise MetadataError(f"Could not retrieve metadata from OEP table '{oep_schema}.{oep_table}'.") + metadata = response.json() + if not metadata: + raise MetadataError(f"Metadata from '{oep_schema}.{oep_table}' is empty.") + return metadata + + +def get_metadata_version(metadata: dict) -> str: + """ + Extract metadata version from metadata. + + Parameters + ---------- + metadata: dict + Metadata + + Returns + ------- + str + Metadata version as string + """ + # For OEP metadata + try: + return metadata["metaMetadata"]["metadataVersion"] + except KeyError: + pass + msg = "Could not extract metadata version from metadata." + raise MetadataError(msg) + + +def get_latest_metadata_version(metadata_format: str) -> str: + """ + Return the latest metadata version of a given metadata format. + + Parameters + ---------- + metadata_format: str + Metadata format to check for latest version + + Raises + ------ + MetadataError + if metadata format is unknown or has no latest version + + Returns + ------- + str + Latest version of metadata format + """ + if metadata_format not in METADATA_FORMATS: + raise MetadataError( + f"Unknown metadata format: {metadata_format}. Possible candidates are: {','.join(METADATA_FORMATS)}.", + ) + if len(METADATA_FORMATS[metadata_format]) == 0: + raise MetadataError(f"No latest metadata version found for format {metadata_format}.") + return METADATA_FORMATS[metadata_format][0] + + +def get_metadata_specification(metadata_version: str) -> MetadataSpecification: + """ + Return metadata specification for given metadata version. + + Metadata versions are defined in METADATA_FORMATS. + Fetching metadata specification depends on metadata format. + + Parameters + ---------- + metadata_version: str + Metadata version + + Raises + ------ + ValueError + if metadata version is not in METADATA_FORMATS + + Returns + ------- + MetadataSpecification + Metadata specification holding (at least) JSON schema for given metadata version. + """ + if metadata_version not in METADATA_VERSIONS: + raise MetadataError(f"Metadata format for metadata version {metadata_version} could not be found.") + metadata_format = METADATA_VERSIONS[metadata_version] + + return METADATA_SPECIFICATIONS[metadata_format](metadata_version) + + +def __get_metadata_specs_for_oep(metadata_version: str) -> MetadataSpecification: + """ + Return OEP metadata schema for given metadata version. + + Parameters + ---------- + metadata_version: str + Metadata version + + Returns + ------- + MetadataSpecification + Metadata schema for given metadata version including template and example. + """ + metadata_modules = {"OEP-1.5.2": v152, "OEP-1.6.0": v160, "OEMetadata-2.0.1": v20} + metadata_module = metadata_modules[metadata_version] + module_path = pathlib.Path(metadata_module.__file__).parent + specs = {} + for item in ("schema", "template", "example"): + with (module_path / f"{item}.json").open("r") as f: + specs[item] = json.loads(f.read()) + return MetadataSpecification(**specs) + + +METADATA_SPECIFICATIONS = {"OEP": __get_metadata_specs_for_oep} diff --git a/src/omi/cli.py b/src/omi/cli.py index 024d35e..6b4d0aa 100644 --- a/src/omi/cli.py +++ b/src/omi/cli.py @@ -6,7 +6,7 @@ You might be tempted to import things from __main__ later, but that will cause problems: the code will get executed twice: - - When you run `python -momi` python will execute + - When you run `python -m omi` python will execute ``__main__.py`` as a script. That means there won't be any ``omi.__main__`` in ``sys.modules``. - When you import __main__ it will get executed again (as a module) because @@ -14,55 +14,18 @@ Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration """ -import click -from omi.dialects import get_dialect -from omi.dialects.oep import conversion +import click @click.group() -def grp(): - pass - - -@grp.command("translate") -@click.option("-f", help="Dialect identifier of the input") -@click.option("-t", default="oep-v1.5", help="Dialect identifier to translate to") -@click.option("-o", default=None, help="Output file") -@click.option("-omit_nones", default=True, help="Use to either keep or omit all null / none values from the json.") -@click.argument("file_path") -def translate(f, t, o, omit_nones, file_path): - with open(file_path, "r", encoding="utf-8") as infile: - from_dialect = get_dialect(f)() - obj = from_dialect.parse(infile.read()) - to_dialect = get_dialect(t)() - to_dialect._compiler.OMIT_NONE_FIELDS = omit_nones - s = to_dialect.compile_and_render(obj) - if o: - with open(o, "w", encoding="utf-8") as outfile: - outfile.write(s) - else: - print(s) - - -@grp.command("convert") -@click.option( - "-i", - default=None, - help="Input file. Must be a JSON conforming to the oemetadata v1.4 spec.", -) -@click.option( - "-o", - default=None, - help="Output file. Will be a a JSON conforming to the oemetadata v1.5 spec.", -) -def convert(o, i): - conversion.run_conversion(o, i) - print(f"Created updated metadata file: {o}") +def grp() -> None: + """Init click group.""" cli = click.CommandCollection(sources=[grp]) -def main(): +def main() -> None: + """Start click application.""" cli() diff --git a/src/omi/conversion.py b/src/omi/conversion.py new file mode 100644 index 0000000..d7e5b71 --- /dev/null +++ b/src/omi/conversion.py @@ -0,0 +1,257 @@ +"""Conversion module for OMI to update metadata to different versions.""" + +from __future__ import annotations + +from copy import deepcopy + +from omi.base import get_metadata_specification, get_metadata_version + + +class ConversionError(Exception): + """Raised when a conversion fails.""" + + +def convert_metadata(metadata: dict, target_version: str) -> dict: + """ + Convert metadata to target version. + + Parameters + ---------- + metadata: dict + Metadata dictionary + target_version: str + Target version to convert + + Returns + ------- + dict + Updated metadata + """ + metadata_version = get_metadata_version(metadata) + conversion_chain = __get_conversion_chain(metadata_version, target_version) + converted_metadata = deepcopy(metadata) + for next_version in conversion_chain[1:]: + current_version = get_metadata_version(converted_metadata) + converted_metadata = METADATA_CONVERSIONS[(current_version, next_version)](converted_metadata) + return converted_metadata + + +def __get_conversion_chain(source_version: str, target_version: str) -> list[str]: + """ + Try to find conversion chain from source version to target version. + + Parameters + ---------- + source_version: str + Starting version + target_version: str + Version goal + + Raises + ------ + ConversionError + if no conversion chain is found + + Returns + ------- + list[str] + List of conversion chain from source version to target version + """ + + def get_chain(current_version: str) -> list[str] | None: + for source, target in METADATA_CONVERSIONS: + if source != current_version: + continue + if target == target_version: + # Solution found! Return last conversion tuple + return [current_version, target_version] + child_chain = get_chain(target) + if child_chain is None: + continue + return [current_version, *child_chain] + return None + + conversion_chain = get_chain(source_version) + if conversion_chain: + return conversion_chain + raise ConversionError(f"No conversion chain found from {source_version} to {target_version}.") + + +def __convert_oep_152_to_160(metadata: dict) -> dict: + """ + Convert metadata with version "OEP-1.5.2" to "OEP-1.6.0". + + Parameters + ---------- + metadata: dict + Metadata + + Returns + ------- + dict + Updated metadata + """ + # No changes in metadata fields + metadata["metaMetadata"]["metadataVersion"] = "OEP-1.6.0" + return metadata + + +def __convert_oep_160_to_200(metadata: dict) -> dict: + """ + Convert metadata with version "OEP-1.6.0" to "OEMetadata-2.0.1" using the v2.0 template. + + Parameters + ---------- + metadata: dict + Metadata dictionary in v1.6 format + + Returns + ------- + dict + Updated metadata dictionary in v2.0 format + """ + metadata_v2 = deepcopy(get_metadata_specification("OEMetadata-2.0.1").template) + metadata_v2["name"] = metadata_v2["title"] = metadata_v2["id"] = metadata_v2["description"] = None + + # Populate metadata v2 resources + for i, resource in enumerate(metadata.get("resources", [])): + resource_v2 = ___v2_ensure_resource_entry(metadata_v2, i) + ___v2_populate_resource_v2(resource_v2, metadata, resource) + + # Update metaMetadata section + metadata_v2["metaMetadata"]["metadataVersion"] = "OEMetadata-2.0.1" + metadata_v2["metaMetadata"]["metadataLicense"] = metadata.get("metaMetadata", {}).get("metadataLicense") + + return metadata_v2 + + +def ___v2_ensure_resource_entry(metadata_v2: dict, index: int) -> dict: + """Ensure a resource entry exists in metadata_v2 resources for the given index.""" + if index >= len(metadata_v2["resources"]): + metadata_v2["resources"].append(deepcopy(metadata_v2["resources"][0])) + return metadata_v2["resources"][index] + + +def ___v2_populate_resource_v2(resource_v2: dict, metadata: dict, resource: dict) -> None: + """Populate resource_v2 fields based on metadata and resource from v1.6.""" + # Bulk update keys without + resource_v2.update( + { + "@id": metadata.get("@id"), + "@context": metadata.get("@context"), + "name": resource.get("name").split(".")[1], + "topics": [resource.get("name", "").split(".")[0]], + "title": metadata.get("title"), + "path": metadata.get("id"), + "description": metadata.get("description"), + "languages": metadata.get("language", []), + "subject": metadata.get("subject", []), + "keywords": metadata.get("keywords", []), + "publicationDate": metadata.get("publicationDate"), + "context": metadata.get("context", {}), + "temporal": metadata.get("temporal", {}), + "type": None, + "format": resource.get("format"), + "encoding": resource.get("encoding"), + "schema": { + "fields": resource.get("schema", {}).get("fields", []), + "primaryKey": resource.get("schema", {}).get("primaryKey", []), + "foreignKeys": resource.get("schema", {}).get("foreignKeys", []), + }, + "dialect": resource.get("dialect", {}), + "review": metadata.get("review", {}), + }, + ) + + resource_v2["context"]["publisher"] = None + + resource_v2["embargoPeriod"]["start"] = None + resource_v2["embargoPeriod"]["end"] = None + + # Set to null to avoid validation errors: URI + resource_v2["spatial"]["location"]["@id"] = None + resource_v2["spatial"]["location"]["address"] = metadata.get("spatial", {}).get("location") + resource_v2["spatial"]["location"]["latitude"] = None + resource_v2["spatial"]["location"]["longitude"] = None + # Set to null to avoid validation errors: URI + resource_v2["spatial"]["extent"]["name"] = metadata.get("spatial", {}).get("extent") + resource_v2["spatial"]["extent"]["@id"] = None + resource_v2["spatial"]["extent"]["resolutionValue"], resource_v2["spatial"]["extent"]["resolutionUnit"] = ( + metadata.get("spatial", {}).get("resolution", "").split(" ", 1) + ) + resource_v2["spatial"]["extent"]["crs"] = None + + ___v2_populate_sources(resource_v2, metadata.get("sources", [])) + ___v2_populate_contributors(resource_v2, metadata.get("contributors", [])) + ___v2_populate_licenses(resource_v2, metadata.get("licenses", [])) + ___v2_populate_schema_fields(resource_v2, resource) + + +def ___v2_populate_sources(resource_v2: dict, sources: list) -> None: + """Populate sources in resource_v2 from sources in v1.6.""" + for i_source, source in enumerate(sources): + if i_source >= len(resource_v2["sources"]): + resource_v2["sources"].append(deepcopy(resource_v2["sources"][0])) + source_v2 = resource_v2["sources"][i_source] + source_v2.update( + { + "title": source.get("title"), + "description": source.get("description"), + "path": source.get("path"), + "publicationYear": None, + "authors": [], + }, + ) + ___v2_populate_source_licenses(source_v2, source.get("licenses", [])) + + +def ___v2_populate_source_licenses(source_v2: dict, licenses: list) -> None: + """Populate licenses in source_v2 from licenses in v1.6.""" + for i_license, license_entry in enumerate(licenses): + if i_license >= len(source_v2["licenses"]): + source_v2["licenses"].append(deepcopy(source_v2["licenses"][0])) + source_v2["licenses"][i_license].update(license_entry) + source_v2["licenses"][i_license]["copyrightStatement"] = None + + +def ___v2_populate_contributors(resource_v2: dict, contributors: list) -> None: + """Populate contributors in resource_v2 from contributors in v1.6.""" + for i_contribution, contributor in enumerate(contributors): + if i_contribution >= len(resource_v2["contributors"]): + resource_v2["contributors"].append(deepcopy(resource_v2["contributors"][0])) + contributor_v2 = resource_v2["contributors"][i_contribution] + contributor_v2.update( + { + "title": contributor.get("title"), + "path": contributor.get("path"), + "organization": contributor.get("organization"), + "date": contributor.get("date"), + "object": contributor.get("object"), + "comment": contributor.get("comment"), + }, + ) + + +def ___v2_populate_licenses(resource_v2: dict, licenses: list) -> None: + """Populate licenses in resource_v2 from licenses in v1.6.""" + for i_license, license_entry in enumerate(licenses): + if i_license >= len(resource_v2["licenses"]): + resource_v2["licenses"].append(deepcopy(resource_v2["licenses"][0])) + resource_v2["licenses"][i_license].update(license_entry) + resource_v2["licenses"][i_license]["copyrightStatement"] = None + + +def ___v2_populate_schema_fields(resource_v2: dict, resource: dict) -> None: + """Populate schema fields in resource_v2 from resource in v1.6.""" + for i_field, field in enumerate(resource.get("schema", {}).get("fields", [])): + if i_field >= len(resource_v2["schema"]["fields"]): + resource_v2["schema"]["fields"].append(deepcopy(resource_v2["schema"]["fields"][0])) + schema_field_v2 = resource_v2["schema"]["fields"][i_field] + schema_field_v2.update(field) + schema_field_v2["nullable"] = None + + +METADATA_CONVERSIONS = { + ("OEP-1.5.2", "OEP-1.6.0"): __convert_oep_152_to_160, + ("OEP-1.6.0", "OEMetadata-2.0.1"): __convert_oep_160_to_200, +} diff --git a/src/omi/data/README.md b/src/omi/data/README.md new file mode 100644 index 0000000..81a437a --- /dev/null +++ b/src/omi/data/README.md @@ -0,0 +1 @@ +License information was downloaded form . diff --git a/src/omi/data/licenses.json b/src/omi/data/licenses.json new file mode 100644 index 0000000..eef5f67 --- /dev/null +++ b/src/omi/data/licenses.json @@ -0,0 +1,8275 @@ +{ + "licenseListVersion": "3.24.0", + "licenses": [ + { + "reference": "https://spdx.org/licenses/0BSD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/0BSD.json", + "referenceNumber": 537, + "name": "BSD Zero Clause License", + "licenseId": "0BSD", + "seeAlso": [ + "http://landley.net/toybox/license.html", + "https://opensource.org/licenses/0BSD" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/3D-Slicer-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/3D-Slicer-1.0.json", + "referenceNumber": 200, + "name": "3D Slicer License v1.0", + "licenseId": "3D-Slicer-1.0", + "seeAlso": [ + "https://slicer.org/LICENSE", + "https://github.com/Slicer/Slicer/blob/main/License.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AAL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AAL.json", + "referenceNumber": 406, + "name": "Attribution Assurance License", + "licenseId": "AAL", + "seeAlso": [ + "https://opensource.org/licenses/attribution" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Abstyles.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Abstyles.json", + "referenceNumber": 526, + "name": "Abstyles License", + "licenseId": "Abstyles", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Abstyles" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AdaCore-doc.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AdaCore-doc.json", + "referenceNumber": 382, + "name": "AdaCore Doc License", + "licenseId": "AdaCore-doc", + "seeAlso": [ + "https://github.com/AdaCore/xmlada/blob/master/docs/index.rst", + "https://github.com/AdaCore/gnatcoll-core/blob/master/docs/index.rst", + "https://github.com/AdaCore/gnatcoll-db/blob/master/docs/index.rst" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Adobe-2006.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Adobe-2006.json", + "referenceNumber": 558, + "name": "Adobe Systems Incorporated Source Code License Agreement", + "licenseId": "Adobe-2006", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/AdobeLicense" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Adobe-Display-PostScript.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Adobe-Display-PostScript.json", + "referenceNumber": 431, + "name": "Adobe Display PostScript License", + "licenseId": "Adobe-Display-PostScript", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type\u003dheads#L752" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Adobe-Glyph.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Adobe-Glyph.json", + "referenceNumber": 297, + "name": "Adobe Glyph List License", + "licenseId": "Adobe-Glyph", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Adobe-Utopia.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Adobe-Utopia.json", + "referenceNumber": 532, + "name": "Adobe Utopia Font License", + "licenseId": "Adobe-Utopia", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/font/adobe-utopia-100dpi/-/blob/master/COPYING?ref_type\u003dheads" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ADSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ADSL.json", + "referenceNumber": 463, + "name": "Amazon Digital Services License", + "licenseId": "ADSL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AFL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AFL-1.1.json", + "referenceNumber": 601, + "name": "Academic Free License v1.1", + "licenseId": "AFL-1.1", + "seeAlso": [ + "http://opensource.linux-mirror.org/licenses/afl-1.1.txt", + "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AFL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AFL-1.2.json", + "referenceNumber": 72, + "name": "Academic Free License v1.2", + "licenseId": "AFL-1.2", + "seeAlso": [ + "http://opensource.linux-mirror.org/licenses/afl-1.2.txt", + "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AFL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AFL-2.0.json", + "referenceNumber": 187, + "name": "Academic Free License v2.0", + "licenseId": "AFL-2.0", + "seeAlso": [ + "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AFL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AFL-2.1.json", + "referenceNumber": 383, + "name": "Academic Free License v2.1", + "licenseId": "AFL-2.1", + "seeAlso": [ + "http://opensource.linux-mirror.org/licenses/afl-2.1.txt" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AFL-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AFL-3.0.json", + "referenceNumber": 369, + "name": "Academic Free License v3.0", + "licenseId": "AFL-3.0", + "seeAlso": [ + "http://www.rosenlaw.com/AFL3.0.htm", + "https://opensource.org/licenses/afl-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Afmparse.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Afmparse.json", + "referenceNumber": 345, + "name": "Afmparse License", + "licenseId": "Afmparse", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Afmparse" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AGPL-1.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/AGPL-1.0.json", + "referenceNumber": 221, + "name": "Affero General Public License v1.0", + "licenseId": "AGPL-1.0", + "seeAlso": [ + "http://www.affero.org/oagpl.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AGPL-1.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AGPL-1.0-only.json", + "referenceNumber": 334, + "name": "Affero General Public License v1.0 only", + "licenseId": "AGPL-1.0-only", + "seeAlso": [ + "http://www.affero.org/oagpl.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AGPL-1.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AGPL-1.0-or-later.json", + "referenceNumber": 527, + "name": "Affero General Public License v1.0 or later", + "licenseId": "AGPL-1.0-or-later", + "seeAlso": [ + "http://www.affero.org/oagpl.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AGPL-3.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/AGPL-3.0.json", + "referenceNumber": 394, + "name": "GNU Affero General Public License v3.0", + "licenseId": "AGPL-3.0", + "seeAlso": [ + "https://www.gnu.org/licenses/agpl.txt", + "https://opensource.org/licenses/AGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AGPL-3.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AGPL-3.0-only.json", + "referenceNumber": 123, + "name": "GNU Affero General Public License v3.0 only", + "licenseId": "AGPL-3.0-only", + "seeAlso": [ + "https://www.gnu.org/licenses/agpl.txt", + "https://opensource.org/licenses/AGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AGPL-3.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AGPL-3.0-or-later.json", + "referenceNumber": 105, + "name": "GNU Affero General Public License v3.0 or later", + "licenseId": "AGPL-3.0-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/agpl.txt", + "https://opensource.org/licenses/AGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Aladdin.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Aladdin.json", + "referenceNumber": 168, + "name": "Aladdin Free Public License", + "licenseId": "Aladdin", + "seeAlso": [ + "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/AMD-newlib.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AMD-newlib.json", + "referenceNumber": 222, + "name": "AMD newlib License", + "licenseId": "AMD-newlib", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/sys/a29khif/_close.S;h\u003d04f52ae00de1dafbd9055ad8d73c5c697a3aae7f;hb\u003dHEAD" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AMDPLPA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AMDPLPA.json", + "referenceNumber": 149, + "name": "AMD\u0027s plpa_map.c License", + "licenseId": "AMDPLPA", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AML.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AML.json", + "referenceNumber": 13, + "name": "Apple MIT License", + "licenseId": "AML", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AML-glslang.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AML-glslang.json", + "referenceNumber": 1, + "name": "AML glslang variant License", + "licenseId": "AML-glslang", + "seeAlso": [ + "https://github.com/KhronosGroup/glslang/blob/main/LICENSE.txt#L949", + "https://docs.omniverse.nvidia.com/install-guide/latest/common/licenses.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AMPAS.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AMPAS.json", + "referenceNumber": 420, + "name": "Academy of Motion Picture Arts and Sciences BSD", + "licenseId": "AMPAS", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ANTLR-PD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ANTLR-PD.json", + "referenceNumber": 576, + "name": "ANTLR Software Rights Notice", + "licenseId": "ANTLR-PD", + "seeAlso": [ + "http://www.antlr2.org/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ANTLR-PD-fallback.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ANTLR-PD-fallback.json", + "referenceNumber": 194, + "name": "ANTLR Software Rights Notice with license fallback", + "licenseId": "ANTLR-PD-fallback", + "seeAlso": [ + "http://www.antlr2.org/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/any-OSI.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/any-OSI.json", + "referenceNumber": 121, + "name": "Any OSI License", + "licenseId": "any-OSI", + "seeAlso": [ + "https://metacpan.org/pod/Exporter::Tidy#LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Apache-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Apache-1.0.json", + "referenceNumber": 616, + "name": "Apache License 1.0", + "licenseId": "Apache-1.0", + "seeAlso": [ + "http://www.apache.org/licenses/LICENSE-1.0" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Apache-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Apache-1.1.json", + "referenceNumber": 313, + "name": "Apache License 1.1", + "licenseId": "Apache-1.1", + "seeAlso": [ + "http://apache.org/licenses/LICENSE-1.1", + "https://opensource.org/licenses/Apache-1.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Apache-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Apache-2.0.json", + "referenceNumber": 564, + "name": "Apache License 2.0", + "licenseId": "Apache-2.0", + "seeAlso": [ + "https://www.apache.org/licenses/LICENSE-2.0", + "https://opensource.org/licenses/Apache-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/APAFML.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APAFML.json", + "referenceNumber": 136, + "name": "Adobe Postscript AFM License", + "licenseId": "APAFML", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/APL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APL-1.0.json", + "referenceNumber": 515, + "name": "Adaptive Public License 1.0", + "licenseId": "APL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/APL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/App-s2p.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/App-s2p.json", + "referenceNumber": 470, + "name": "App::s2p License", + "licenseId": "App-s2p", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/App-s2p" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/APSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APSL-1.0.json", + "referenceNumber": 39, + "name": "Apple Public Source License 1.0", + "licenseId": "APSL-1.0", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0" + ], + "isOsiApproved": true, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/APSL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APSL-1.1.json", + "referenceNumber": 582, + "name": "Apple Public Source License 1.1", + "licenseId": "APSL-1.1", + "seeAlso": [ + "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/APSL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APSL-1.2.json", + "referenceNumber": 628, + "name": "Apple Public Source License 1.2", + "licenseId": "APSL-1.2", + "seeAlso": [ + "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/APSL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APSL-2.0.json", + "referenceNumber": 144, + "name": "Apple Public Source License 2.0", + "licenseId": "APSL-2.0", + "seeAlso": [ + "http://www.opensource.apple.com/license/apsl/" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Arphic-1999.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Arphic-1999.json", + "referenceNumber": 131, + "name": "Arphic Public License", + "licenseId": "Arphic-1999", + "seeAlso": [ + "http://ftp.gnu.org/gnu/non-gnu/chinese-fonts-truetype/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Artistic-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Artistic-1.0.json", + "referenceNumber": 388, + "name": "Artistic License 1.0", + "licenseId": "Artistic-1.0", + "seeAlso": [ + "https://opensource.org/licenses/Artistic-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/Artistic-1.0-cl8.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Artistic-1.0-cl8.json", + "referenceNumber": 321, + "name": "Artistic License 1.0 w/clause 8", + "licenseId": "Artistic-1.0-cl8", + "seeAlso": [ + "https://opensource.org/licenses/Artistic-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Artistic-1.0-Perl.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Artistic-1.0-Perl.json", + "referenceNumber": 652, + "name": "Artistic License 1.0 (Perl)", + "licenseId": "Artistic-1.0-Perl", + "seeAlso": [ + "http://dev.perl.org/licenses/artistic.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Artistic-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Artistic-2.0.json", + "referenceNumber": 355, + "name": "Artistic License 2.0", + "licenseId": "Artistic-2.0", + "seeAlso": [ + "http://www.perlfoundation.org/artistic_license_2_0", + "https://www.perlfoundation.org/artistic-license-20.html", + "https://opensource.org/licenses/artistic-license-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/ASWF-Digital-Assets-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ASWF-Digital-Assets-1.0.json", + "referenceNumber": 330, + "name": "ASWF Digital Assets License version 1.0", + "licenseId": "ASWF-Digital-Assets-1.0", + "seeAlso": [ + "https://github.com/AcademySoftwareFoundation/foundation/blob/main/digital_assets/aswf_digital_assets_license_v1.0.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ASWF-Digital-Assets-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ASWF-Digital-Assets-1.1.json", + "referenceNumber": 447, + "name": "ASWF Digital Assets License 1.1", + "licenseId": "ASWF-Digital-Assets-1.1", + "seeAlso": [ + "https://github.com/AcademySoftwareFoundation/foundation/blob/main/digital_assets/aswf_digital_assets_license_v1.1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Baekmuk.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Baekmuk.json", + "referenceNumber": 436, + "name": "Baekmuk License", + "licenseId": "Baekmuk", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:Baekmuk?rd\u003dLicensing/Baekmuk" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Bahyph.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Bahyph.json", + "referenceNumber": 494, + "name": "Bahyph License", + "licenseId": "Bahyph", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Bahyph" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Barr.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Barr.json", + "referenceNumber": 48, + "name": "Barr License", + "licenseId": "Barr", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Barr" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/bcrypt-Solar-Designer.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/bcrypt-Solar-Designer.json", + "referenceNumber": 27, + "name": "bcrypt Solar Designer License", + "licenseId": "bcrypt-Solar-Designer", + "seeAlso": [ + "https://github.com/bcrypt-ruby/bcrypt-ruby/blob/master/ext/mri/crypt_blowfish.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Beerware.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Beerware.json", + "referenceNumber": 143, + "name": "Beerware License", + "licenseId": "Beerware", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Beerware", + "https://people.freebsd.org/~phk/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Bitstream-Charter.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Bitstream-Charter.json", + "referenceNumber": 560, + "name": "Bitstream Charter Font License", + "licenseId": "Bitstream-Charter", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Charter#License_Text", + "https://raw.githubusercontent.com/blackhole89/notekit/master/data/fonts/Charter%20license.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Bitstream-Vera.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Bitstream-Vera.json", + "referenceNumber": 581, + "name": "Bitstream Vera Font License", + "licenseId": "Bitstream-Vera", + "seeAlso": [ + "https://web.archive.org/web/20080207013128/http://www.gnome.org/fonts/", + "https://docubrain.com/sites/default/files/licenses/bitstream-vera.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BitTorrent-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BitTorrent-1.0.json", + "referenceNumber": 373, + "name": "BitTorrent Open Source License v1.0", + "licenseId": "BitTorrent-1.0", + "seeAlso": [ + "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BitTorrent-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BitTorrent-1.1.json", + "referenceNumber": 288, + "name": "BitTorrent Open Source License v1.1", + "licenseId": "BitTorrent-1.1", + "seeAlso": [ + "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/blessing.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/blessing.json", + "referenceNumber": 469, + "name": "SQLite Blessing", + "licenseId": "blessing", + "seeAlso": [ + "https://www.sqlite.org/src/artifact/e33a4df7e32d742a?ln\u003d4-9", + "https://sqlite.org/src/artifact/df5091916dbb40e6" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BlueOak-1.0.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BlueOak-1.0.0.json", + "referenceNumber": 60, + "name": "Blue Oak Model License 1.0.0", + "licenseId": "BlueOak-1.0.0", + "seeAlso": [ + "https://blueoakcouncil.org/license/1.0.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Boehm-GC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Boehm-GC.json", + "referenceNumber": 322, + "name": "Boehm-Demers-Weiser GC License", + "licenseId": "Boehm-GC", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:MIT#Another_Minimal_variant_(found_in_libatomic_ops)", + "https://github.com/uim/libgcroots/blob/master/COPYING", + "https://github.com/ivmai/libatomic_ops/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Borceux.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Borceux.json", + "referenceNumber": 552, + "name": "Borceux license", + "licenseId": "Borceux", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Borceux" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Brian-Gladman-2-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Brian-Gladman-2-Clause.json", + "referenceNumber": 457, + "name": "Brian Gladman 2-Clause License", + "licenseId": "Brian-Gladman-2-Clause", + "seeAlso": [ + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L140-L156", + "https://web.mit.edu/kerberos/krb5-1.21/doc/mitK5license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Brian-Gladman-3-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Brian-Gladman-3-Clause.json", + "referenceNumber": 409, + "name": "Brian Gladman 3-Clause License", + "licenseId": "Brian-Gladman-3-Clause", + "seeAlso": [ + "https://github.com/SWI-Prolog/packages-clib/blob/master/sha1/brg_endian.h" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-1-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-1-Clause.json", + "referenceNumber": 567, + "name": "BSD 1-Clause License", + "licenseId": "BSD-1-Clause", + "seeAlso": [ + "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause.json", + "referenceNumber": 264, + "name": "BSD 2-Clause \"Simplified\" License", + "licenseId": "BSD-2-Clause", + "seeAlso": [ + "https://opensource.org/licenses/BSD-2-Clause" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause-Darwin.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-Darwin.json", + "referenceNumber": 231, + "name": "BSD 2-Clause - Ian Darwin variant", + "licenseId": "BSD-2-Clause-Darwin", + "seeAlso": [ + "https://github.com/file/file/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause-first-lines.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-first-lines.json", + "referenceNumber": 245, + "name": "BSD 2-Clause - first lines requirement", + "licenseId": "BSD-2-Clause-first-lines", + "seeAlso": [ + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L664-L690", + "https://web.mit.edu/kerberos/krb5-1.21/doc/mitK5license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.json", + "referenceNumber": 192, + "name": "BSD 2-Clause FreeBSD License", + "licenseId": "BSD-2-Clause-FreeBSD", + "seeAlso": [ + "http://www.freebsd.org/copyright/freebsd-license.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-NetBSD.json", + "referenceNumber": 449, + "name": "BSD 2-Clause NetBSD License", + "licenseId": "BSD-2-Clause-NetBSD", + "seeAlso": [ + "http://www.netbsd.org/about/redistribution.html#default" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause-Patent.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-Patent.json", + "referenceNumber": 612, + "name": "BSD-2-Clause Plus Patent License", + "licenseId": "BSD-2-Clause-Patent", + "seeAlso": [ + "https://opensource.org/licenses/BSDplusPatent" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause-Views.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-Views.json", + "referenceNumber": 657, + "name": "BSD 2-Clause with views sentence", + "licenseId": "BSD-2-Clause-Views", + "seeAlso": [ + "http://www.freebsd.org/copyright/freebsd-license.html", + "https://people.freebsd.org/~ivoras/wine/patch-wine-nvidia.sh", + "https://github.com/protegeproject/protege/blob/master/license.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause.json", + "referenceNumber": 216, + "name": "BSD 3-Clause \"New\" or \"Revised\" License", + "licenseId": "BSD-3-Clause", + "seeAlso": [ + "https://opensource.org/licenses/BSD-3-Clause", + "https://www.eclipse.org/org/documents/edl-v10.php" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-acpica.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-acpica.json", + "referenceNumber": 408, + "name": "BSD 3-Clause acpica variant", + "licenseId": "BSD-3-Clause-acpica", + "seeAlso": [ + "https://github.com/acpica/acpica/blob/master/source/common/acfileio.c#L119" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-Attribution.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Attribution.json", + "referenceNumber": 14, + "name": "BSD with attribution", + "licenseId": "BSD-3-Clause-Attribution", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-Clear.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Clear.json", + "referenceNumber": 347, + "name": "BSD 3-Clause Clear License", + "licenseId": "BSD-3-Clause-Clear", + "seeAlso": [ + "http://labs.metacarta.com/license-explanation.html#license" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-flex.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-flex.json", + "referenceNumber": 211, + "name": "BSD 3-Clause Flex variant", + "licenseId": "BSD-3-Clause-flex", + "seeAlso": [ + "https://github.com/westes/flex/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-HP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-HP.json", + "referenceNumber": 210, + "name": "Hewlett-Packard BSD variant license", + "licenseId": "BSD-3-Clause-HP", + "seeAlso": [ + "https://github.com/zdohnal/hplip/blob/master/COPYING#L939" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-LBNL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-LBNL.json", + "referenceNumber": 597, + "name": "Lawrence Berkeley National Labs BSD variant license", + "licenseId": "BSD-3-Clause-LBNL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/LBNLBSD" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-Modification.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Modification.json", + "referenceNumber": 364, + "name": "BSD 3-Clause Modification", + "licenseId": "BSD-3-Clause-Modification", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:BSD#Modification_Variant" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Military-License.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Military-License.json", + "referenceNumber": 30, + "name": "BSD 3-Clause No Military License", + "licenseId": "BSD-3-Clause-No-Military-License", + "seeAlso": [ + "https://gitlab.syncad.com/hive/dhive/-/blob/master/LICENSE", + "https://github.com/greymass/swift-eosio/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json", + "referenceNumber": 21, + "name": "BSD 3-Clause No Nuclear License", + "licenseId": "BSD-3-Clause-No-Nuclear-License", + "seeAlso": [ + "http://download.oracle.com/otn-pub/java/licenses/bsd.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json", + "referenceNumber": 543, + "name": "BSD 3-Clause No Nuclear License 2014", + "licenseId": "BSD-3-Clause-No-Nuclear-License-2014", + "seeAlso": [ + "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json", + "referenceNumber": 402, + "name": "BSD 3-Clause No Nuclear Warranty", + "licenseId": "BSD-3-Clause-No-Nuclear-Warranty", + "seeAlso": [ + "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.json", + "referenceNumber": 376, + "name": "BSD 3-Clause Open MPI variant", + "licenseId": "BSD-3-Clause-Open-MPI", + "seeAlso": [ + "https://www.open-mpi.org/community/license.php", + "http://www.netlib.org/lapack/LICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-Sun.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Sun.json", + "referenceNumber": 554, + "name": "BSD 3-Clause Sun Microsystems", + "licenseId": "BSD-3-Clause-Sun", + "seeAlso": [ + "https://github.com/xmlark/msv/blob/b9316e2f2270bc1606952ea4939ec87fbba157f3/xsdlib/src/main/java/com/sun/msv/datatype/regexp/InternalImpl.java" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-4-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause.json", + "referenceNumber": 650, + "name": "BSD 4-Clause \"Original\" or \"Old\" License", + "licenseId": "BSD-4-Clause", + "seeAlso": [ + "http://directory.fsf.org/wiki/License:BSD_4Clause" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-4-Clause-Shortened.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause-Shortened.json", + "referenceNumber": 252, + "name": "BSD 4 Clause Shortened", + "licenseId": "BSD-4-Clause-Shortened", + "seeAlso": [ + "https://metadata.ftp-master.debian.org/changelogs//main/a/arpwatch/arpwatch_2.1a15-7_copyright" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-4-Clause-UC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause-UC.json", + "referenceNumber": 117, + "name": "BSD-4-Clause (University of California-Specific)", + "licenseId": "BSD-4-Clause-UC", + "seeAlso": [ + "http://www.freebsd.org/copyright/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-4.3RENO.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-4.3RENO.json", + "referenceNumber": 298, + "name": "BSD 4.3 RENO License", + "licenseId": "BSD-4.3RENO", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dlibiberty/strcasecmp.c;h\u003d131d81c2ce7881fa48c363dc5bf5fb302c61ce0b;hb\u003dHEAD", + "https://git.openldap.org/openldap/openldap/-/blob/master/COPYRIGHT#L55-63" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-4.3TAHOE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-4.3TAHOE.json", + "referenceNumber": 0, + "name": "BSD 4.3 TAHOE License", + "licenseId": "BSD-4.3TAHOE", + "seeAlso": [ + "https://github.com/389ds/389-ds-base/blob/main/ldap/include/sysexits-compat.h#L15", + "https://git.savannah.gnu.org/cgit/indent.git/tree/doc/indent.texi?id\u003da74c6b4ee49397cf330b333da1042bffa60ed14f#n1788" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Advertising-Acknowledgement.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Advertising-Acknowledgement.json", + "referenceNumber": 423, + "name": "BSD Advertising Acknowledgement License", + "licenseId": "BSD-Advertising-Acknowledgement", + "seeAlso": [ + "https://github.com/python-excel/xlrd/blob/master/LICENSE#L33" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Attribution-HPND-disclaimer.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Attribution-HPND-disclaimer.json", + "referenceNumber": 171, + "name": "BSD with Attribution and HPND disclaimer", + "licenseId": "BSD-Attribution-HPND-disclaimer", + "seeAlso": [ + "https://github.com/cyrusimap/cyrus-sasl/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Inferno-Nettverk.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Inferno-Nettverk.json", + "referenceNumber": 401, + "name": "BSD-Inferno-Nettverk", + "licenseId": "BSD-Inferno-Nettverk", + "seeAlso": [ + "https://www.inet.no/dante/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Protection.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Protection.json", + "referenceNumber": 403, + "name": "BSD Protection License", + "licenseId": "BSD-Protection", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Source-beginning-file.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Source-beginning-file.json", + "referenceNumber": 97, + "name": "BSD Source Code Attribution - beginning of file variant", + "licenseId": "BSD-Source-beginning-file", + "seeAlso": [ + "https://github.com/lattera/freebsd/blob/master/sys/cam/cam.c#L4" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Source-Code.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Source-Code.json", + "referenceNumber": 22, + "name": "BSD Source Code Attribution", + "licenseId": "BSD-Source-Code", + "seeAlso": [ + "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Systemics.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Systemics.json", + "referenceNumber": 178, + "name": "Systemics BSD variant license", + "licenseId": "BSD-Systemics", + "seeAlso": [ + "https://metacpan.org/release/DPARIS/Crypt-DES-2.07/source/COPYRIGHT" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-Systemics-W3Works.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-Systemics-W3Works.json", + "referenceNumber": 350, + "name": "Systemics W3Works BSD variant license", + "licenseId": "BSD-Systemics-W3Works", + "seeAlso": [ + "https://metacpan.org/release/DPARIS/Crypt-Blowfish-2.14/source/COPYRIGHT#L7" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSL-1.0.json", + "referenceNumber": 514, + "name": "Boost Software License 1.0", + "licenseId": "BSL-1.0", + "seeAlso": [ + "http://www.boost.org/LICENSE_1_0.txt", + "https://opensource.org/licenses/BSL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BUSL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BUSL-1.1.json", + "referenceNumber": 549, + "name": "Business Source License 1.1", + "licenseId": "BUSL-1.1", + "seeAlso": [ + "https://mariadb.com/bsl11/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/bzip2-1.0.5.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/bzip2-1.0.5.json", + "referenceNumber": 419, + "name": "bzip2 and libbzip2 License v1.0.5", + "licenseId": "bzip2-1.0.5", + "seeAlso": [ + "https://sourceware.org/bzip2/1.0.5/bzip2-manual-1.0.5.html", + "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/bzip2-1.0.6.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/bzip2-1.0.6.json", + "referenceNumber": 396, + "name": "bzip2 and libbzip2 License v1.0.6", + "licenseId": "bzip2-1.0.6", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dbzip2.git;a\u003dblob;f\u003dLICENSE;hb\u003dbzip2-1.0.6", + "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html", + "https://sourceware.org/cgit/valgrind/tree/mpi/libmpiwrap.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/C-UDA-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/C-UDA-1.0.json", + "referenceNumber": 432, + "name": "Computational Use of Data Agreement v1.0", + "licenseId": "C-UDA-1.0", + "seeAlso": [ + "https://github.com/microsoft/Computational-Use-of-Data-Agreement/blob/master/C-UDA-1.0.md", + "https://cdla.dev/computational-use-of-data-agreement-v1-0/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CAL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CAL-1.0.json", + "referenceNumber": 653, + "name": "Cryptographic Autonomy License 1.0", + "licenseId": "CAL-1.0", + "seeAlso": [ + "http://cryptographicautonomylicense.com/license-text.html", + "https://opensource.org/licenses/CAL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.json", + "referenceNumber": 217, + "name": "Cryptographic Autonomy License 1.0 (Combined Work Exception)", + "licenseId": "CAL-1.0-Combined-Work-Exception", + "seeAlso": [ + "http://cryptographicautonomylicense.com/license-text.html", + "https://opensource.org/licenses/CAL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Caldera.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Caldera.json", + "referenceNumber": 622, + "name": "Caldera License", + "licenseId": "Caldera", + "seeAlso": [ + "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Caldera-no-preamble.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Caldera-no-preamble.json", + "referenceNumber": 585, + "name": "Caldera License (without preamble)", + "licenseId": "Caldera-no-preamble", + "seeAlso": [ + "https://github.com/apache/apr/blob/trunk/LICENSE#L298C6-L298C29" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Catharon.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Catharon.json", + "referenceNumber": 45, + "name": "Catharon License", + "licenseId": "Catharon", + "seeAlso": [ + "https://github.com/scummvm/scummvm/blob/v2.8.0/LICENSES/CatharonLicense.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CATOSL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CATOSL-1.1.json", + "referenceNumber": 193, + "name": "Computer Associates Trusted Open Source License 1.1", + "licenseId": "CATOSL-1.1", + "seeAlso": [ + "https://opensource.org/licenses/CATOSL-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-1.0.json", + "referenceNumber": 37, + "name": "Creative Commons Attribution 1.0 Generic", + "licenseId": "CC-BY-1.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by/1.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-2.0.json", + "referenceNumber": 241, + "name": "Creative Commons Attribution 2.0 Generic", + "licenseId": "CC-BY-2.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by/2.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-2.5.json", + "referenceNumber": 129, + "name": "Creative Commons Attribution 2.5 Generic", + "licenseId": "CC-BY-2.5", + "seeAlso": [ + "https://creativecommons.org/licenses/by/2.5/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-2.5-AU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-2.5-AU.json", + "referenceNumber": 583, + "name": "Creative Commons Attribution 2.5 Australia", + "licenseId": "CC-BY-2.5-AU", + "seeAlso": [ + "https://creativecommons.org/licenses/by/2.5/au/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0.json", + "referenceNumber": 302, + "name": "Creative Commons Attribution 3.0 Unported", + "licenseId": "CC-BY-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0-AT.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-AT.json", + "referenceNumber": 324, + "name": "Creative Commons Attribution 3.0 Austria", + "licenseId": "CC-BY-3.0-AT", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/at/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0-AU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-AU.json", + "referenceNumber": 342, + "name": "Creative Commons Attribution 3.0 Australia", + "licenseId": "CC-BY-3.0-AU", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/au/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-DE.json", + "referenceNumber": 239, + "name": "Creative Commons Attribution 3.0 Germany", + "licenseId": "CC-BY-3.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0-IGO.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-IGO.json", + "referenceNumber": 19, + "name": "Creative Commons Attribution 3.0 IGO", + "licenseId": "CC-BY-3.0-IGO", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/igo/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0-NL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-NL.json", + "referenceNumber": 501, + "name": "Creative Commons Attribution 3.0 Netherlands", + "licenseId": "CC-BY-3.0-NL", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/nl/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0-US.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-US.json", + "referenceNumber": 569, + "name": "Creative Commons Attribution 3.0 United States", + "licenseId": "CC-BY-3.0-US", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/us/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-4.0.json", + "referenceNumber": 265, + "name": "Creative Commons Attribution 4.0 International", + "licenseId": "CC-BY-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by/4.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-1.0.json", + "referenceNumber": 167, + "name": "Creative Commons Attribution Non Commercial 1.0 Generic", + "licenseId": "CC-BY-NC-1.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc/1.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-2.0.json", + "referenceNumber": 92, + "name": "Creative Commons Attribution Non Commercial 2.0 Generic", + "licenseId": "CC-BY-NC-2.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc/2.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-2.5.json", + "referenceNumber": 253, + "name": "Creative Commons Attribution Non Commercial 2.5 Generic", + "licenseId": "CC-BY-NC-2.5", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc/2.5/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-3.0.json", + "referenceNumber": 199, + "name": "Creative Commons Attribution Non Commercial 3.0 Unported", + "licenseId": "CC-BY-NC-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc/3.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-3.0-DE.json", + "referenceNumber": 429, + "name": "Creative Commons Attribution Non Commercial 3.0 Germany", + "licenseId": "CC-BY-NC-3.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc/3.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-4.0.json", + "referenceNumber": 188, + "name": "Creative Commons Attribution Non Commercial 4.0 International", + "licenseId": "CC-BY-NC-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc/4.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-1.0.json", + "referenceNumber": 365, + "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic", + "licenseId": "CC-BY-NC-ND-1.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-2.0.json", + "referenceNumber": 416, + "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic", + "licenseId": "CC-BY-NC-ND-2.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-2.5.json", + "referenceNumber": 58, + "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic", + "licenseId": "CC-BY-NC-ND-2.5", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0.json", + "referenceNumber": 213, + "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported", + "licenseId": "CC-BY-NC-ND-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-DE.json", + "referenceNumber": 84, + "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Germany", + "licenseId": "CC-BY-NC-ND-3.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-nd/3.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-IGO.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-IGO.json", + "referenceNumber": 587, + "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO", + "licenseId": "CC-BY-NC-ND-3.0-IGO", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-nd/3.0/igo/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-4.0.json", + "referenceNumber": 296, + "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0 International", + "licenseId": "CC-BY-NC-ND-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-1.0.json", + "referenceNumber": 170, + "name": "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic", + "licenseId": "CC-BY-NC-SA-1.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0.json", + "referenceNumber": 484, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic", + "licenseId": "CC-BY-NC-SA-2.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-DE.json", + "referenceNumber": 184, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Germany", + "licenseId": "CC-BY-NC-SA-2.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/2.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-FR.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-FR.json", + "referenceNumber": 116, + "name": "Creative Commons Attribution-NonCommercial-ShareAlike 2.0 France", + "licenseId": "CC-BY-NC-SA-2.0-FR", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/2.0/fr/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-UK.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-UK.json", + "referenceNumber": 415, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 England and Wales", + "licenseId": "CC-BY-NC-SA-2.0-UK", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/2.0/uk/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.5.json", + "referenceNumber": 106, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic", + "licenseId": "CC-BY-NC-SA-2.5", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0.json", + "referenceNumber": 323, + "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported", + "licenseId": "CC-BY-NC-SA-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-DE.json", + "referenceNumber": 150, + "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Germany", + "licenseId": "CC-BY-NC-SA-3.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-IGO.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-IGO.json", + "referenceNumber": 295, + "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 IGO", + "licenseId": "CC-BY-NC-SA-3.0-IGO", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/3.0/igo/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-4.0.json", + "referenceNumber": 351, + "name": "Creative Commons Attribution Non Commercial Share Alike 4.0 International", + "licenseId": "CC-BY-NC-SA-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-1.0.json", + "referenceNumber": 56, + "name": "Creative Commons Attribution No Derivatives 1.0 Generic", + "licenseId": "CC-BY-ND-1.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/1.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-2.0.json", + "referenceNumber": 640, + "name": "Creative Commons Attribution No Derivatives 2.0 Generic", + "licenseId": "CC-BY-ND-2.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/2.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-2.5.json", + "referenceNumber": 276, + "name": "Creative Commons Attribution No Derivatives 2.5 Generic", + "licenseId": "CC-BY-ND-2.5", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/2.5/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-3.0.json", + "referenceNumber": 173, + "name": "Creative Commons Attribution No Derivatives 3.0 Unported", + "licenseId": "CC-BY-ND-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/3.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-3.0-DE.json", + "referenceNumber": 525, + "name": "Creative Commons Attribution No Derivatives 3.0 Germany", + "licenseId": "CC-BY-ND-3.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/3.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-4.0.json", + "referenceNumber": 328, + "name": "Creative Commons Attribution No Derivatives 4.0 International", + "licenseId": "CC-BY-ND-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/4.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-1.0.json", + "referenceNumber": 453, + "name": "Creative Commons Attribution Share Alike 1.0 Generic", + "licenseId": "CC-BY-SA-1.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/1.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.0.json", + "referenceNumber": 174, + "name": "Creative Commons Attribution Share Alike 2.0 Generic", + "licenseId": "CC-BY-SA-2.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/2.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-2.0-UK.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.0-UK.json", + "referenceNumber": 387, + "name": "Creative Commons Attribution Share Alike 2.0 England and Wales", + "licenseId": "CC-BY-SA-2.0-UK", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/2.0/uk/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-2.1-JP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.1-JP.json", + "referenceNumber": 471, + "name": "Creative Commons Attribution Share Alike 2.1 Japan", + "licenseId": "CC-BY-SA-2.1-JP", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.5.json", + "referenceNumber": 461, + "name": "Creative Commons Attribution Share Alike 2.5 Generic", + "licenseId": "CC-BY-SA-2.5", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/2.5/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0.json", + "referenceNumber": 621, + "name": "Creative Commons Attribution Share Alike 3.0 Unported", + "licenseId": "CC-BY-SA-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/3.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-AT.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-AT.json", + "referenceNumber": 31, + "name": "Creative Commons Attribution Share Alike 3.0 Austria", + "licenseId": "CC-BY-SA-3.0-AT", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/3.0/at/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-DE.json", + "referenceNumber": 325, + "name": "Creative Commons Attribution Share Alike 3.0 Germany", + "licenseId": "CC-BY-SA-3.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/3.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-IGO.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-IGO.json", + "referenceNumber": 20, + "name": "Creative Commons Attribution-ShareAlike 3.0 IGO", + "licenseId": "CC-BY-SA-3.0-IGO", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/3.0/igo/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-4.0.json", + "referenceNumber": 155, + "name": "Creative Commons Attribution Share Alike 4.0 International", + "licenseId": "CC-BY-SA-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/4.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CC-PDDC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-PDDC.json", + "referenceNumber": 349, + "name": "Creative Commons Public Domain Dedication and Certification", + "licenseId": "CC-PDDC", + "seeAlso": [ + "https://creativecommons.org/licenses/publicdomain/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC0-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC0-1.0.json", + "referenceNumber": 70, + "name": "Creative Commons Zero v1.0 Universal", + "licenseId": "CC0-1.0", + "seeAlso": [ + "https://creativecommons.org/publicdomain/zero/1.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CDDL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDDL-1.0.json", + "referenceNumber": 282, + "name": "Common Development and Distribution License 1.0", + "licenseId": "CDDL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/cddl1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CDDL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDDL-1.1.json", + "referenceNumber": 130, + "name": "Common Development and Distribution License 1.1", + "licenseId": "CDDL-1.1", + "seeAlso": [ + "http://glassfish.java.net/public/CDDL+GPL_1_1.html", + "https://javaee.github.io/glassfish/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CDL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDL-1.0.json", + "referenceNumber": 592, + "name": "Common Documentation License 1.0", + "licenseId": "CDL-1.0", + "seeAlso": [ + "http://www.opensource.apple.com/cdl/", + "https://fedoraproject.org/wiki/Licensing/Common_Documentation_License", + "https://www.gnu.org/licenses/license-list.html#ACDL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CDLA-Permissive-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDLA-Permissive-1.0.json", + "referenceNumber": 551, + "name": "Community Data License Agreement Permissive 1.0", + "licenseId": "CDLA-Permissive-1.0", + "seeAlso": [ + "https://cdla.io/permissive-1-0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CDLA-Permissive-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDLA-Permissive-2.0.json", + "referenceNumber": 319, + "name": "Community Data License Agreement Permissive 2.0", + "licenseId": "CDLA-Permissive-2.0", + "seeAlso": [ + "https://cdla.dev/permissive-2-0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CDLA-Sharing-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDLA-Sharing-1.0.json", + "referenceNumber": 445, + "name": "Community Data License Agreement Sharing 1.0", + "licenseId": "CDLA-Sharing-1.0", + "seeAlso": [ + "https://cdla.io/sharing-1-0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CECILL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CECILL-1.0.json", + "referenceNumber": 219, + "name": "CeCILL Free Software License Agreement v1.0", + "licenseId": "CECILL-1.0", + "seeAlso": [ + "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CECILL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CECILL-1.1.json", + "referenceNumber": 38, + "name": "CeCILL Free Software License Agreement v1.1", + "licenseId": "CECILL-1.1", + "seeAlso": [ + "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CECILL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CECILL-2.0.json", + "referenceNumber": 73, + "name": "CeCILL Free Software License Agreement v2.0", + "licenseId": "CECILL-2.0", + "seeAlso": [ + "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CECILL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CECILL-2.1.json", + "referenceNumber": 393, + "name": "CeCILL Free Software License Agreement v2.1", + "licenseId": "CECILL-2.1", + "seeAlso": [ + "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CECILL-B.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CECILL-B.json", + "referenceNumber": 354, + "name": "CeCILL-B Free Software License Agreement", + "licenseId": "CECILL-B", + "seeAlso": [ + "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CECILL-C.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CECILL-C.json", + "referenceNumber": 271, + "name": "CeCILL-C Free Software License Agreement", + "licenseId": "CECILL-C", + "seeAlso": [ + "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CERN-OHL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-1.1.json", + "referenceNumber": 32, + "name": "CERN Open Hardware Licence v1.1", + "licenseId": "CERN-OHL-1.1", + "seeAlso": [ + "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.1" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CERN-OHL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-1.2.json", + "referenceNumber": 95, + "name": "CERN Open Hardware Licence v1.2", + "licenseId": "CERN-OHL-1.2", + "seeAlso": [ + "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.2" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CERN-OHL-P-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-P-2.0.json", + "referenceNumber": 198, + "name": "CERN Open Hardware Licence Version 2 - Permissive", + "licenseId": "CERN-OHL-P-2.0", + "seeAlso": [ + "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CERN-OHL-S-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-S-2.0.json", + "referenceNumber": 370, + "name": "CERN Open Hardware Licence Version 2 - Strongly Reciprocal", + "licenseId": "CERN-OHL-S-2.0", + "seeAlso": [ + "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CERN-OHL-W-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-W-2.0.json", + "referenceNumber": 82, + "name": "CERN Open Hardware Licence Version 2 - Weakly Reciprocal", + "licenseId": "CERN-OHL-W-2.0", + "seeAlso": [ + "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CFITSIO.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CFITSIO.json", + "referenceNumber": 96, + "name": "CFITSIO License", + "licenseId": "CFITSIO", + "seeAlso": [ + "https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/f_user/node9.html", + "https://heasarc.gsfc.nasa.gov/docs/software/ftools/fv/doc/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/check-cvs.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/check-cvs.json", + "referenceNumber": 521, + "name": "check-cvs License", + "licenseId": "check-cvs", + "seeAlso": [ + "http://cvs.savannah.gnu.org/viewvc/cvs/ccvs/contrib/check_cvs.in?revision\u003d1.1.4.3\u0026view\u003dmarkup\u0026pathrev\u003dcvs1-11-23#l2" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/checkmk.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/checkmk.json", + "referenceNumber": 272, + "name": "Checkmk License", + "licenseId": "checkmk", + "seeAlso": [ + "https://github.com/libcheck/check/blob/master/checkmk/checkmk.in" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ClArtistic.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ClArtistic.json", + "referenceNumber": 66, + "name": "Clarified Artistic License", + "licenseId": "ClArtistic", + "seeAlso": [ + "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/", + "http://www.ncftp.com/ncftp/doc/LICENSE.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Clips.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Clips.json", + "referenceNumber": 450, + "name": "Clips License", + "licenseId": "Clips", + "seeAlso": [ + "https://github.com/DrItanium/maya/blob/master/LICENSE.CLIPS" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CMU-Mach.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CMU-Mach.json", + "referenceNumber": 410, + "name": "CMU Mach License", + "licenseId": "CMU-Mach", + "seeAlso": [ + "https://www.cs.cmu.edu/~410/licenses.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CMU-Mach-nodoc.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CMU-Mach-nodoc.json", + "referenceNumber": 111, + "name": "CMU Mach - no notices-in-documentation variant", + "licenseId": "CMU-Mach-nodoc", + "seeAlso": [ + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L718-L728", + "https://web.mit.edu/kerberos/krb5-1.21/doc/mitK5license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CNRI-Jython.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CNRI-Jython.json", + "referenceNumber": 509, + "name": "CNRI Jython License", + "licenseId": "CNRI-Jython", + "seeAlso": [ + "http://www.jython.org/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CNRI-Python.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CNRI-Python.json", + "referenceNumber": 611, + "name": "CNRI Python License", + "licenseId": "CNRI-Python", + "seeAlso": [ + "https://opensource.org/licenses/CNRI-Python" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.json", + "referenceNumber": 504, + "name": "CNRI Python Open Source GPL Compatible License Agreement", + "licenseId": "CNRI-Python-GPL-Compatible", + "seeAlso": [ + "http://www.python.org/download/releases/1.6.1/download_win/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/COIL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/COIL-1.0.json", + "referenceNumber": 286, + "name": "Copyfree Open Innovation License", + "licenseId": "COIL-1.0", + "seeAlso": [ + "https://coil.apotheon.org/plaintext/01.0.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Community-Spec-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Community-Spec-1.0.json", + "referenceNumber": 631, + "name": "Community Specification License 1.0", + "licenseId": "Community-Spec-1.0", + "seeAlso": [ + "https://github.com/CommunitySpecification/1.0/blob/master/1._Community_Specification_License-v1.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Condor-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Condor-1.1.json", + "referenceNumber": 251, + "name": "Condor Public License v1.1", + "licenseId": "Condor-1.1", + "seeAlso": [ + "http://research.cs.wisc.edu/condor/license.html#condor", + "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/copyleft-next-0.3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/copyleft-next-0.3.0.json", + "referenceNumber": 421, + "name": "copyleft-next 0.3.0", + "licenseId": "copyleft-next-0.3.0", + "seeAlso": [ + "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/copyleft-next-0.3.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/copyleft-next-0.3.1.json", + "referenceNumber": 119, + "name": "copyleft-next 0.3.1", + "licenseId": "copyleft-next-0.3.1", + "seeAlso": [ + "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.1" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Cornell-Lossless-JPEG.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Cornell-Lossless-JPEG.json", + "referenceNumber": 632, + "name": "Cornell Lossless JPEG License", + "licenseId": "Cornell-Lossless-JPEG", + "seeAlso": [ + "https://android.googlesource.com/platform/external/dng_sdk/+/refs/heads/master/source/dng_lossless_jpeg.cpp#16", + "https://www.mssl.ucl.ac.uk/~mcrw/src/20050920/proto.h", + "https://gitlab.freedesktop.org/libopenraw/libopenraw/blob/master/lib/ljpegdecompressor.cpp#L32" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CPAL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CPAL-1.0.json", + "referenceNumber": 315, + "name": "Common Public Attribution License 1.0", + "licenseId": "CPAL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/CPAL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CPL-1.0.json", + "referenceNumber": 135, + "name": "Common Public License 1.0", + "licenseId": "CPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/CPL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CPOL-1.02.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CPOL-1.02.json", + "referenceNumber": 479, + "name": "Code Project Open License 1.02", + "licenseId": "CPOL-1.02", + "seeAlso": [ + "http://www.codeproject.com/info/cpol10.aspx" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/Cronyx.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Cronyx.json", + "referenceNumber": 377, + "name": "Cronyx License", + "licenseId": "Cronyx", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/font/alias/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/font/cronyx-cyrillic/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/font/misc-cyrillic/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/font/screen-cyrillic/-/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Crossword.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Crossword.json", + "referenceNumber": 340, + "name": "Crossword License", + "licenseId": "Crossword", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Crossword" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CrystalStacker.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CrystalStacker.json", + "referenceNumber": 593, + "name": "CrystalStacker License", + "licenseId": "CrystalStacker", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CUA-OPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CUA-OPL-1.0.json", + "referenceNumber": 553, + "name": "CUA Office Public License v1.0", + "licenseId": "CUA-OPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/CUA-OPL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Cube.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Cube.json", + "referenceNumber": 404, + "name": "Cube License", + "licenseId": "Cube", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Cube" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/curl.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/curl.json", + "referenceNumber": 604, + "name": "curl License", + "licenseId": "curl", + "seeAlso": [ + "https://github.com/bagder/curl/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/cve-tou.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/cve-tou.json", + "referenceNumber": 306, + "name": "Common Vulnerability Enumeration ToU License", + "licenseId": "cve-tou", + "seeAlso": [ + "https://www.cve.org/Legal/TermsOfUse" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/D-FSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/D-FSL-1.0.json", + "referenceNumber": 154, + "name": "Deutsche Freie Software Lizenz", + "licenseId": "D-FSL-1.0", + "seeAlso": [ + "http://www.dipp.nrw.de/d-fsl/lizenzen/", + "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt", + "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DEC-3-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DEC-3-Clause.json", + "referenceNumber": 15, + "name": "DEC 3-Clause License", + "licenseId": "DEC-3-Clause", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type\u003dheads#L239" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/diffmark.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/diffmark.json", + "referenceNumber": 292, + "name": "diffmark license", + "licenseId": "diffmark", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/diffmark" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DL-DE-BY-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DL-DE-BY-2.0.json", + "referenceNumber": 225, + "name": "Data licence Germany – attribution – version 2.0", + "licenseId": "DL-DE-BY-2.0", + "seeAlso": [ + "https://www.govdata.de/dl-de/by-2-0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DL-DE-ZERO-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DL-DE-ZERO-2.0.json", + "referenceNumber": 341, + "name": "Data licence Germany – zero – version 2.0", + "licenseId": "DL-DE-ZERO-2.0", + "seeAlso": [ + "https://www.govdata.de/dl-de/zero-2-0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DOC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DOC.json", + "referenceNumber": 397, + "name": "DOC License", + "licenseId": "DOC", + "seeAlso": [ + "http://www.cs.wustl.edu/~schmidt/ACE-copying.html", + "https://www.dre.vanderbilt.edu/~schmidt/ACE-copying.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Dotseqn.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Dotseqn.json", + "referenceNumber": 132, + "name": "Dotseqn License", + "licenseId": "Dotseqn", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Dotseqn" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DRL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DRL-1.0.json", + "referenceNumber": 16, + "name": "Detection Rule License 1.0", + "licenseId": "DRL-1.0", + "seeAlso": [ + "https://github.com/Neo23x0/sigma/blob/master/LICENSE.Detection.Rules.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DRL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DRL-1.1.json", + "referenceNumber": 278, + "name": "Detection Rule License 1.1", + "licenseId": "DRL-1.1", + "seeAlso": [ + "https://github.com/SigmaHQ/Detection-Rule-License/blob/6ec7fbde6101d101b5b5d1fcb8f9b69fbc76c04a/LICENSE.Detection.Rules.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DSDP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DSDP.json", + "referenceNumber": 485, + "name": "DSDP License", + "licenseId": "DSDP", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/DSDP" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/dtoa.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/dtoa.json", + "referenceNumber": 358, + "name": "David M. Gay dtoa License", + "licenseId": "dtoa", + "seeAlso": [ + "https://github.com/SWI-Prolog/swipl-devel/blob/master/src/os/dtoa.c", + "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/stdlib/mprec.h;hb\u003dHEAD" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/dvipdfm.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/dvipdfm.json", + "referenceNumber": 100, + "name": "dvipdfm License", + "licenseId": "dvipdfm", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/dvipdfm" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ECL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ECL-1.0.json", + "referenceNumber": 124, + "name": "Educational Community License v1.0", + "licenseId": "ECL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/ECL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/ECL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ECL-2.0.json", + "referenceNumber": 361, + "name": "Educational Community License v2.0", + "licenseId": "ECL-2.0", + "seeAlso": [ + "https://opensource.org/licenses/ECL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/eCos-2.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/eCos-2.0.json", + "referenceNumber": 372, + "name": "eCos license version 2.0", + "licenseId": "eCos-2.0", + "seeAlso": [ + "https://www.gnu.org/licenses/ecos-license.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/EFL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EFL-1.0.json", + "referenceNumber": 335, + "name": "Eiffel Forum License v1.0", + "licenseId": "EFL-1.0", + "seeAlso": [ + "http://www.eiffel-nice.org/license/forum.txt", + "https://opensource.org/licenses/EFL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/EFL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EFL-2.0.json", + "referenceNumber": 88, + "name": "Eiffel Forum License v2.0", + "licenseId": "EFL-2.0", + "seeAlso": [ + "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html", + "https://opensource.org/licenses/EFL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/eGenix.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/eGenix.json", + "referenceNumber": 261, + "name": "eGenix.com Public License 1.1.0", + "licenseId": "eGenix", + "seeAlso": [ + "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf", + "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Elastic-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Elastic-2.0.json", + "referenceNumber": 147, + "name": "Elastic License 2.0", + "licenseId": "Elastic-2.0", + "seeAlso": [ + "https://www.elastic.co/licensing/elastic-license", + "https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE-2.0.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Entessa.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Entessa.json", + "referenceNumber": 546, + "name": "Entessa Public License v1.0", + "licenseId": "Entessa", + "seeAlso": [ + "https://opensource.org/licenses/Entessa" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/EPICS.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EPICS.json", + "referenceNumber": 120, + "name": "EPICS Open License", + "licenseId": "EPICS", + "seeAlso": [ + "https://epics.anl.gov/license/open.php" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/EPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EPL-1.0.json", + "referenceNumber": 500, + "name": "Eclipse Public License 1.0", + "licenseId": "EPL-1.0", + "seeAlso": [ + "http://www.eclipse.org/legal/epl-v10.html", + "https://opensource.org/licenses/EPL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/EPL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EPL-2.0.json", + "referenceNumber": 407, + "name": "Eclipse Public License 2.0", + "licenseId": "EPL-2.0", + "seeAlso": [ + "https://www.eclipse.org/legal/epl-2.0", + "https://www.opensource.org/licenses/EPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/ErlPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ErlPL-1.1.json", + "referenceNumber": 466, + "name": "Erlang Public License v1.1", + "licenseId": "ErlPL-1.1", + "seeAlso": [ + "http://www.erlang.org/EPLICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/etalab-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/etalab-2.0.json", + "referenceNumber": 636, + "name": "Etalab Open License 2.0", + "licenseId": "etalab-2.0", + "seeAlso": [ + "https://github.com/DISIC/politique-de-contribution-open-source/blob/master/LICENSE.pdf", + "https://raw.githubusercontent.com/DISIC/politique-de-contribution-open-source/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/EUDatagrid.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EUDatagrid.json", + "referenceNumber": 228, + "name": "EU DataGrid Software License", + "licenseId": "EUDatagrid", + "seeAlso": [ + "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html", + "https://opensource.org/licenses/EUDatagrid" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/EUPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EUPL-1.0.json", + "referenceNumber": 227, + "name": "European Union Public License 1.0", + "licenseId": "EUPL-1.0", + "seeAlso": [ + "http://ec.europa.eu/idabc/en/document/7330.html", + "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/EUPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EUPL-1.1.json", + "referenceNumber": 266, + "name": "European Union Public License 1.1", + "licenseId": "EUPL-1.1", + "seeAlso": [ + "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf", + "https://opensource.org/licenses/EUPL-1.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/EUPL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EUPL-1.2.json", + "referenceNumber": 559, + "name": "European Union Public License 1.2", + "licenseId": "EUPL-1.2", + "seeAlso": [ + "https://joinup.ec.europa.eu/page/eupl-text-11-12", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/2020-03/EUPL-1.2%20EN.txt", + "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt", + "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863", + "https://opensource.org/licenses/EUPL-1.2" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Eurosym.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Eurosym.json", + "referenceNumber": 63, + "name": "Eurosym License", + "licenseId": "Eurosym", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Eurosym" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Fair.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Fair.json", + "referenceNumber": 570, + "name": "Fair License", + "licenseId": "Fair", + "seeAlso": [ + "https://web.archive.org/web/20150926120323/http://fairlicense.org/", + "https://opensource.org/licenses/Fair" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/FBM.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FBM.json", + "referenceNumber": 175, + "name": "Fuzzy Bitmap License", + "licenseId": "FBM", + "seeAlso": [ + "https://github.com/SWI-Prolog/packages-xpce/blob/161a40cd82004f731ba48024f9d30af388a7edf5/src/img/gifwrite.c#L21-L26" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FDK-AAC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FDK-AAC.json", + "referenceNumber": 49, + "name": "Fraunhofer FDK AAC Codec Library", + "licenseId": "FDK-AAC", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/FDK-AAC", + "https://directory.fsf.org/wiki/License:Fdk" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Ferguson-Twofish.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Ferguson-Twofish.json", + "referenceNumber": 617, + "name": "Ferguson Twofish License", + "licenseId": "Ferguson-Twofish", + "seeAlso": [ + "https://github.com/wernerd/ZRTPCPP/blob/6b3cd8e6783642292bad0c21e3e5e5ce45ff3e03/cryptcommon/twofish.c#L113C3-L127" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Frameworx-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Frameworx-1.0.json", + "referenceNumber": 259, + "name": "Frameworx Open License 1.0", + "licenseId": "Frameworx-1.0", + "seeAlso": [ + "https://opensource.org/licenses/Frameworx-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/FreeBSD-DOC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FreeBSD-DOC.json", + "referenceNumber": 333, + "name": "FreeBSD Documentation License", + "licenseId": "FreeBSD-DOC", + "seeAlso": [ + "https://www.freebsd.org/copyright/freebsd-doc-license/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FreeImage.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FreeImage.json", + "referenceNumber": 181, + "name": "FreeImage Public License v1.0", + "licenseId": "FreeImage", + "seeAlso": [ + "http://freeimage.sourceforge.net/freeimage-license.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FSFAP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FSFAP.json", + "referenceNumber": 36, + "name": "FSF All Permissive License", + "licenseId": "FSFAP", + "seeAlso": [ + "https://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/FSFAP-no-warranty-disclaimer.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FSFAP-no-warranty-disclaimer.json", + "referenceNumber": 536, + "name": "FSF All Permissive License (without Warranty)", + "licenseId": "FSFAP-no-warranty-disclaimer", + "seeAlso": [ + "https://git.savannah.gnu.org/cgit/wget.git/tree/util/trunc.c?h\u003dv1.21.3\u0026id\u003d40747a11e44ced5a8ac628a41f879ced3e2ebce9#n6" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FSFUL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FSFUL.json", + "referenceNumber": 454, + "name": "FSF Unlimited License", + "licenseId": "FSFUL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FSFULLR.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FSFULLR.json", + "referenceNumber": 422, + "name": "FSF Unlimited License (with License Retention)", + "licenseId": "FSFULLR", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FSFULLRWD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FSFULLRWD.json", + "referenceNumber": 197, + "name": "FSF Unlimited License (With License Retention and Warranty Disclaimer)", + "licenseId": "FSFULLRWD", + "seeAlso": [ + "https://lists.gnu.org/archive/html/autoconf/2012-04/msg00061.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FTL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FTL.json", + "referenceNumber": 438, + "name": "Freetype Project License", + "licenseId": "FTL", + "seeAlso": [ + "http://freetype.fis.uniroma2.it/FTL.TXT", + "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT", + "http://gitlab.freedesktop.org/freetype/freetype/-/raw/master/docs/FTL.TXT" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Furuseth.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Furuseth.json", + "referenceNumber": 380, + "name": "Furuseth License", + "licenseId": "Furuseth", + "seeAlso": [ + "https://git.openldap.org/openldap/openldap/-/blob/master/COPYRIGHT?ref_type\u003dheads#L39-51" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/fwlw.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/fwlw.json", + "referenceNumber": 529, + "name": "fwlw License", + "licenseId": "fwlw", + "seeAlso": [ + "https://mirrors.nic.cz/tex-archive/macros/latex/contrib/fwlw/README" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GCR-docs.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GCR-docs.json", + "referenceNumber": 115, + "name": "Gnome GCR Documentation License", + "licenseId": "GCR-docs", + "seeAlso": [ + "https://github.com/GNOME/gcr/blob/master/docs/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GD.json", + "referenceNumber": 291, + "name": "GD License", + "licenseId": "GD", + "seeAlso": [ + "https://libgd.github.io/manuals/2.3.0/files/license-txt.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1.json", + "referenceNumber": 589, + "name": "GNU Free Documentation License v1.1", + "licenseId": "GFDL-1.1", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-invariants-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-invariants-only.json", + "referenceNumber": 307, + "name": "GNU Free Documentation License v1.1 only - invariants", + "licenseId": "GFDL-1.1-invariants-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-invariants-or-later.json", + "referenceNumber": 98, + "name": "GNU Free Documentation License v1.1 or later - invariants", + "licenseId": "GFDL-1.1-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-no-invariants-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-no-invariants-only.json", + "referenceNumber": 47, + "name": "GNU Free Documentation License v1.1 only - no invariants", + "licenseId": "GFDL-1.1-no-invariants-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-no-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-no-invariants-or-later.json", + "referenceNumber": 273, + "name": "GNU Free Documentation License v1.1 or later - no invariants", + "licenseId": "GFDL-1.1-no-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-only.json", + "referenceNumber": 626, + "name": "GNU Free Documentation License v1.1 only", + "licenseId": "GFDL-1.1-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-or-later.json", + "referenceNumber": 644, + "name": "GNU Free Documentation License v1.1 or later", + "licenseId": "GFDL-1.1-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2.json", + "referenceNumber": 520, + "name": "GNU Free Documentation License v1.2", + "licenseId": "GFDL-1.2", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2-invariants-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-invariants-only.json", + "referenceNumber": 495, + "name": "GNU Free Documentation License v1.2 only - invariants", + "licenseId": "GFDL-1.2-invariants-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-invariants-or-later.json", + "referenceNumber": 6, + "name": "GNU Free Documentation License v1.2 or later - invariants", + "licenseId": "GFDL-1.2-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2-no-invariants-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-no-invariants-only.json", + "referenceNumber": 77, + "name": "GNU Free Documentation License v1.2 only - no invariants", + "licenseId": "GFDL-1.2-no-invariants-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.json", + "referenceNumber": 279, + "name": "GNU Free Documentation License v1.2 or later - no invariants", + "licenseId": "GFDL-1.2-no-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-only.json", + "referenceNumber": 648, + "name": "GNU Free Documentation License v1.2 only", + "licenseId": "GFDL-1.2-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-or-later.json", + "referenceNumber": 318, + "name": "GNU Free Documentation License v1.2 or later", + "licenseId": "GFDL-1.2-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3.json", + "referenceNumber": 287, + "name": "GNU Free Documentation License v1.3", + "licenseId": "GFDL-1.3", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3-invariants-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-invariants-only.json", + "referenceNumber": 289, + "name": "GNU Free Documentation License v1.3 only - invariants", + "licenseId": "GFDL-1.3-invariants-only", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-invariants-or-later.json", + "referenceNumber": 497, + "name": "GNU Free Documentation License v1.3 or later - invariants", + "licenseId": "GFDL-1.3-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3-no-invariants-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-no-invariants-only.json", + "referenceNumber": 254, + "name": "GNU Free Documentation License v1.3 only - no invariants", + "licenseId": "GFDL-1.3-no-invariants-only", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3-no-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-no-invariants-or-later.json", + "referenceNumber": 207, + "name": "GNU Free Documentation License v1.3 or later - no invariants", + "licenseId": "GFDL-1.3-no-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-only.json", + "referenceNumber": 635, + "name": "GNU Free Documentation License v1.3 only", + "licenseId": "GFDL-1.3-only", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-or-later.json", + "referenceNumber": 448, + "name": "GNU Free Documentation License v1.3 or later", + "licenseId": "GFDL-1.3-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Giftware.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Giftware.json", + "referenceNumber": 172, + "name": "Giftware License", + "licenseId": "Giftware", + "seeAlso": [ + "http://liballeg.org/license.html#allegro-4-the-giftware-license" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GL2PS.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GL2PS.json", + "referenceNumber": 434, + "name": "GL2PS License", + "licenseId": "GL2PS", + "seeAlso": [ + "http://www.geuz.org/gl2ps/COPYING.GL2PS" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Glide.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Glide.json", + "referenceNumber": 189, + "name": "3dfx Glide License", + "licenseId": "Glide", + "seeAlso": [ + "http://www.users.on.net/~triforce/glidexp/COPYING.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Glulxe.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Glulxe.json", + "referenceNumber": 85, + "name": "Glulxe License", + "licenseId": "Glulxe", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Glulxe" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GLWTPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GLWTPL.json", + "referenceNumber": 190, + "name": "Good Luck With That Public License", + "licenseId": "GLWTPL", + "seeAlso": [ + "https://github.com/me-shaon/GLWTPL/commit/da5f6bc734095efbacb442c0b31e33a65b9d6e85" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/gnuplot.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/gnuplot.json", + "referenceNumber": 110, + "name": "gnuplot License", + "licenseId": "gnuplot", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Gnuplot" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-1.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-1.0.json", + "referenceNumber": 630, + "name": "GNU General Public License v1.0 only", + "licenseId": "GPL-1.0", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-1.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-1.0+.json", + "referenceNumber": 26, + "name": "GNU General Public License v1.0 or later", + "licenseId": "GPL-1.0+", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-1.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GPL-1.0-only.json", + "referenceNumber": 12, + "name": "GNU General Public License v1.0 only", + "licenseId": "GPL-1.0-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-1.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GPL-1.0-or-later.json", + "referenceNumber": 642, + "name": "GNU General Public License v1.0 or later", + "licenseId": "GPL-1.0-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0.json", + "referenceNumber": 524, + "name": "GNU General Public License v2.0 only", + "licenseId": "GPL-2.0", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "https://opensource.org/licenses/GPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0+.json", + "referenceNumber": 25, + "name": "GNU General Public License v2.0 or later", + "licenseId": "GPL-2.0+", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "https://opensource.org/licenses/GPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-only.json", + "referenceNumber": 618, + "name": "GNU General Public License v2.0 only", + "licenseId": "GPL-2.0-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt", + "https://opensource.org/licenses/GPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-or-later.json", + "referenceNumber": 164, + "name": "GNU General Public License v2.0 or later", + "licenseId": "GPL-2.0-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "https://opensource.org/licenses/GPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json", + "referenceNumber": 146, + "name": "GNU General Public License v2.0 w/Autoconf exception", + "licenseId": "GPL-2.0-with-autoconf-exception", + "seeAlso": [ + "http://ac-archive.sourceforge.net/doc/copyright.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-bison-exception.json", + "referenceNumber": 374, + "name": "GNU General Public License v2.0 w/Bison exception", + "licenseId": "GPL-2.0-with-bison-exception", + "seeAlso": [ + "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.json", + "referenceNumber": 331, + "name": "GNU General Public License v2.0 w/Classpath exception", + "licenseId": "GPL-2.0-with-classpath-exception", + "seeAlso": [ + "https://www.gnu.org/software/classpath/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-with-font-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-font-exception.json", + "referenceNumber": 542, + "name": "GNU General Public License v2.0 w/Font exception", + "licenseId": "GPL-2.0-with-font-exception", + "seeAlso": [ + "https://www.gnu.org/licenses/gpl-faq.html#FontException" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.json", + "referenceNumber": 68, + "name": "GNU General Public License v2.0 w/GCC Runtime Library exception", + "licenseId": "GPL-2.0-with-GCC-exception", + "seeAlso": [ + "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-3.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0.json", + "referenceNumber": 442, + "name": "GNU General Public License v3.0 only", + "licenseId": "GPL-3.0", + "seeAlso": [ + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-3.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0+.json", + "referenceNumber": 270, + "name": "GNU General Public License v3.0 or later", + "licenseId": "GPL-3.0+", + "seeAlso": [ + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-3.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-only.json", + "referenceNumber": 133, + "name": "GNU General Public License v3.0 only", + "licenseId": "GPL-3.0-only", + "seeAlso": [ + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-3.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-or-later.json", + "referenceNumber": 390, + "name": "GNU General Public License v3.0 or later", + "licenseId": "GPL-3.0-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json", + "referenceNumber": 458, + "name": "GNU General Public License v3.0 w/Autoconf exception", + "licenseId": "GPL-3.0-with-autoconf-exception", + "seeAlso": [ + "https://www.gnu.org/licenses/autoconf-exception-3.0.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.json", + "referenceNumber": 356, + "name": "GNU General Public License v3.0 w/GCC Runtime Library exception", + "licenseId": "GPL-3.0-with-GCC-exception", + "seeAlso": [ + "https://www.gnu.org/licenses/gcc-exception-3.1.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Graphics-Gems.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Graphics-Gems.json", + "referenceNumber": 574, + "name": "Graphics Gems License", + "licenseId": "Graphics-Gems", + "seeAlso": [ + "https://github.com/erich666/GraphicsGems/blob/master/LICENSE.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/gSOAP-1.3b.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/gSOAP-1.3b.json", + "referenceNumber": 655, + "name": "gSOAP Public License v1.3b", + "licenseId": "gSOAP-1.3b", + "seeAlso": [ + "http://www.cs.fsu.edu/~engelen/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/gtkbook.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/gtkbook.json", + "referenceNumber": 237, + "name": "gtkbook License", + "licenseId": "gtkbook", + "seeAlso": [ + "https://github.com/slogan621/gtkbook", + "https://github.com/oetiker/rrdtool-1.x/blob/master/src/plbasename.c#L8-L11" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Gutmann.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Gutmann.json", + "referenceNumber": 441, + "name": "Gutmann License", + "licenseId": "Gutmann", + "seeAlso": [ + "https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HaskellReport.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HaskellReport.json", + "referenceNumber": 625, + "name": "Haskell Language Report License", + "licenseId": "HaskellReport", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/hdparm.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/hdparm.json", + "referenceNumber": 81, + "name": "hdparm License", + "licenseId": "hdparm", + "seeAlso": [ + "https://github.com/Distrotech/hdparm/blob/4517550db29a91420fb2b020349523b1b4512df2/LICENSE.TXT" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Hippocratic-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Hippocratic-2.1.json", + "referenceNumber": 299, + "name": "Hippocratic License 2.1", + "licenseId": "Hippocratic-2.1", + "seeAlso": [ + "https://firstdonoharm.dev/version/2/1/license.html", + "https://github.com/EthicalSource/hippocratic-license/blob/58c0e646d64ff6fbee275bfe2b9492f914e3ab2a/LICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HP-1986.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HP-1986.json", + "referenceNumber": 277, + "name": "Hewlett-Packard 1986 License", + "licenseId": "HP-1986", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/machine/hppa/memchr.S;h\u003d1cca3e5e8867aa4bffef1f75a5c1bba25c0c441e;hb\u003dHEAD#l2" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HP-1989.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HP-1989.json", + "referenceNumber": 639, + "name": "Hewlett-Packard 1989 License", + "licenseId": "HP-1989", + "seeAlso": [ + "https://github.com/bleargh45/Data-UUID/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND.json", + "referenceNumber": 281, + "name": "Historical Permission Notice and Disclaimer", + "licenseId": "HPND", + "seeAlso": [ + "https://opensource.org/licenses/HPND", + "http://lists.opensource.org/pipermail/license-discuss_lists.opensource.org/2002-November/006304.html" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/HPND-DEC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-DEC.json", + "referenceNumber": 577, + "name": "Historical Permission Notice and Disclaimer - DEC variant", + "licenseId": "HPND-DEC", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/app/xkbcomp/-/blob/master/COPYING?ref_type\u003dheads#L69" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-doc.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-doc.json", + "referenceNumber": 391, + "name": "Historical Permission Notice and Disclaimer - documentation variant", + "licenseId": "HPND-doc", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/lib/libxext/-/blob/master/COPYING?ref_type\u003dheads#L185-197", + "https://gitlab.freedesktop.org/xorg/lib/libxtst/-/blob/master/COPYING?ref_type\u003dheads#L70-77" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-doc-sell.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-doc-sell.json", + "referenceNumber": 163, + "name": "Historical Permission Notice and Disclaimer - documentation sell variant", + "licenseId": "HPND-doc-sell", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/lib/libxtst/-/blob/master/COPYING?ref_type\u003dheads#L108-117", + "https://gitlab.freedesktop.org/xorg/lib/libxext/-/blob/master/COPYING?ref_type\u003dheads#L153-162" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-export-US.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-export-US.json", + "referenceNumber": 214, + "name": "HPND with US Government export control warning", + "licenseId": "HPND-export-US", + "seeAlso": [ + "https://www.kermitproject.org/ck90.html#source" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-export-US-acknowledgement.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-export-US-acknowledgement.json", + "referenceNumber": 610, + "name": "HPND with US Government export control warning and acknowledgment", + "licenseId": "HPND-export-US-acknowledgement", + "seeAlso": [ + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L831-L852", + "https://web.mit.edu/kerberos/krb5-1.21/doc/mitK5license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-export-US-modify.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-export-US-modify.json", + "referenceNumber": 498, + "name": "HPND with US Government export control warning and modification rqmt", + "licenseId": "HPND-export-US-modify", + "seeAlso": [ + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L1157-L1182", + "https://github.com/pythongssapi/k5test/blob/v0.10.3/K5TEST-LICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-export2-US.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-export2-US.json", + "referenceNumber": 33, + "name": "HPND with US Government export control and 2 disclaimers", + "licenseId": "HPND-export2-US", + "seeAlso": [ + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L111-L133", + "https://web.mit.edu/kerberos/krb5-1.21/doc/mitK5license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-Fenneberg-Livingston.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-Fenneberg-Livingston.json", + "referenceNumber": 145, + "name": "Historical Permission Notice and Disclaimer - Fenneberg-Livingston variant", + "licenseId": "HPND-Fenneberg-Livingston", + "seeAlso": [ + "https://github.com/FreeRADIUS/freeradius-client/blob/master/COPYRIGHT#L32", + "https://github.com/radcli/radcli/blob/master/COPYRIGHT#L34" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-INRIA-IMAG.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-INRIA-IMAG.json", + "referenceNumber": 614, + "name": "Historical Permission Notice and Disclaimer - INRIA-IMAG variant", + "licenseId": "HPND-INRIA-IMAG", + "seeAlso": [ + "https://github.com/ppp-project/ppp/blob/master/pppd/ipv6cp.c#L75-L83" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-Intel.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-Intel.json", + "referenceNumber": 195, + "name": "Historical Permission Notice and Disclaimer - Intel variant", + "licenseId": "HPND-Intel", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/machine/i960/memcpy.S;hb\u003dHEAD" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-Kevlin-Henney.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-Kevlin-Henney.json", + "referenceNumber": 428, + "name": "Historical Permission Notice and Disclaimer - Kevlin Henney variant", + "licenseId": "HPND-Kevlin-Henney", + "seeAlso": [ + "https://github.com/mruby/mruby/blob/83d12f8d52522cdb7c8cc46fad34821359f453e6/mrbgems/mruby-dir/src/Win/dirent.c#L127-L140" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-Markus-Kuhn.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-Markus-Kuhn.json", + "referenceNumber": 8, + "name": "Historical Permission Notice and Disclaimer - Markus Kuhn variant", + "licenseId": "HPND-Markus-Kuhn", + "seeAlso": [ + "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c", + "https://sourceware.org/git/?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dreadline/readline/support/wcwidth.c;h\u003d0f5ec995796f4813abbcf4972aec0378ab74722a;hb\u003dHEAD#l55" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-merchantability-variant.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-merchantability-variant.json", + "referenceNumber": 540, + "name": "Historical Permission Notice and Disclaimer - merchantability variant", + "licenseId": "HPND-merchantability-variant", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/misc/fini.c;hb\u003dHEAD" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-MIT-disclaimer.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-MIT-disclaimer.json", + "referenceNumber": 185, + "name": "Historical Permission Notice and Disclaimer with MIT disclaimer", + "licenseId": "HPND-MIT-disclaimer", + "seeAlso": [ + "https://metacpan.org/release/NLNETLABS/Net-DNS-SEC-1.22/source/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-Pbmplus.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-Pbmplus.json", + "referenceNumber": 603, + "name": "Historical Permission Notice and Disclaimer - Pbmplus variant", + "licenseId": "HPND-Pbmplus", + "seeAlso": [ + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/netpbm.c#l8" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-sell-MIT-disclaimer-xserver.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-sell-MIT-disclaimer-xserver.json", + "referenceNumber": 125, + "name": "Historical Permission Notice and Disclaimer - sell xserver variant with MIT disclaimer", + "licenseId": "HPND-sell-MIT-disclaimer-xserver", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/COPYING?ref_type\u003dheads#L1781" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-sell-regexpr.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-sell-regexpr.json", + "referenceNumber": 633, + "name": "Historical Permission Notice and Disclaimer - sell regexpr variant", + "licenseId": "HPND-sell-regexpr", + "seeAlso": [ + "https://gitlab.com/bacula-org/bacula/-/blob/Branch-11.0/bacula/LICENSE-FOSS?ref_type\u003dheads#L245" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-sell-variant.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-sell-variant.json", + "referenceNumber": 344, + "name": "Historical Permission Notice and Disclaimer - sell variant", + "licenseId": "HPND-sell-variant", + "seeAlso": [ + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sunrpc/auth_gss/gss_generic_token.c?h\u003dv4.19" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer.json", + "referenceNumber": 160, + "name": "HPND sell variant with MIT disclaimer", + "licenseId": "HPND-sell-variant-MIT-disclaimer", + "seeAlso": [ + "https://github.com/sigmavirus24/x11-ssh-askpass/blob/master/README" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer-rev.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer-rev.json", + "referenceNumber": 609, + "name": "HPND sell variant with MIT disclaimer - reverse", + "licenseId": "HPND-sell-variant-MIT-disclaimer-rev", + "seeAlso": [ + "https://github.com/sigmavirus24/x11-ssh-askpass/blob/master/dynlist.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-UC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-UC.json", + "referenceNumber": 386, + "name": "Historical Permission Notice and Disclaimer - University of California variant", + "licenseId": "HPND-UC", + "seeAlso": [ + "https://core.tcl-lang.org/tk/file?name\u003dcompat/unistd.h" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-UC-export-US.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-UC-export-US.json", + "referenceNumber": 118, + "name": "Historical Permission Notice and Disclaimer - University of California, US export warning", + "licenseId": "HPND-UC-export-US", + "seeAlso": [ + "https://github.com/RTimothyEdwards/magic/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HTMLTIDY.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HTMLTIDY.json", + "referenceNumber": 134, + "name": "HTML Tidy License", + "licenseId": "HTMLTIDY", + "seeAlso": [ + "https://github.com/htacg/tidy-html5/blob/next/README/LICENSE.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/IBM-pibs.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IBM-pibs.json", + "referenceNumber": 102, + "name": "IBM PowerPC Initialization and Boot Software", + "licenseId": "IBM-pibs", + "seeAlso": [ + "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ICU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ICU.json", + "referenceNumber": 67, + "name": "ICU License", + "licenseId": "ICU", + "seeAlso": [ + "http://source.icu-project.org/repos/icu/icu/trunk/license.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/IEC-Code-Components-EULA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IEC-Code-Components-EULA.json", + "referenceNumber": 359, + "name": "IEC Code Components End-user licence agreement", + "licenseId": "IEC-Code-Components-EULA", + "seeAlso": [ + "https://www.iec.ch/webstore/custserv/pdf/CC-EULA.pdf", + "https://www.iec.ch/CCv1", + "https://www.iec.ch/copyright" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/IJG.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IJG.json", + "referenceNumber": 641, + "name": "Independent JPEG Group License", + "licenseId": "IJG", + "seeAlso": [ + "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/IJG-short.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IJG-short.json", + "referenceNumber": 615, + "name": "Independent JPEG Group License - short", + "licenseId": "IJG-short", + "seeAlso": [ + "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/ljpg/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ImageMagick.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ImageMagick.json", + "referenceNumber": 478, + "name": "ImageMagick License", + "licenseId": "ImageMagick", + "seeAlso": [ + "http://www.imagemagick.org/script/license.php" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/iMatix.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/iMatix.json", + "referenceNumber": 327, + "name": "iMatix Standard Function Library Agreement", + "licenseId": "iMatix", + "seeAlso": [ + "http://legacy.imatix.com/html/sfl/sfl4.htm#license" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Imlib2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Imlib2.json", + "referenceNumber": 169, + "name": "Imlib2 License", + "licenseId": "Imlib2", + "seeAlso": [ + "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING", + "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Info-ZIP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Info-ZIP.json", + "referenceNumber": 269, + "name": "Info-ZIP License", + "licenseId": "Info-ZIP", + "seeAlso": [ + "http://www.info-zip.org/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Inner-Net-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Inner-Net-2.0.json", + "referenceNumber": 572, + "name": "Inner Net License v2.0", + "licenseId": "Inner-Net-2.0", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Inner_Net_License", + "https://sourceware.org/git/?p\u003dglibc.git;a\u003dblob;f\u003dLICENSES;h\u003d530893b1dc9ea00755603c68fb36bd4fc38a7be8;hb\u003dHEAD#l207" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Intel.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Intel.json", + "referenceNumber": 623, + "name": "Intel Open Source License", + "licenseId": "Intel", + "seeAlso": [ + "https://opensource.org/licenses/Intel" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Intel-ACPI.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Intel-ACPI.json", + "referenceNumber": 571, + "name": "Intel ACPI Software License Agreement", + "licenseId": "Intel-ACPI", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Interbase-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Interbase-1.0.json", + "referenceNumber": 654, + "name": "Interbase Public License v1.0", + "licenseId": "Interbase-1.0", + "seeAlso": [ + "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/IPA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IPA.json", + "referenceNumber": 94, + "name": "IPA Font License", + "licenseId": "IPA", + "seeAlso": [ + "https://opensource.org/licenses/IPA" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/IPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IPL-1.0.json", + "referenceNumber": 332, + "name": "IBM Public License v1.0", + "licenseId": "IPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/IPL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/ISC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ISC.json", + "referenceNumber": 488, + "name": "ISC License", + "licenseId": "ISC", + "seeAlso": [ + "https://www.isc.org/licenses/", + "https://www.isc.org/downloads/software-support-policy/isc-license/", + "https://opensource.org/licenses/ISC" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/ISC-Veillard.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ISC-Veillard.json", + "referenceNumber": 513, + "name": "ISC Veillard variant", + "licenseId": "ISC-Veillard", + "seeAlso": [ + "https://raw.githubusercontent.com/GNOME/libxml2/4c2e7c651f6c2f0d1a74f350cbda95f7df3e7017/hash.c", + "https://github.com/GNOME/libxml2/blob/master/dict.c", + "https://sourceforge.net/p/ctrio/git/ci/master/tree/README" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Jam.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Jam.json", + "referenceNumber": 108, + "name": "Jam License", + "licenseId": "Jam", + "seeAlso": [ + "https://www.boost.org/doc/libs/1_35_0/doc/html/jam.html", + "https://web.archive.org/web/20160330173339/https://swarm.workshop.perforce.com/files/guest/perforce_software/jam/src/README" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/JasPer-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/JasPer-2.0.json", + "referenceNumber": 487, + "name": "JasPer License", + "licenseId": "JasPer-2.0", + "seeAlso": [ + "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/JPL-image.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/JPL-image.json", + "referenceNumber": 363, + "name": "JPL Image Use Policy", + "licenseId": "JPL-image", + "seeAlso": [ + "https://www.jpl.nasa.gov/jpl-image-use-policy" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/JPNIC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/JPNIC.json", + "referenceNumber": 83, + "name": "Japan Network Information Center License", + "licenseId": "JPNIC", + "seeAlso": [ + "https://gitlab.isc.org/isc-projects/bind9/blob/master/COPYRIGHT#L366" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/JSON.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/JSON.json", + "referenceNumber": 65, + "name": "JSON License", + "licenseId": "JSON", + "seeAlso": [ + "http://www.json.org/license.html" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/Kastrup.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Kastrup.json", + "referenceNumber": 226, + "name": "Kastrup License", + "licenseId": "Kastrup", + "seeAlso": [ + "https://ctan.math.utah.edu/ctan/tex-archive/macros/generic/kastrup/binhex.dtx" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Kazlib.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Kazlib.json", + "referenceNumber": 232, + "name": "Kazlib License", + "licenseId": "Kazlib", + "seeAlso": [ + "http://git.savannah.gnu.org/cgit/kazlib.git/tree/except.c?id\u003d0062df360c2d17d57f6af19b0e444c51feb99036" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Knuth-CTAN.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Knuth-CTAN.json", + "referenceNumber": 290, + "name": "Knuth CTAN License", + "licenseId": "Knuth-CTAN", + "seeAlso": [ + "https://ctan.org/license/knuth" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LAL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LAL-1.2.json", + "referenceNumber": 165, + "name": "Licence Art Libre 1.2", + "licenseId": "LAL-1.2", + "seeAlso": [ + "http://artlibre.org/licence/lal/licence-art-libre-12/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LAL-1.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LAL-1.3.json", + "referenceNumber": 600, + "name": "Licence Art Libre 1.3", + "licenseId": "LAL-1.3", + "seeAlso": [ + "https://artlibre.org/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Latex2e.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Latex2e.json", + "referenceNumber": 439, + "name": "Latex2e License", + "licenseId": "Latex2e", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Latex2e" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Latex2e-translated-notice.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Latex2e-translated-notice.json", + "referenceNumber": 620, + "name": "Latex2e with translated notice permission", + "licenseId": "Latex2e-translated-notice", + "seeAlso": [ + "https://git.savannah.gnu.org/cgit/indent.git/tree/doc/indent.texi?id\u003da74c6b4ee49397cf330b333da1042bffa60ed14f#n74" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Leptonica.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Leptonica.json", + "referenceNumber": 103, + "name": "Leptonica License", + "licenseId": "Leptonica", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Leptonica" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0.json", + "referenceNumber": 353, + "name": "GNU Library General Public License v2 only", + "licenseId": "LGPL-2.0", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0+.json", + "referenceNumber": 62, + "name": "GNU Library General Public License v2 or later", + "licenseId": "LGPL-2.0+", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0-only.json", + "referenceNumber": 519, + "name": "GNU Library General Public License v2 only", + "licenseId": "LGPL-2.0-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0-or-later.json", + "referenceNumber": 366, + "name": "GNU Library General Public License v2 or later", + "licenseId": "LGPL-2.0-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.1.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1.json", + "referenceNumber": 656, + "name": "GNU Lesser General Public License v2.1 only", + "licenseId": "LGPL-2.1", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.1+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1+.json", + "referenceNumber": 64, + "name": "GNU Lesser General Public License v2.1 or later", + "licenseId": "LGPL-2.1+", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.1-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1-only.json", + "referenceNumber": 177, + "name": "GNU Lesser General Public License v2.1 only", + "licenseId": "LGPL-2.1-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.1-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1-or-later.json", + "referenceNumber": 24, + "name": "GNU Lesser General Public License v2.1 or later", + "licenseId": "LGPL-2.1-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-3.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0.json", + "referenceNumber": 578, + "name": "GNU Lesser General Public License v3.0 only", + "licenseId": "LGPL-3.0", + "seeAlso": [ + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-3.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0+.json", + "referenceNumber": 233, + "name": "GNU Lesser General Public License v3.0 or later", + "licenseId": "LGPL-3.0+", + "seeAlso": [ + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-3.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0-only.json", + "referenceNumber": 3, + "name": "GNU Lesser General Public License v3.0 only", + "licenseId": "LGPL-3.0-only", + "seeAlso": [ + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-3.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0-or-later.json", + "referenceNumber": 262, + "name": "GNU Lesser General Public License v3.0 or later", + "licenseId": "LGPL-3.0-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPLLR.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPLLR.json", + "referenceNumber": 477, + "name": "Lesser General Public License For Linguistic Resources", + "licenseId": "LGPLLR", + "seeAlso": [ + "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Libpng.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Libpng.json", + "referenceNumber": 186, + "name": "libpng License", + "licenseId": "Libpng", + "seeAlso": [ + "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/libpng-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/libpng-2.0.json", + "referenceNumber": 257, + "name": "PNG Reference Library version 2", + "licenseId": "libpng-2.0", + "seeAlso": [ + "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/libselinux-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/libselinux-1.0.json", + "referenceNumber": 556, + "name": "libselinux public domain notice", + "licenseId": "libselinux-1.0", + "seeAlso": [ + "https://github.com/SELinuxProject/selinux/blob/master/libselinux/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/libtiff.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/libtiff.json", + "referenceNumber": 392, + "name": "libtiff License", + "licenseId": "libtiff", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/libtiff" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/libutil-David-Nugent.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/libutil-David-Nugent.json", + "referenceNumber": 400, + "name": "libutil David Nugent License", + "licenseId": "libutil-David-Nugent", + "seeAlso": [ + "http://web.mit.edu/freebsd/head/lib/libutil/login_ok.3", + "https://cgit.freedesktop.org/libbsd/tree/man/setproctitle.3bsd" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LiLiQ-P-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LiLiQ-P-1.1.json", + "referenceNumber": 43, + "name": "Licence Libre du Québec – Permissive version 1.1", + "licenseId": "LiLiQ-P-1.1", + "seeAlso": [ + "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/", + "http://opensource.org/licenses/LiLiQ-P-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LiLiQ-R-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LiLiQ-R-1.1.json", + "referenceNumber": 74, + "name": "Licence Libre du Québec – Réciprocité version 1.1", + "licenseId": "LiLiQ-R-1.1", + "seeAlso": [ + "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/", + "http://opensource.org/licenses/LiLiQ-R-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LiLiQ-Rplus-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LiLiQ-Rplus-1.1.json", + "referenceNumber": 40, + "name": "Licence Libre du Québec – Réciprocité forte version 1.1", + "licenseId": "LiLiQ-Rplus-1.1", + "seeAlso": [ + "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/", + "http://opensource.org/licenses/LiLiQ-Rplus-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Linux-man-pages-1-para.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-1-para.json", + "referenceNumber": 339, + "name": "Linux man-pages - 1 paragraph", + "licenseId": "Linux-man-pages-1-para", + "seeAlso": [ + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/getcpu.2#n4" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Linux-man-pages-copyleft.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-copyleft.json", + "referenceNumber": 590, + "name": "Linux man-pages Copyleft", + "licenseId": "Linux-man-pages-copyleft", + "seeAlso": [ + "https://www.kernel.org/doc/man-pages/licenses.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Linux-man-pages-copyleft-2-para.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-copyleft-2-para.json", + "referenceNumber": 86, + "name": "Linux man-pages Copyleft - 2 paragraphs", + "licenseId": "Linux-man-pages-copyleft-2-para", + "seeAlso": [ + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/move_pages.2#n5", + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/migrate_pages.2#n8" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Linux-man-pages-copyleft-var.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-copyleft-var.json", + "referenceNumber": 337, + "name": "Linux man-pages Copyleft Variant", + "licenseId": "Linux-man-pages-copyleft-var", + "seeAlso": [ + "https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man2/set_mempolicy.2#n5" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Linux-OpenIB.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Linux-OpenIB.json", + "referenceNumber": 613, + "name": "Linux Kernel Variant of OpenIB.org license", + "licenseId": "Linux-OpenIB", + "seeAlso": [ + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LOOP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LOOP.json", + "referenceNumber": 607, + "name": "Common Lisp LOOP License", + "licenseId": "LOOP", + "seeAlso": [ + "https://gitlab.com/embeddable-common-lisp/ecl/-/blob/develop/src/lsp/loop.lsp", + "http://git.savannah.gnu.org/cgit/gcl.git/tree/gcl/lsp/gcl_loop.lsp?h\u003dVersion_2_6_13pre", + "https://sourceforge.net/p/sbcl/sbcl/ci/master/tree/src/code/loop.lisp", + "https://github.com/cl-adams/adams/blob/master/LICENSE.md", + "https://github.com/blakemcbride/eclipse-lisp/blob/master/lisp/loop.lisp", + "https://gitlab.common-lisp.net/cmucl/cmucl/-/blob/master/src/code/loop.lisp" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LPD-document.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPD-document.json", + "referenceNumber": 522, + "name": "LPD Documentation License", + "licenseId": "LPD-document", + "seeAlso": [ + "https://github.com/Cyan4973/xxHash/blob/dev/doc/xxhash_spec.md", + "https://www.ietf.org/rfc/rfc1952.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPL-1.0.json", + "referenceNumber": 196, + "name": "Lucent Public License Version 1.0", + "licenseId": "LPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/LPL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LPL-1.02.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPL-1.02.json", + "referenceNumber": 69, + "name": "Lucent Public License v1.02", + "licenseId": "LPL-1.02", + "seeAlso": [ + "http://plan9.bell-labs.com/plan9/license.html", + "https://opensource.org/licenses/LPL-1.02" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LPPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPPL-1.0.json", + "referenceNumber": 215, + "name": "LaTeX Project Public License v1.0", + "licenseId": "LPPL-1.0", + "seeAlso": [ + "http://www.latex-project.org/lppl/lppl-1-0.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LPPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPPL-1.1.json", + "referenceNumber": 114, + "name": "LaTeX Project Public License v1.1", + "licenseId": "LPPL-1.1", + "seeAlso": [ + "http://www.latex-project.org/lppl/lppl-1-1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LPPL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPPL-1.2.json", + "referenceNumber": 435, + "name": "LaTeX Project Public License v1.2", + "licenseId": "LPPL-1.2", + "seeAlso": [ + "http://www.latex-project.org/lppl/lppl-1-2.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LPPL-1.3a.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPPL-1.3a.json", + "referenceNumber": 18, + "name": "LaTeX Project Public License v1.3a", + "licenseId": "LPPL-1.3a", + "seeAlso": [ + "http://www.latex-project.org/lppl/lppl-1-3a.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LPPL-1.3c.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPPL-1.3c.json", + "referenceNumber": 240, + "name": "LaTeX Project Public License v1.3c", + "licenseId": "LPPL-1.3c", + "seeAlso": [ + "http://www.latex-project.org/lppl/lppl-1-3c.txt", + "https://opensource.org/licenses/LPPL-1.3c" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/lsof.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/lsof.json", + "referenceNumber": 605, + "name": "lsof License", + "licenseId": "lsof", + "seeAlso": [ + "https://github.com/lsof-org/lsof/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Lucida-Bitmap-Fonts.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Lucida-Bitmap-Fonts.json", + "referenceNumber": 399, + "name": "Lucida Bitmap Fonts License", + "licenseId": "Lucida-Bitmap-Fonts", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/font/bh-100dpi/-/blob/master/COPYING?ref_type\u003dheads" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LZMA-SDK-9.11-to-9.20.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LZMA-SDK-9.11-to-9.20.json", + "referenceNumber": 430, + "name": "LZMA SDK License (versions 9.11 to 9.20)", + "licenseId": "LZMA-SDK-9.11-to-9.20", + "seeAlso": [ + "https://www.7-zip.org/sdk.html", + "https://sourceforge.net/projects/sevenzip/files/LZMA%20SDK/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LZMA-SDK-9.22.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LZMA-SDK-9.22.json", + "referenceNumber": 244, + "name": "LZMA SDK License (versions 9.22 and beyond)", + "licenseId": "LZMA-SDK-9.22", + "seeAlso": [ + "https://www.7-zip.org/sdk.html", + "https://sourceforge.net/projects/sevenzip/files/LZMA%20SDK/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Mackerras-3-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Mackerras-3-Clause.json", + "referenceNumber": 59, + "name": "Mackerras 3-Clause License", + "licenseId": "Mackerras-3-Clause", + "seeAlso": [ + "https://github.com/ppp-project/ppp/blob/master/pppd/chap_ms.c#L6-L28" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Mackerras-3-Clause-acknowledgment.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Mackerras-3-Clause-acknowledgment.json", + "referenceNumber": 598, + "name": "Mackerras 3-Clause - acknowledgment variant", + "licenseId": "Mackerras-3-Clause-acknowledgment", + "seeAlso": [ + "https://github.com/ppp-project/ppp/blob/master/pppd/auth.c#L6-L28" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/magaz.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/magaz.json", + "referenceNumber": 516, + "name": "magaz License", + "licenseId": "magaz", + "seeAlso": [ + "https://mirrors.nic.cz/tex-archive/macros/latex/contrib/magaz/magaz.tex" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/mailprio.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/mailprio.json", + "referenceNumber": 179, + "name": "mailprio License", + "licenseId": "mailprio", + "seeAlso": [ + "https://fossies.org/linux/sendmail/contrib/mailprio" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MakeIndex.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MakeIndex.json", + "referenceNumber": 206, + "name": "MakeIndex License", + "licenseId": "MakeIndex", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/MakeIndex" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Martin-Birgmeier.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Martin-Birgmeier.json", + "referenceNumber": 535, + "name": "Martin Birgmeier License", + "licenseId": "Martin-Birgmeier", + "seeAlso": [ + "https://github.com/Perl/perl5/blob/blead/util.c#L6136" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/McPhee-slideshow.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/McPhee-slideshow.json", + "referenceNumber": 492, + "name": "McPhee Slideshow License", + "licenseId": "McPhee-slideshow", + "seeAlso": [ + "https://mirror.las.iastate.edu/tex-archive/graphics/metapost/contrib/macros/slideshow/slideshow.mp" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/metamail.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/metamail.json", + "referenceNumber": 437, + "name": "metamail License", + "licenseId": "metamail", + "seeAlso": [ + "https://github.com/Dual-Life/mime-base64/blob/master/Base64.xs#L12" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Minpack.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Minpack.json", + "referenceNumber": 512, + "name": "Minpack License", + "licenseId": "Minpack", + "seeAlso": [ + "http://www.netlib.org/minpack/disclaimer", + "https://gitlab.com/libeigen/eigen/-/blob/master/COPYING.MINPACK" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MirOS.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MirOS.json", + "referenceNumber": 183, + "name": "The MirOS Licence", + "licenseId": "MirOS", + "seeAlso": [ + "https://opensource.org/licenses/MirOS" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/MIT.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT.json", + "referenceNumber": 608, + "name": "MIT License", + "licenseId": "MIT", + "seeAlso": [ + "https://opensource.org/license/mit/" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/MIT-0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-0.json", + "referenceNumber": 395, + "name": "MIT No Attribution", + "licenseId": "MIT-0", + "seeAlso": [ + "https://github.com/aws/mit-0", + "https://romanrm.net/mit-zero", + "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/MIT-advertising.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-advertising.json", + "referenceNumber": 293, + "name": "Enlightenment License (e16)", + "licenseId": "MIT-advertising", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-CMU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-CMU.json", + "referenceNumber": 575, + "name": "CMU License", + "licenseId": "MIT-CMU", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style", + "https://github.com/python-pillow/Pillow/blob/fffb426092c8db24a5f4b6df243a8a3c01fb63cd/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-enna.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-enna.json", + "referenceNumber": 638, + "name": "enna License", + "licenseId": "MIT-enna", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/MIT#enna" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-feh.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-feh.json", + "referenceNumber": 53, + "name": "feh License", + "licenseId": "MIT-feh", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/MIT#feh" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-Festival.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-Festival.json", + "referenceNumber": 317, + "name": "MIT Festival Variant", + "licenseId": "MIT-Festival", + "seeAlso": [ + "https://github.com/festvox/flite/blob/master/COPYING", + "https://github.com/festvox/speech_tools/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-Khronos-old.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-Khronos-old.json", + "referenceNumber": 249, + "name": "MIT Khronos - old variant", + "licenseId": "MIT-Khronos-old", + "seeAlso": [ + "https://github.com/KhronosGroup/SPIRV-Cross/blob/main/LICENSES/LicenseRef-KhronosFreeUse.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-Modern-Variant.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-Modern-Variant.json", + "referenceNumber": 424, + "name": "MIT License Modern Variant", + "licenseId": "MIT-Modern-Variant", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:MIT#Modern_Variants", + "https://ptolemy.berkeley.edu/copyright.htm", + "https://pirlwww.lpl.arizona.edu/resources/guide/software/PerlTk/Tixlic.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/MIT-open-group.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-open-group.json", + "referenceNumber": 283, + "name": "MIT Open Group variant", + "licenseId": "MIT-open-group", + "seeAlso": [ + "https://gitlab.freedesktop.org/xorg/app/iceauth/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/app/xvinfo/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/app/xsetroot/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/app/xauth/-/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-testregex.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-testregex.json", + "referenceNumber": 427, + "name": "MIT testregex Variant", + "licenseId": "MIT-testregex", + "seeAlso": [ + "https://github.com/dotnet/runtime/blob/55e1ac7c07df62c4108d4acedf78f77574470ce5/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/AttRegexTests.cs#L12-L28" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MIT-Wu.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-Wu.json", + "referenceNumber": 459, + "name": "MIT Tom Wu Variant", + "licenseId": "MIT-Wu", + "seeAlso": [ + "https://github.com/chromium/octane/blob/master/crypto.js" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MITNFA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MITNFA.json", + "referenceNumber": 157, + "name": "MIT +no-false-attribs license", + "licenseId": "MITNFA", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/MITNFA" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MMIXware.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MMIXware.json", + "referenceNumber": 474, + "name": "MMIXware License", + "licenseId": "MMIXware", + "seeAlso": [ + "https://gitlab.lrz.de/mmix/mmixware/-/blob/master/boilerplate.w" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Motosoto.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Motosoto.json", + "referenceNumber": 627, + "name": "Motosoto License", + "licenseId": "Motosoto", + "seeAlso": [ + "https://opensource.org/licenses/Motosoto" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/MPEG-SSG.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MPEG-SSG.json", + "referenceNumber": 417, + "name": "MPEG Software Simulation", + "licenseId": "MPEG-SSG", + "seeAlso": [ + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/ppm/ppmtompeg/jrevdct.c#l1189" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/mpi-permissive.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/mpi-permissive.json", + "referenceNumber": 80, + "name": "mpi Permissive License", + "licenseId": "mpi-permissive", + "seeAlso": [ + "https://sources.debian.org/src/openmpi/4.1.0-10/ompi/debuggers/msgq_interface.h/?hl\u003d19#L19" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/mpich2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/mpich2.json", + "referenceNumber": 482, + "name": "mpich2 License", + "licenseId": "mpich2", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/MIT" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MPL-1.0.json", + "referenceNumber": 28, + "name": "Mozilla Public License 1.0", + "licenseId": "MPL-1.0", + "seeAlso": [ + "http://www.mozilla.org/MPL/MPL-1.0.html", + "https://opensource.org/licenses/MPL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/MPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MPL-1.1.json", + "referenceNumber": 619, + "name": "Mozilla Public License 1.1", + "licenseId": "MPL-1.1", + "seeAlso": [ + "http://www.mozilla.org/MPL/MPL-1.1.html", + "https://opensource.org/licenses/MPL-1.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/MPL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MPL-2.0.json", + "referenceNumber": 263, + "name": "Mozilla Public License 2.0", + "licenseId": "MPL-2.0", + "seeAlso": [ + "https://www.mozilla.org/MPL/2.0/", + "https://opensource.org/licenses/MPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json", + "referenceNumber": 455, + "name": "Mozilla Public License 2.0 (no copyleft exception)", + "licenseId": "MPL-2.0-no-copyleft-exception", + "seeAlso": [ + "https://www.mozilla.org/MPL/2.0/", + "https://opensource.org/licenses/MPL-2.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/mplus.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/mplus.json", + "referenceNumber": 541, + "name": "mplus Font License", + "licenseId": "mplus", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:Mplus?rd\u003dLicensing/mplus" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MS-LPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MS-LPL.json", + "referenceNumber": 528, + "name": "Microsoft Limited Public License", + "licenseId": "MS-LPL", + "seeAlso": [ + "https://www.openhub.net/licenses/mslpl", + "https://github.com/gabegundy/atlserver/blob/master/License.txt", + "https://en.wikipedia.org/wiki/Shared_Source_Initiative#Microsoft_Limited_Public_License_(Ms-LPL)" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MS-PL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MS-PL.json", + "referenceNumber": 499, + "name": "Microsoft Public License", + "licenseId": "MS-PL", + "seeAlso": [ + "http://www.microsoft.com/opensource/licenses.mspx", + "https://opensource.org/licenses/MS-PL" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/MS-RL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MS-RL.json", + "referenceNumber": 343, + "name": "Microsoft Reciprocal License", + "licenseId": "MS-RL", + "seeAlso": [ + "http://www.microsoft.com/opensource/licenses.mspx", + "https://opensource.org/licenses/MS-RL" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/MTLL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MTLL.json", + "referenceNumber": 137, + "name": "Matrix Template Library License", + "licenseId": "MTLL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MulanPSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MulanPSL-1.0.json", + "referenceNumber": 107, + "name": "Mulan Permissive Software License, Version 1", + "licenseId": "MulanPSL-1.0", + "seeAlso": [ + "https://license.coscl.org.cn/MulanPSL/", + "https://github.com/yuwenlong/longphp/blob/25dfb70cc2a466dc4bb55ba30901cbce08d164b5/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MulanPSL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MulanPSL-2.0.json", + "referenceNumber": 490, + "name": "Mulan Permissive Software License, Version 2", + "licenseId": "MulanPSL-2.0", + "seeAlso": [ + "https://license.coscl.org.cn/MulanPSL2" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Multics.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Multics.json", + "referenceNumber": 573, + "name": "Multics License", + "licenseId": "Multics", + "seeAlso": [ + "https://opensource.org/licenses/Multics" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Mup.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Mup.json", + "referenceNumber": 440, + "name": "Mup License", + "licenseId": "Mup", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Mup" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NAIST-2003.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NAIST-2003.json", + "referenceNumber": 104, + "name": "Nara Institute of Science and Technology License (2003)", + "licenseId": "NAIST-2003", + "seeAlso": [ + "https://enterprise.dejacode.com/licenses/public/naist-2003/#license-text", + "https://github.com/nodejs/node/blob/4a19cc8947b1bba2b2d27816ec3d0edf9b28e503/LICENSE#L343" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NASA-1.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NASA-1.3.json", + "referenceNumber": 127, + "name": "NASA Open Source Agreement 1.3", + "licenseId": "NASA-1.3", + "seeAlso": [ + "http://ti.arc.nasa.gov/opensource/nosa/", + "https://opensource.org/licenses/NASA-1.3" + ], + "isOsiApproved": true, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/Naumen.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Naumen.json", + "referenceNumber": 128, + "name": "Naumen Public License", + "licenseId": "Naumen", + "seeAlso": [ + "https://opensource.org/licenses/Naumen" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/NBPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NBPL-1.0.json", + "referenceNumber": 41, + "name": "Net Boolean Public License v1", + "licenseId": "NBPL-1.0", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NCBI-PD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NCBI-PD.json", + "referenceNumber": 362, + "name": "NCBI Public Domain Notice", + "licenseId": "NCBI-PD", + "seeAlso": [ + "https://github.com/ncbi/sra-tools/blob/e8e5b6af4edc460156ad9ce5902d0779cffbf685/LICENSE", + "https://github.com/ncbi/datasets/blob/0ea4cd16b61e5b799d9cc55aecfa016d6c9bd2bf/LICENSE.md", + "https://github.com/ncbi/gprobe/blob/de64d30fee8b4c4013094d7d3139ea89b5dd1ace/LICENSE", + "https://github.com/ncbi/egapx/blob/08930b9dec0c69b2d1a05e5153c7b95ef0a3eb0f/LICENSE", + "https://github.com/ncbi/datasets/blob/master/LICENSE.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NCGL-UK-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NCGL-UK-2.0.json", + "referenceNumber": 320, + "name": "Non-Commercial Government Licence", + "licenseId": "NCGL-UK-2.0", + "seeAlso": [ + "http://www.nationalarchives.gov.uk/doc/non-commercial-government-licence/version/2/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NCL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NCL.json", + "referenceNumber": 153, + "name": "NCL Source Code License", + "licenseId": "NCL", + "seeAlso": [ + "https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/src/modules/module-filter-chain/pffft.c?ref_type\u003dheads#L1-52" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NCSA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NCSA.json", + "referenceNumber": 557, + "name": "University of Illinois/NCSA Open Source License", + "licenseId": "NCSA", + "seeAlso": [ + "http://otm.illinois.edu/uiuc_openSource", + "https://opensource.org/licenses/NCSA" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Net-SNMP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Net-SNMP.json", + "referenceNumber": 234, + "name": "Net-SNMP License", + "licenseId": "Net-SNMP", + "seeAlso": [ + "http://net-snmp.sourceforge.net/about/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NetCDF.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NetCDF.json", + "referenceNumber": 503, + "name": "NetCDF license", + "licenseId": "NetCDF", + "seeAlso": [ + "http://www.unidata.ucar.edu/software/netcdf/copyright.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Newsletr.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Newsletr.json", + "referenceNumber": 412, + "name": "Newsletr License", + "licenseId": "Newsletr", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Newsletr" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NGPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NGPL.json", + "referenceNumber": 275, + "name": "Nethack General Public License", + "licenseId": "NGPL", + "seeAlso": [ + "https://opensource.org/licenses/NGPL" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/NICTA-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NICTA-1.0.json", + "referenceNumber": 311, + "name": "NICTA Public Software License, Version 1.0", + "licenseId": "NICTA-1.0", + "seeAlso": [ + "https://opensource.apple.com/source/mDNSResponder/mDNSResponder-320.10/mDNSPosix/nss_ReadMe.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NIST-PD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NIST-PD.json", + "referenceNumber": 309, + "name": "NIST Public Domain Notice", + "licenseId": "NIST-PD", + "seeAlso": [ + "https://github.com/tcheneau/simpleRPL/blob/e645e69e38dd4e3ccfeceb2db8cba05b7c2e0cd3/LICENSE.txt", + "https://github.com/tcheneau/Routing/blob/f09f46fcfe636107f22f2c98348188a65a135d98/README.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NIST-PD-fallback.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NIST-PD-fallback.json", + "referenceNumber": 34, + "name": "NIST Public Domain Notice with license fallback", + "licenseId": "NIST-PD-fallback", + "seeAlso": [ + "https://github.com/usnistgov/jsip/blob/59700e6926cbe96c5cdae897d9a7d2656b42abe3/LICENSE", + "https://github.com/usnistgov/fipy/blob/86aaa5c2ba2c6f1be19593c5986071cf6568cc34/LICENSE.rst" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NIST-Software.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NIST-Software.json", + "referenceNumber": 76, + "name": "NIST Software License", + "licenseId": "NIST-Software", + "seeAlso": [ + "https://github.com/open-quantum-safe/liboqs/blob/40b01fdbb270f8614fde30e65d30e9da18c02393/src/common/rand/rand_nist.c#L1-L15" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NLOD-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NLOD-1.0.json", + "referenceNumber": 565, + "name": "Norwegian Licence for Open Government Data (NLOD) 1.0", + "licenseId": "NLOD-1.0", + "seeAlso": [ + "http://data.norge.no/nlod/en/1.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NLOD-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NLOD-2.0.json", + "referenceNumber": 483, + "name": "Norwegian Licence for Open Government Data (NLOD) 2.0", + "licenseId": "NLOD-2.0", + "seeAlso": [ + "http://data.norge.no/nlod/en/2.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NLPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NLPL.json", + "referenceNumber": 71, + "name": "No Limit Public License", + "licenseId": "NLPL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/NLPL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Nokia.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Nokia.json", + "referenceNumber": 44, + "name": "Nokia Open Source License", + "licenseId": "Nokia", + "seeAlso": [ + "https://opensource.org/licenses/nokia" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/NOSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NOSL.json", + "referenceNumber": 126, + "name": "Netizen Open Source License", + "licenseId": "NOSL", + "seeAlso": [ + "http://bits.netizen.com.au/licenses/NOSL/nosl.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Noweb.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Noweb.json", + "referenceNumber": 534, + "name": "Noweb License", + "licenseId": "Noweb", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Noweb" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NPL-1.0.json", + "referenceNumber": 346, + "name": "Netscape Public License v1.0", + "licenseId": "NPL-1.0", + "seeAlso": [ + "http://www.mozilla.org/MPL/NPL/1.0/" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/NPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NPL-1.1.json", + "referenceNumber": 418, + "name": "Netscape Public License v1.1", + "licenseId": "NPL-1.1", + "seeAlso": [ + "http://www.mozilla.org/MPL/NPL/1.1/" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/NPOSL-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NPOSL-3.0.json", + "referenceNumber": 579, + "name": "Non-Profit Open Software License 3.0", + "licenseId": "NPOSL-3.0", + "seeAlso": [ + "https://opensource.org/licenses/NOSL3.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/NRL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NRL.json", + "referenceNumber": 230, + "name": "NRL License", + "licenseId": "NRL", + "seeAlso": [ + "http://web.mit.edu/network/isakmp/nrllicense.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NTP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NTP.json", + "referenceNumber": 547, + "name": "NTP License", + "licenseId": "NTP", + "seeAlso": [ + "https://opensource.org/licenses/NTP" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/NTP-0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NTP-0.json", + "referenceNumber": 460, + "name": "NTP No Attribution", + "licenseId": "NTP-0", + "seeAlso": [ + "https://github.com/tytso/e2fsprogs/blob/master/lib/et/et_name.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Nunit.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/Nunit.json", + "referenceNumber": 634, + "name": "Nunit License", + "licenseId": "Nunit", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Nunit" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/O-UDA-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/O-UDA-1.0.json", + "referenceNumber": 191, + "name": "Open Use of Data Agreement v1.0", + "licenseId": "O-UDA-1.0", + "seeAlso": [ + "https://github.com/microsoft/Open-Use-of-Data-Agreement/blob/v1.0/O-UDA-1.0.md", + "https://cdla.dev/open-use-of-data-agreement-v1-0/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OAR.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OAR.json", + "referenceNumber": 4, + "name": "OAR License", + "licenseId": "OAR", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/string/strsignal.c;hb\u003dHEAD#l35" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OCCT-PL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OCCT-PL.json", + "referenceNumber": 596, + "name": "Open CASCADE Technology Public License", + "licenseId": "OCCT-PL", + "seeAlso": [ + "http://www.opencascade.com/content/occt-public-license" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OCLC-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OCLC-2.0.json", + "referenceNumber": 308, + "name": "OCLC Research Public License 2.0", + "licenseId": "OCLC-2.0", + "seeAlso": [ + "http://www.oclc.org/research/activities/software/license/v2final.htm", + "https://opensource.org/licenses/OCLC-2.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/ODbL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ODbL-1.0.json", + "referenceNumber": 243, + "name": "Open Data Commons Open Database License v1.0", + "licenseId": "ODbL-1.0", + "seeAlso": [ + "http://www.opendatacommons.org/licenses/odbl/1.0/", + "https://opendatacommons.org/licenses/odbl/1-0/" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/ODC-By-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ODC-By-1.0.json", + "referenceNumber": 7, + "name": "Open Data Commons Attribution License v1.0", + "licenseId": "ODC-By-1.0", + "seeAlso": [ + "https://opendatacommons.org/licenses/by/1.0/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OFFIS.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFFIS.json", + "referenceNumber": 238, + "name": "OFFIS License", + "licenseId": "OFFIS", + "seeAlso": [ + "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/dicom/README" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OFL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFL-1.0.json", + "referenceNumber": 475, + "name": "SIL Open Font License 1.0", + "licenseId": "OFL-1.0", + "seeAlso": [ + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OFL-1.0-no-RFN.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFL-1.0-no-RFN.json", + "referenceNumber": 23, + "name": "SIL Open Font License 1.0 with no Reserved Font Name", + "licenseId": "OFL-1.0-no-RFN", + "seeAlso": [ + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OFL-1.0-RFN.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFL-1.0-RFN.json", + "referenceNumber": 11, + "name": "SIL Open Font License 1.0 with Reserved Font Name", + "licenseId": "OFL-1.0-RFN", + "seeAlso": [ + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OFL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFL-1.1.json", + "referenceNumber": 248, + "name": "SIL Open Font License 1.1", + "licenseId": "OFL-1.1", + "seeAlso": [ + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", + "https://opensource.org/licenses/OFL-1.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OFL-1.1-no-RFN.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFL-1.1-no-RFN.json", + "referenceNumber": 550, + "name": "SIL Open Font License 1.1 with no Reserved Font Name", + "licenseId": "OFL-1.1-no-RFN", + "seeAlso": [ + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", + "https://opensource.org/licenses/OFL-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/OFL-1.1-RFN.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFL-1.1-RFN.json", + "referenceNumber": 507, + "name": "SIL Open Font License 1.1 with Reserved Font Name", + "licenseId": "OFL-1.1-RFN", + "seeAlso": [ + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", + "https://opensource.org/licenses/OFL-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/OGC-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OGC-1.0.json", + "referenceNumber": 166, + "name": "OGC Software License, Version 1.0", + "licenseId": "OGC-1.0", + "seeAlso": [ + "https://www.ogc.org/ogc/software/1.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OGDL-Taiwan-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OGDL-Taiwan-1.0.json", + "referenceNumber": 468, + "name": "Taiwan Open Government Data License, version 1.0", + "licenseId": "OGDL-Taiwan-1.0", + "seeAlso": [ + "https://data.gov.tw/license" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OGL-Canada-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OGL-Canada-2.0.json", + "referenceNumber": 464, + "name": "Open Government Licence - Canada", + "licenseId": "OGL-Canada-2.0", + "seeAlso": [ + "https://open.canada.ca/en/open-government-licence-canada" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OGL-UK-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OGL-UK-1.0.json", + "referenceNumber": 489, + "name": "Open Government Licence v1.0", + "licenseId": "OGL-UK-1.0", + "seeAlso": [ + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OGL-UK-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OGL-UK-2.0.json", + "referenceNumber": 467, + "name": "Open Government Licence v2.0", + "licenseId": "OGL-UK-2.0", + "seeAlso": [ + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/2/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OGL-UK-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OGL-UK-3.0.json", + "referenceNumber": 151, + "name": "Open Government Licence v3.0", + "licenseId": "OGL-UK-3.0", + "seeAlso": [ + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OGTSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OGTSL.json", + "referenceNumber": 367, + "name": "Open Group Test Suite License", + "licenseId": "OGTSL", + "seeAlso": [ + "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt", + "https://opensource.org/licenses/OGTSL" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/OLDAP-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.1.json", + "referenceNumber": 180, + "name": "Open LDAP Public License v1.1", + "licenseId": "OLDAP-1.1", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.2.json", + "referenceNumber": 229, + "name": "Open LDAP Public License v1.2", + "licenseId": "OLDAP-1.2", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d42b0383c50c299977b5893ee695cf4e486fb0dc7" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-1.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.3.json", + "referenceNumber": 224, + "name": "Open LDAP Public License v1.3", + "licenseId": "OLDAP-1.3", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-1.4.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.4.json", + "referenceNumber": 255, + "name": "Open LDAP Public License v1.4", + "licenseId": "OLDAP-1.4", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.0.json", + "referenceNumber": 208, + "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", + "licenseId": "OLDAP-2.0", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.0.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.0.1.json", + "referenceNumber": 79, + "name": "Open LDAP Public License v2.0.1", + "licenseId": "OLDAP-2.0.1", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.1.json", + "referenceNumber": 360, + "name": "Open LDAP Public License v2.1", + "licenseId": "OLDAP-2.1", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.json", + "referenceNumber": 316, + "name": "Open LDAP Public License v2.2", + "licenseId": "OLDAP-2.2", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.1.json", + "referenceNumber": 426, + "name": "Open LDAP Public License v2.2.1", + "licenseId": "OLDAP-2.2.1", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.2.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.2.json", + "referenceNumber": 384, + "name": "Open LDAP Public License 2.2.2", + "licenseId": "OLDAP-2.2.2", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.3.json", + "referenceNumber": 381, + "name": "Open LDAP Public License v2.3", + "licenseId": "OLDAP-2.3", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.4.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.4.json", + "referenceNumber": 93, + "name": "Open LDAP Public License v2.4", + "licenseId": "OLDAP-2.4", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.5.json", + "referenceNumber": 651, + "name": "Open LDAP Public License v2.5", + "licenseId": "OLDAP-2.5", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.6.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.6.json", + "referenceNumber": 568, + "name": "Open LDAP Public License v2.6", + "licenseId": "OLDAP-2.6", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.7.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.7.json", + "referenceNumber": 220, + "name": "Open LDAP Public License v2.7", + "licenseId": "OLDAP-2.7", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.8.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.8.json", + "referenceNumber": 5, + "name": "Open LDAP Public License v2.8", + "licenseId": "OLDAP-2.8", + "seeAlso": [ + "http://www.openldap.org/software/release/license.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/OLFL-1.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLFL-1.3.json", + "referenceNumber": 142, + "name": "Open Logistics Foundation License Version 1.3", + "licenseId": "OLFL-1.3", + "seeAlso": [ + "https://openlogisticsfoundation.org/licenses/", + "https://opensource.org/license/olfl-1-3/" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/OML.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OML.json", + "referenceNumber": 375, + "name": "Open Market License", + "licenseId": "OML", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Open_Market_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OpenPBS-2.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OpenPBS-2.3.json", + "referenceNumber": 314, + "name": "OpenPBS v2.3 Software License", + "licenseId": "OpenPBS-2.3", + "seeAlso": [ + "https://github.com/adaptivecomputing/torque/blob/master/PBS_License.txt", + "https://www.mcs.anl.gov/research/projects/openpbs/PBS_License.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OpenSSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OpenSSL.json", + "referenceNumber": 303, + "name": "OpenSSL License", + "licenseId": "OpenSSL", + "seeAlso": [ + "http://www.openssl.org/source/license.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OpenSSL-standalone.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OpenSSL-standalone.json", + "referenceNumber": 602, + "name": "OpenSSL License - standalone", + "licenseId": "OpenSSL-standalone", + "seeAlso": [ + "https://library.netapp.com/ecm/ecm_download_file/ECMP1196395", + "https://hstechdocs.helpsystems.com/manuals/globalscape/archive/cuteftp6/open_ssl_license_agreement.htm" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OpenVision.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OpenVision.json", + "referenceNumber": 588, + "name": "OpenVision License", + "licenseId": "OpenVision", + "seeAlso": [ + "https://github.com/krb5/krb5/blob/krb5-1.21.2-final/NOTICE#L66-L98", + "https://web.mit.edu/kerberos/krb5-1.21/doc/mitK5license.html", + "https://fedoraproject.org/wiki/Licensing:MIT#OpenVision_Variant" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OPL-1.0.json", + "referenceNumber": 91, + "name": "Open Public License v1.0", + "licenseId": "OPL-1.0", + "seeAlso": [ + "http://old.koalateam.com/jackaroo/OPL_1_0.TXT", + "https://fedoraproject.org/wiki/Licensing/Open_Public_License" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/OPL-UK-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OPL-UK-3.0.json", + "referenceNumber": 480, + "name": "United Kingdom Open Parliament Licence v3.0", + "licenseId": "OPL-UK-3.0", + "seeAlso": [ + "https://www.parliament.uk/site-information/copyright-parliament/open-parliament-licence/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OPUBL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OPUBL-1.0.json", + "referenceNumber": 329, + "name": "Open Publication License v1.0", + "licenseId": "OPUBL-1.0", + "seeAlso": [ + "http://opencontent.org/openpub/", + "https://www.debian.org/opl", + "https://www.ctan.org/license/opl" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OSET-PL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSET-PL-2.1.json", + "referenceNumber": 517, + "name": "OSET Public License version 2.1", + "licenseId": "OSET-PL-2.1", + "seeAlso": [ + "http://www.osetfoundation.org/public-license", + "https://opensource.org/licenses/OPL-2.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/OSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSL-1.0.json", + "referenceNumber": 162, + "name": "Open Software License 1.0", + "licenseId": "OSL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/OSL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OSL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSL-1.1.json", + "referenceNumber": 586, + "name": "Open Software License 1.1", + "licenseId": "OSL-1.1", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/OSL1.1" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OSL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSL-2.0.json", + "referenceNumber": 531, + "name": "Open Software License 2.0", + "licenseId": "OSL-2.0", + "seeAlso": [ + "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OSL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSL-2.1.json", + "referenceNumber": 138, + "name": "Open Software License 2.1", + "licenseId": "OSL-2.1", + "seeAlso": [ + "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm", + "https://opensource.org/licenses/OSL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OSL-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSL-3.0.json", + "referenceNumber": 300, + "name": "Open Software License 3.0", + "licenseId": "OSL-3.0", + "seeAlso": [ + "https://web.archive.org/web/20120101081418/http://rosenlaw.com:80/OSL3.0.htm", + "https://opensource.org/licenses/OSL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/PADL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PADL.json", + "referenceNumber": 113, + "name": "PADL License", + "licenseId": "PADL", + "seeAlso": [ + "https://git.openldap.org/openldap/openldap/-/blob/master/libraries/libldap/os-local.c?ref_type\u003dheads#L19-23" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Parity-6.0.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Parity-6.0.0.json", + "referenceNumber": 246, + "name": "The Parity Public License 6.0.0", + "licenseId": "Parity-6.0.0", + "seeAlso": [ + "https://paritylicense.com/versions/6.0.0.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Parity-7.0.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Parity-7.0.0.json", + "referenceNumber": 212, + "name": "The Parity Public License 7.0.0", + "licenseId": "Parity-7.0.0", + "seeAlso": [ + "https://paritylicense.com/versions/7.0.0.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/PDDL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PDDL-1.0.json", + "referenceNumber": 493, + "name": "Open Data Commons Public Domain Dedication \u0026 License 1.0", + "licenseId": "PDDL-1.0", + "seeAlso": [ + "http://opendatacommons.org/licenses/pddl/1.0/", + "https://opendatacommons.org/licenses/pddl/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/PHP-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PHP-3.0.json", + "referenceNumber": 584, + "name": "PHP License v3.0", + "licenseId": "PHP-3.0", + "seeAlso": [ + "http://www.php.net/license/3_0.txt", + "https://opensource.org/licenses/PHP-3.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/PHP-3.01.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PHP-3.01.json", + "referenceNumber": 538, + "name": "PHP License v3.01", + "licenseId": "PHP-3.01", + "seeAlso": [ + "http://www.php.net/license/3_01.txt" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Pixar.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Pixar.json", + "referenceNumber": 204, + "name": "Pixar License", + "licenseId": "Pixar", + "seeAlso": [ + "https://github.com/PixarAnimationStudios/OpenSubdiv/raw/v3_5_0/LICENSE.txt", + "https://graphics.pixar.com/opensubdiv/docs/license.html", + "https://github.com/PixarAnimationStudios/OpenSubdiv/blob/v3_5_0/opensubdiv/version.cpp#L2-L22" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/pkgconf.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/pkgconf.json", + "referenceNumber": 389, + "name": "pkgconf License", + "licenseId": "pkgconf", + "seeAlso": [ + "https://github.com/pkgconf/pkgconf/blob/master/cli/main.c#L8" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Plexus.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Plexus.json", + "referenceNumber": 141, + "name": "Plexus Classworlds License", + "licenseId": "Plexus", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/pnmstitch.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/pnmstitch.json", + "referenceNumber": 158, + "name": "pnmstitch License", + "licenseId": "pnmstitch", + "seeAlso": [ + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/editor/pnmstitch.c#l2" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.json", + "referenceNumber": 54, + "name": "PolyForm Noncommercial License 1.0.0", + "licenseId": "PolyForm-Noncommercial-1.0.0", + "seeAlso": [ + "https://polyformproject.org/licenses/noncommercial/1.0.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/PolyForm-Small-Business-1.0.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PolyForm-Small-Business-1.0.0.json", + "referenceNumber": 594, + "name": "PolyForm Small Business License 1.0.0", + "licenseId": "PolyForm-Small-Business-1.0.0", + "seeAlso": [ + "https://polyformproject.org/licenses/small-business/1.0.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/PostgreSQL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PostgreSQL.json", + "referenceNumber": 643, + "name": "PostgreSQL License", + "licenseId": "PostgreSQL", + "seeAlso": [ + "http://www.postgresql.org/about/licence", + "https://opensource.org/licenses/PostgreSQL" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/PPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PPL.json", + "referenceNumber": 580, + "name": "Peer Production License", + "licenseId": "PPL", + "seeAlso": [ + "https://wiki.p2pfoundation.net/Peer_Production_License", + "http://www.networkcultures.org/_uploads/%233notebook_telekommunist.pdf" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/PSF-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PSF-2.0.json", + "referenceNumber": 55, + "name": "Python Software Foundation License 2.0", + "licenseId": "PSF-2.0", + "seeAlso": [ + "https://opensource.org/licenses/Python-2.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/psfrag.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/psfrag.json", + "referenceNumber": 555, + "name": "psfrag License", + "licenseId": "psfrag", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/psfrag" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/psutils.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/psutils.json", + "referenceNumber": 260, + "name": "psutils License", + "licenseId": "psutils", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/psutils" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Python-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Python-2.0.json", + "referenceNumber": 285, + "name": "Python License 2.0", + "licenseId": "Python-2.0", + "seeAlso": [ + "https://opensource.org/licenses/Python-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Python-2.0.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Python-2.0.1.json", + "referenceNumber": 201, + "name": "Python License 2.0.1", + "licenseId": "Python-2.0.1", + "seeAlso": [ + "https://www.python.org/download/releases/2.0.1/license/", + "https://docs.python.org/3/license.html", + "https://github.com/python/cpython/blob/main/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/python-ldap.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/python-ldap.json", + "referenceNumber": 446, + "name": "Python ldap License", + "licenseId": "python-ldap", + "seeAlso": [ + "https://github.com/python-ldap/python-ldap/blob/main/LICENCE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Qhull.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Qhull.json", + "referenceNumber": 326, + "name": "Qhull License", + "licenseId": "Qhull", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Qhull" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/QPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/QPL-1.0.json", + "referenceNumber": 413, + "name": "Q Public License 1.0", + "licenseId": "QPL-1.0", + "seeAlso": [ + "http://doc.qt.nokia.com/3.3/license.html", + "https://opensource.org/licenses/QPL-1.0", + "https://doc.qt.io/archives/3.3/license.html" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/QPL-1.0-INRIA-2004.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/QPL-1.0-INRIA-2004.json", + "referenceNumber": 486, + "name": "Q Public License 1.0 - INRIA 2004 variant", + "licenseId": "QPL-1.0-INRIA-2004", + "seeAlso": [ + "https://github.com/maranget/hevea/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/radvd.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/radvd.json", + "referenceNumber": 433, + "name": "radvd License", + "licenseId": "radvd", + "seeAlso": [ + "https://github.com/radvd-project/radvd/blob/master/COPYRIGHT" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Rdisc.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Rdisc.json", + "referenceNumber": 50, + "name": "Rdisc License", + "licenseId": "Rdisc", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Rdisc_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/RHeCos-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/RHeCos-1.1.json", + "referenceNumber": 99, + "name": "Red Hat eCos Public License v1.1", + "licenseId": "RHeCos-1.1", + "seeAlso": [ + "http://ecos.sourceware.org/old-license.html" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/RPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/RPL-1.1.json", + "referenceNumber": 205, + "name": "Reciprocal Public License 1.1", + "licenseId": "RPL-1.1", + "seeAlso": [ + "https://opensource.org/licenses/RPL-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/RPL-1.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/RPL-1.5.json", + "referenceNumber": 52, + "name": "Reciprocal Public License 1.5", + "licenseId": "RPL-1.5", + "seeAlso": [ + "https://opensource.org/licenses/RPL-1.5" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/RPSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/RPSL-1.0.json", + "referenceNumber": 637, + "name": "RealNetworks Public Source License v1.0", + "licenseId": "RPSL-1.0", + "seeAlso": [ + "https://helixcommunity.org/content/rpsl", + "https://opensource.org/licenses/RPSL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/RSA-MD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/RSA-MD.json", + "referenceNumber": 496, + "name": "RSA Message-Digest License", + "licenseId": "RSA-MD", + "seeAlso": [ + "http://www.faqs.org/rfcs/rfc1321.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/RSCPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/RSCPL.json", + "referenceNumber": 235, + "name": "Ricoh Source Code Public License", + "licenseId": "RSCPL", + "seeAlso": [ + "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml", + "https://opensource.org/licenses/RSCPL" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Ruby.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Ruby.json", + "referenceNumber": 223, + "name": "Ruby License", + "licenseId": "Ruby", + "seeAlso": [ + "https://www.ruby-lang.org/en/about/license.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/SAX-PD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SAX-PD.json", + "referenceNumber": 301, + "name": "Sax Public Domain Notice", + "licenseId": "SAX-PD", + "seeAlso": [ + "http://www.saxproject.org/copying.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SAX-PD-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SAX-PD-2.0.json", + "referenceNumber": 561, + "name": "Sax Public Domain Notice 2.0", + "licenseId": "SAX-PD-2.0", + "seeAlso": [ + "http://www.saxproject.org/copying.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Saxpath.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Saxpath.json", + "referenceNumber": 109, + "name": "Saxpath License", + "licenseId": "Saxpath", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Saxpath_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SCEA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SCEA.json", + "referenceNumber": 35, + "name": "SCEA Shared Source License", + "licenseId": "SCEA", + "seeAlso": [ + "http://research.scea.com/scea_shared_source_license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SchemeReport.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SchemeReport.json", + "referenceNumber": 425, + "name": "Scheme Language Report License", + "licenseId": "SchemeReport", + "seeAlso": [], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Sendmail.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Sendmail.json", + "referenceNumber": 274, + "name": "Sendmail License", + "licenseId": "Sendmail", + "seeAlso": [ + "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf", + "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Sendmail-8.23.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Sendmail-8.23.json", + "referenceNumber": 247, + "name": "Sendmail License 8.23", + "licenseId": "Sendmail-8.23", + "seeAlso": [ + "https://www.proofpoint.com/sites/default/files/sendmail-license.pdf", + "https://web.archive.org/web/20181003101040/https://www.proofpoint.com/sites/default/files/sendmail-license.pdf" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SGI-B-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SGI-B-1.0.json", + "referenceNumber": 476, + "name": "SGI Free Software License B v1.0", + "licenseId": "SGI-B-1.0", + "seeAlso": [ + "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SGI-B-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SGI-B-1.1.json", + "referenceNumber": 456, + "name": "SGI Free Software License B v1.1", + "licenseId": "SGI-B-1.1", + "seeAlso": [ + "http://oss.sgi.com/projects/FreeB/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SGI-B-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SGI-B-2.0.json", + "referenceNumber": 405, + "name": "SGI Free Software License B v2.0", + "licenseId": "SGI-B-2.0", + "seeAlso": [ + "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/SGI-OpenGL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SGI-OpenGL.json", + "referenceNumber": 629, + "name": "SGI OpenGL License", + "licenseId": "SGI-OpenGL", + "seeAlso": [ + "https://gitlab.freedesktop.org/mesa/glw/-/blob/master/README?ref_type\u003dheads" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SGP4.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SGP4.json", + "referenceNumber": 336, + "name": "SGP4 Permission Notice", + "licenseId": "SGP4", + "seeAlso": [ + "https://celestrak.org/publications/AIAA/2006-6753/faq.php" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SHL-0.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SHL-0.5.json", + "referenceNumber": 338, + "name": "Solderpad Hardware License v0.5", + "licenseId": "SHL-0.5", + "seeAlso": [ + "https://solderpad.org/licenses/SHL-0.5/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SHL-0.51.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SHL-0.51.json", + "referenceNumber": 29, + "name": "Solderpad Hardware License, Version 0.51", + "licenseId": "SHL-0.51", + "seeAlso": [ + "https://solderpad.org/licenses/SHL-0.51/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SimPL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SimPL-2.0.json", + "referenceNumber": 444, + "name": "Simple Public License 2.0", + "licenseId": "SimPL-2.0", + "seeAlso": [ + "https://opensource.org/licenses/SimPL-2.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/SISSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SISSL.json", + "referenceNumber": 268, + "name": "Sun Industry Standards Source License v1.1", + "licenseId": "SISSL", + "seeAlso": [ + "http://www.openoffice.org/licenses/sissl_license.html", + "https://opensource.org/licenses/SISSL" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/SISSL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SISSL-1.2.json", + "referenceNumber": 502, + "name": "Sun Industry Standards Source License v1.2", + "licenseId": "SISSL-1.2", + "seeAlso": [ + "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SL.json", + "referenceNumber": 645, + "name": "SL License", + "licenseId": "SL", + "seeAlso": [ + "https://github.com/mtoyoda/sl/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Sleepycat.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Sleepycat.json", + "referenceNumber": 182, + "name": "Sleepycat License", + "licenseId": "Sleepycat", + "seeAlso": [ + "https://opensource.org/licenses/Sleepycat" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/SMLNJ.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SMLNJ.json", + "referenceNumber": 148, + "name": "Standard ML of New Jersey License", + "licenseId": "SMLNJ", + "seeAlso": [ + "https://www.smlnj.org/license.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/SMPPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SMPPL.json", + "referenceNumber": 250, + "name": "Secure Messaging Protocol Public License", + "licenseId": "SMPPL", + "seeAlso": [ + "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SNIA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SNIA.json", + "referenceNumber": 518, + "name": "SNIA Public License 1.1", + "licenseId": "SNIA", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/snprintf.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/snprintf.json", + "referenceNumber": 161, + "name": "snprintf License", + "licenseId": "snprintf", + "seeAlso": [ + "https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bsd-snprintf.c#L2" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/softSurfer.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/softSurfer.json", + "referenceNumber": 523, + "name": "softSurfer License", + "licenseId": "softSurfer", + "seeAlso": [ + "https://github.com/mm2/Little-CMS/blob/master/src/cmssm.c#L207", + "https://fedoraproject.org/wiki/Licensing/softSurfer" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Soundex.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Soundex.json", + "referenceNumber": 368, + "name": "Soundex License", + "licenseId": "Soundex", + "seeAlso": [ + "https://metacpan.org/release/RJBS/Text-Soundex-3.05/source/Soundex.pm#L3-11" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Spencer-86.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Spencer-86.json", + "referenceNumber": 472, + "name": "Spencer License 86", + "licenseId": "Spencer-86", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Spencer-94.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Spencer-94.json", + "referenceNumber": 378, + "name": "Spencer License 94", + "licenseId": "Spencer-94", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License", + "https://metacpan.org/release/KNOK/File-MMagic-1.30/source/COPYING#L28" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Spencer-99.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Spencer-99.json", + "referenceNumber": 139, + "name": "Spencer License 99", + "licenseId": "Spencer-99", + "seeAlso": [ + "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SPL-1.0.json", + "referenceNumber": 280, + "name": "Sun Public License v1.0", + "licenseId": "SPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/SPL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/ssh-keyscan.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ssh-keyscan.json", + "referenceNumber": 294, + "name": "ssh-keyscan License", + "licenseId": "ssh-keyscan", + "seeAlso": [ + "https://github.com/openssh/openssh-portable/blob/master/LICENCE#L82" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SSH-OpenSSH.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SSH-OpenSSH.json", + "referenceNumber": 506, + "name": "SSH OpenSSH license", + "licenseId": "SSH-OpenSSH", + "seeAlso": [ + "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/LICENCE#L10" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SSH-short.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SSH-short.json", + "referenceNumber": 563, + "name": "SSH short notice", + "licenseId": "SSH-short", + "seeAlso": [ + "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/pathnames.h", + "http://web.mit.edu/kolya/.f/root/athena.mit.edu/sipb.mit.edu/project/openssh/OldFiles/src/openssh-2.9.9p2/ssh-add.1", + "https://joinup.ec.europa.eu/svn/lesoll/trunk/italc/lib/src/dsa_key.cpp" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SSLeay-standalone.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SSLeay-standalone.json", + "referenceNumber": 591, + "name": "SSLeay License - standalone", + "licenseId": "SSLeay-standalone", + "seeAlso": [ + "https://www.tq-group.com/filedownloads/files/software-license-conditions/OriginalSSLeay/OriginalSSLeay.pdf" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SSPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SSPL-1.0.json", + "referenceNumber": 17, + "name": "Server Side Public License, v 1", + "licenseId": "SSPL-1.0", + "seeAlso": [ + "https://www.mongodb.com/licensing/server-side-public-license" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/StandardML-NJ.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/StandardML-NJ.json", + "referenceNumber": 658, + "name": "Standard ML of New Jersey License", + "licenseId": "StandardML-NJ", + "seeAlso": [ + "https://www.smlnj.org/license.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/SugarCRM-1.1.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SugarCRM-1.1.3.json", + "referenceNumber": 42, + "name": "SugarCRM Public License v1.1.3", + "licenseId": "SugarCRM-1.1.3", + "seeAlso": [ + "http://www.sugarcrm.com/crm/SPL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Sun-PPP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Sun-PPP.json", + "referenceNumber": 385, + "name": "Sun PPP License", + "licenseId": "Sun-PPP", + "seeAlso": [ + "https://github.com/ppp-project/ppp/blob/master/pppd/eap.c#L7-L16" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Sun-PPP-2000.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Sun-PPP-2000.json", + "referenceNumber": 310, + "name": "Sun PPP License (2000)", + "licenseId": "Sun-PPP-2000", + "seeAlso": [ + "https://github.com/ppp-project/ppp/blob/master/modules/ppp_ahdlc.c#L7-L19" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SunPro.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SunPro.json", + "referenceNumber": 57, + "name": "SunPro License", + "licenseId": "SunPro", + "seeAlso": [ + "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_acosh.c", + "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_lgammal.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SWL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SWL.json", + "referenceNumber": 649, + "name": "Scheme Widget Library (SWL) Software License Agreement", + "licenseId": "SWL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/SWL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/swrule.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/swrule.json", + "referenceNumber": 90, + "name": "swrule License", + "licenseId": "swrule", + "seeAlso": [ + "https://ctan.math.utah.edu/ctan/tex-archive/macros/generic/misc/swrule.sty" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Symlinks.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Symlinks.json", + "referenceNumber": 414, + "name": "Symlinks License", + "licenseId": "Symlinks", + "seeAlso": [ + "https://www.mail-archive.com/debian-bugs-rc@lists.debian.org/msg11494.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TAPR-OHL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TAPR-OHL-1.0.json", + "referenceNumber": 242, + "name": "TAPR Open Hardware License v1.0", + "licenseId": "TAPR-OHL-1.0", + "seeAlso": [ + "https://www.tapr.org/OHL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TCL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TCL.json", + "referenceNumber": 2, + "name": "TCL/TK License", + "licenseId": "TCL", + "seeAlso": [ + "http://www.tcl.tk/software/tcltk/license.html", + "https://fedoraproject.org/wiki/Licensing/TCL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TCP-wrappers.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TCP-wrappers.json", + "referenceNumber": 9, + "name": "TCP Wrappers License", + "licenseId": "TCP-wrappers", + "seeAlso": [ + "http://rc.quest.com/topics/openssh/license.php#tcpwrappers" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TermReadKey.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TermReadKey.json", + "referenceNumber": 256, + "name": "TermReadKey License", + "licenseId": "TermReadKey", + "seeAlso": [ + "https://github.com/jonathanstowe/TermReadKey/blob/master/README#L9-L10" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TGPPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TGPPL-1.0.json", + "referenceNumber": 101, + "name": "Transitive Grace Period Public Licence 1.0", + "licenseId": "TGPPL-1.0", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/TGPPL", + "https://tahoe-lafs.org/trac/tahoe-lafs/browser/trunk/COPYING.TGPPL.rst" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/threeparttable.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/threeparttable.json", + "referenceNumber": 398, + "name": "threeparttable License", + "licenseId": "threeparttable", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Threeparttable" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TMate.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TMate.json", + "referenceNumber": 539, + "name": "TMate Open Source License", + "licenseId": "TMate", + "seeAlso": [ + "http://svnkit.com/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TORQUE-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TORQUE-1.1.json", + "referenceNumber": 61, + "name": "TORQUE v2.5+ Software License v1.1", + "licenseId": "TORQUE-1.1", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TOSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TOSL.json", + "referenceNumber": 267, + "name": "Trusster Open Source License", + "licenseId": "TOSL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/TOSL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TPDL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TPDL.json", + "referenceNumber": 75, + "name": "Time::ParseDate License", + "licenseId": "TPDL", + "seeAlso": [ + "https://metacpan.org/pod/Time::ParseDate#LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TPL-1.0.json", + "referenceNumber": 508, + "name": "THOR Public License 1.0", + "licenseId": "TPL-1.0", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:ThorPublicLicense" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TTWL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TTWL.json", + "referenceNumber": 87, + "name": "Text-Tabs+Wrap License", + "licenseId": "TTWL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/TTWL", + "https://github.com/ap/Text-Tabs/blob/master/lib.modern/Text/Tabs.pm#L148" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TTYP0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TTYP0.json", + "referenceNumber": 451, + "name": "TTYP0 License", + "licenseId": "TTYP0", + "seeAlso": [ + "https://people.mpi-inf.mpg.de/~uwe/misc/uw-ttyp0/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TU-Berlin-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TU-Berlin-1.0.json", + "referenceNumber": 159, + "name": "Technische Universitaet Berlin License 1.0", + "licenseId": "TU-Berlin-1.0", + "seeAlso": [ + "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/TU-Berlin-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TU-Berlin-2.0.json", + "referenceNumber": 624, + "name": "Technische Universitaet Berlin License 2.0", + "licenseId": "TU-Berlin-2.0", + "seeAlso": [ + "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/UCAR.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/UCAR.json", + "referenceNumber": 78, + "name": "UCAR License", + "licenseId": "UCAR", + "seeAlso": [ + "https://github.com/Unidata/UDUNITS-2/blob/master/COPYRIGHT" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/UCL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/UCL-1.0.json", + "referenceNumber": 646, + "name": "Upstream Compatibility License v1.0", + "licenseId": "UCL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/UCL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/ulem.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ulem.json", + "referenceNumber": 566, + "name": "ulem License", + "licenseId": "ulem", + "seeAlso": [ + "https://mirrors.ctan.org/macros/latex/contrib/ulem/README" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/UMich-Merit.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/UMich-Merit.json", + "referenceNumber": 505, + "name": "Michigan/Merit Networks License", + "licenseId": "UMich-Merit", + "seeAlso": [ + "https://github.com/radcli/radcli/blob/master/COPYRIGHT#L64" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Unicode-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Unicode-3.0.json", + "referenceNumber": 46, + "name": "Unicode License v3", + "licenseId": "Unicode-3.0", + "seeAlso": [ + "https://www.unicode.org/license.txt" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Unicode-DFS-2015.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Unicode-DFS-2015.json", + "referenceNumber": 647, + "name": "Unicode License Agreement - Data Files and Software (2015)", + "licenseId": "Unicode-DFS-2015", + "seeAlso": [ + "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Unicode-DFS-2016.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Unicode-DFS-2016.json", + "referenceNumber": 152, + "name": "Unicode License Agreement - Data Files and Software (2016)", + "licenseId": "Unicode-DFS-2016", + "seeAlso": [ + "https://www.unicode.org/license.txt", + "http://web.archive.org/web/20160823201924/http://www.unicode.org/copyright.html#License", + "http://www.unicode.org/copyright.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Unicode-TOU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Unicode-TOU.json", + "referenceNumber": 606, + "name": "Unicode Terms of Use", + "licenseId": "Unicode-TOU", + "seeAlso": [ + "http://web.archive.org/web/20140704074106/http://www.unicode.org/copyright.html", + "http://www.unicode.org/copyright.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/UnixCrypt.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/UnixCrypt.json", + "referenceNumber": 462, + "name": "UnixCrypt License", + "licenseId": "UnixCrypt", + "seeAlso": [ + "https://foss.heptapod.net/python-libs/passlib/-/blob/branch/stable/LICENSE#L70", + "https://opensource.apple.com/source/JBoss/JBoss-737/jboss-all/jetty/src/main/org/mortbay/util/UnixCrypt.java.auto.html", + "https://archive.eclipse.org/jetty/8.0.1.v20110908/xref/org/eclipse/jetty/http/security/UnixCrypt.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Unlicense.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Unlicense.json", + "referenceNumber": 411, + "name": "The Unlicense", + "licenseId": "Unlicense", + "seeAlso": [ + "https://unlicense.org/" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/UPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/UPL-1.0.json", + "referenceNumber": 511, + "name": "Universal Permissive License v1.0", + "licenseId": "UPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/UPL" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/URT-RLE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/URT-RLE.json", + "referenceNumber": 443, + "name": "Utah Raster Toolkit Run Length Encoded License", + "licenseId": "URT-RLE", + "seeAlso": [ + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/other/pnmtorle.c", + "https://sourceforge.net/p/netpbm/code/HEAD/tree/super_stable/converter/other/rletopnm.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Vim.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Vim.json", + "referenceNumber": 371, + "name": "Vim License", + "licenseId": "Vim", + "seeAlso": [ + "http://vimdoc.sourceforge.net/htmldoc/uganda.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/VOSTROM.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/VOSTROM.json", + "referenceNumber": 122, + "name": "VOSTROM Public License for Open Source", + "licenseId": "VOSTROM", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/VOSTROM" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/VSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/VSL-1.0.json", + "referenceNumber": 510, + "name": "Vovida Software License v1.0", + "licenseId": "VSL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/VSL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/W3C.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/W3C.json", + "referenceNumber": 284, + "name": "W3C Software Notice and License (2002-12-31)", + "licenseId": "W3C", + "seeAlso": [ + "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html", + "https://opensource.org/licenses/W3C" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/W3C-19980720.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/W3C-19980720.json", + "referenceNumber": 156, + "name": "W3C Software Notice and License (1998-07-20)", + "licenseId": "W3C-19980720", + "seeAlso": [ + "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/W3C-20150513.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/W3C-20150513.json", + "referenceNumber": 452, + "name": "W3C Software Notice and Document License (2015-05-13)", + "licenseId": "W3C-20150513", + "seeAlso": [ + "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document", + "https://www.w3.org/copyright/software-license-2015/", + "https://www.w3.org/copyright/software-license-2023/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/w3m.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/w3m.json", + "referenceNumber": 202, + "name": "w3m License", + "licenseId": "w3m", + "seeAlso": [ + "https://github.com/tats/w3m/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Watcom-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Watcom-1.0.json", + "referenceNumber": 533, + "name": "Sybase Open Watcom Public License 1.0", + "licenseId": "Watcom-1.0", + "seeAlso": [ + "https://opensource.org/licenses/Watcom-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/Widget-Workshop.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Widget-Workshop.json", + "referenceNumber": 548, + "name": "Widget Workshop License", + "licenseId": "Widget-Workshop", + "seeAlso": [ + "https://github.com/novnc/noVNC/blob/master/core/crypto/des.js#L24" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Wsuipa.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Wsuipa.json", + "referenceNumber": 305, + "name": "Wsuipa License", + "licenseId": "Wsuipa", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Wsuipa" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/WTFPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/WTFPL.json", + "referenceNumber": 176, + "name": "Do What The F*ck You Want To Public License", + "licenseId": "WTFPL", + "seeAlso": [ + "http://www.wtfpl.net/about/", + "http://sam.zoy.org/wtfpl/COPYING" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/wxWindows.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/wxWindows.json", + "referenceNumber": 258, + "name": "wxWindows Library License", + "licenseId": "wxWindows", + "seeAlso": [ + "https://opensource.org/licenses/WXwindows" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/X11.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/X11.json", + "referenceNumber": 203, + "name": "X11 License", + "licenseId": "X11", + "seeAlso": [ + "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/X11-distribute-modifications-variant.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/X11-distribute-modifications-variant.json", + "referenceNumber": 112, + "name": "X11 License Distribution Modification Variant", + "licenseId": "X11-distribute-modifications-variant", + "seeAlso": [ + "https://github.com/mirror/ncurses/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Xdebug-1.03.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Xdebug-1.03.json", + "referenceNumber": 10, + "name": "Xdebug License v 1.03", + "licenseId": "Xdebug-1.03", + "seeAlso": [ + "https://github.com/xdebug/xdebug/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Xerox.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Xerox.json", + "referenceNumber": 595, + "name": "Xerox License", + "licenseId": "Xerox", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Xerox" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Xfig.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Xfig.json", + "referenceNumber": 89, + "name": "Xfig License", + "licenseId": "Xfig", + "seeAlso": [ + "https://github.com/Distrotech/transfig/blob/master/transfig/transfig.c", + "https://fedoraproject.org/wiki/Licensing:MIT#Xfig_Variant", + "https://sourceforge.net/p/mcj/xfig/ci/master/tree/src/Makefile.am" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/XFree86-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/XFree86-1.1.json", + "referenceNumber": 562, + "name": "XFree86 License 1.1", + "licenseId": "XFree86-1.1", + "seeAlso": [ + "http://www.xfree86.org/current/LICENSE4.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/xinetd.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/xinetd.json", + "referenceNumber": 465, + "name": "xinetd License", + "licenseId": "xinetd", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Xinetd_License" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/xkeyboard-config-Zinoviev.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/xkeyboard-config-Zinoviev.json", + "referenceNumber": 140, + "name": "xkeyboard-config Zinoviev License", + "licenseId": "xkeyboard-config-Zinoviev", + "seeAlso": [ + "https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/master/COPYING?ref_type\u003dheads#L178" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/xlock.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/xlock.json", + "referenceNumber": 357, + "name": "xlock License", + "licenseId": "xlock", + "seeAlso": [ + "https://fossies.org/linux/tiff/contrib/ras/ras2tif.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Xnet.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Xnet.json", + "referenceNumber": 236, + "name": "X.Net License", + "licenseId": "Xnet", + "seeAlso": [ + "https://opensource.org/licenses/Xnet" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/xpp.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/xpp.json", + "referenceNumber": 312, + "name": "XPP License", + "licenseId": "xpp", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/xpp" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/XSkat.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/XSkat.json", + "referenceNumber": 544, + "name": "XSkat License", + "licenseId": "XSkat", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/XSkat_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/xzoom.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/xzoom.json", + "referenceNumber": 530, + "name": "xzoom License", + "licenseId": "xzoom", + "seeAlso": [ + "https://metadata.ftp-master.debian.org/changelogs//main/x/xzoom/xzoom_0.3-27_copyright" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/YPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/YPL-1.0.json", + "referenceNumber": 491, + "name": "Yahoo! Public License v1.0", + "licenseId": "YPL-1.0", + "seeAlso": [ + "http://www.zimbra.com/license/yahoo_public_license_1.0.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/YPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/YPL-1.1.json", + "referenceNumber": 473, + "name": "Yahoo! Public License v1.1", + "licenseId": "YPL-1.1", + "seeAlso": [ + "http://www.zimbra.com/license/yahoo_public_license_1.1.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Zed.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zed.json", + "referenceNumber": 599, + "name": "Zed License", + "licenseId": "Zed", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Zed" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Zeeff.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zeeff.json", + "referenceNumber": 218, + "name": "Zeeff License", + "licenseId": "Zeeff", + "seeAlso": [ + "ftp://ftp.tin.org/pub/news/utils/newsx/newsx-1.6.tar.gz" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Zend-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zend-2.0.json", + "referenceNumber": 481, + "name": "Zend License v2.0", + "licenseId": "Zend-2.0", + "seeAlso": [ + "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Zimbra-1.3.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zimbra-1.3.json", + "referenceNumber": 379, + "name": "Zimbra Public License v1.3", + "licenseId": "Zimbra-1.3", + "seeAlso": [ + "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Zimbra-1.4.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zimbra-1.4.json", + "referenceNumber": 304, + "name": "Zimbra Public License v1.4", + "licenseId": "Zimbra-1.4", + "seeAlso": [ + "http://www.zimbra.com/legal/zimbra-public-license-1-4" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Zlib.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zlib.json", + "referenceNumber": 209, + "name": "zlib License", + "licenseId": "Zlib", + "seeAlso": [ + "http://www.zlib.net/zlib_license.html", + "https://opensource.org/licenses/Zlib" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/zlib-acknowledgement.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/zlib-acknowledgement.json", + "referenceNumber": 348, + "name": "zlib/libpng License with Acknowledgement", + "licenseId": "zlib-acknowledgement", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ZPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ZPL-1.1.json", + "referenceNumber": 545, + "name": "Zope Public License 1.1", + "licenseId": "ZPL-1.1", + "seeAlso": [ + "http://old.zope.org/Resources/License/ZPL-1.1" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ZPL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ZPL-2.0.json", + "referenceNumber": 51, + "name": "Zope Public License 2.0", + "licenseId": "ZPL-2.0", + "seeAlso": [ + "http://old.zope.org/Resources/License/ZPL-2.0", + "https://opensource.org/licenses/ZPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/ZPL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ZPL-2.1.json", + "referenceNumber": 352, + "name": "Zope Public License 2.1", + "licenseId": "ZPL-2.1", + "seeAlso": [ + "http://old.zope.org/Resources/ZPL/" + ], + "isOsiApproved": true, + "isFsfLibre": true + } + ], + "releaseDate": "2024-05-22" +} diff --git a/src/omi/dialects/__init__.py b/src/omi/dialects/__init__.py deleted file mode 100644 index 1407efc..0000000 --- a/src/omi/dialects/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -import omi.dialects.oep.dialect -import omi.dialects.rdf.dialect -from omi.dialects.base.register import get_dialect diff --git a/src/omi/dialects/base/compiler.py b/src/omi/dialects/base/compiler.py deleted file mode 100644 index f130823..0000000 --- a/src/omi/dialects/base/compiler.py +++ /dev/null @@ -1,89 +0,0 @@ -from omi import structure -from omi.oem_structures import oem_v15 - - -class Compiler: - """ - Compiles :class:`~omi.structure.Compilable` objects into the respective metadata - format. Every omi compiler should inherit from this class - """ - - def visit(self, obj, *args, **kwargs): - """ - Calls the respective compiler for :class:`~omi.structure.Compilable` objects - respective to :attr:`Compilable.__compiler_name__` - - - Parameters - ---------- - obj - Object to compile - - Returns - ------- - Metadata representation of `obj` - - """ - if isinstance(obj, list): - return [self.visit(x) for x in obj if x is not None] - if isinstance(obj, structure.Compilable): - meth = getattr(self, "visit_{name}".format(name=obj.__compiler_name__)) - return meth(obj, *args, **kwargs) - else: - return obj - - def visit_context(self, context: structure.Context, *args, **kwargs): - raise NotImplementedError - - def visit_contributor(self, contributor: structure.Contribution, *args, **kwargs): - raise NotImplementedError - - def visit_language(self, language: structure.Language, *args, **kwargs): - raise NotImplementedError - - def visit_spatial(self, spatial: structure.Spatial, *args, **kwargs): - raise NotImplementedError - - def visit_temporal(self, temporal: structure.Temporal, *args, **kwargs): - raise NotImplementedError - - def visit_timestamp_orientation( - self, ts_orientation: structure.TimestampOrientation, *args, **kwargs - ): - raise NotImplementedError - - def visit_timeseries(self, timeseries: oem_v15.Timeseries, *args, **kwargs): - raise NotImplementedError - - def visit_source(self, source: structure.Source, *args, **kwargs): - raise NotImplementedError - - def visit_license(self, lic: structure.License, *args, **kwargs): - raise NotImplementedError - - def visit_resource(self, resource: structure.Resource, *args, **kwargs): - raise NotImplementedError - - def visit_schema(self, context: structure.Schema, *args, **kwargs): - raise NotImplementedError - - def visit_dialect(self, context: structure.Dialect, *args, **kwargs): - raise NotImplementedError - - def visit_field(self, field: structure.Field, *args, **kwargs): - raise NotImplementedError - - def visit_foreign_key(self, foreign_key: structure.ForeignKey, *args, **kwargs): - raise NotImplementedError - - def visit_reference(self, reference: structure.Reference, *args, **kwargs): - raise NotImplementedError - - def visit_review(self, review: structure.Review, *args, **kwargs): - raise NotImplementedError - - def visit_meta_comment(self, comment: structure.MetaComment, *args, **kwargs): - raise NotImplementedError - - def visit_metadata(self, metadata: structure.OEPMetadata, *args, **kwargs): - raise NotImplementedError diff --git a/src/omi/dialects/base/dialect.py b/src/omi/dialects/base/dialect.py deleted file mode 100644 index 5e4fb21..0000000 --- a/src/omi/dialects/base/dialect.py +++ /dev/null @@ -1,69 +0,0 @@ -from omi.dialects.base.compiler import Compiler -from omi.dialects.base.parser import Parser -from omi.dialects.base.renderer import Renderer -from omi.structure import OEPMetadata - - -class Dialect: - _parser = Parser - _compiler = Compiler - _renderer = Renderer - - def compile(self, obj: OEPMetadata, *args, **kwargs): - """ - Compiles the passed :class:`~omi.structure.OEPMetadata`-object into the - structure fitting for this dialect - - Parameters - ---------- - obj - The :class:`~omi.structure.OEPMetadata`-object to compile - - Returns - ------- - - """ - c = self._compiler() - return c.visit(obj, *args, **kwargs) - - def parse(self, string: str, *args, **kwargs) -> OEPMetadata: - """ - Loads the passed string into an - :class:`~omi.structure.OEPMetadata`-object. - - Parameters - ---------- - string - The string to parse - - Returns - ------- - The :class:`~omi.structure.OEPMetadata`-object represented by `string` - """ - p = self._parser() - return p.parse_from_string(string, *args, **kwargs) - - def render(self, structure, *args, **kwargs) -> str: - """ - Turns the structure used by this dialect into a string - - Parameters - ---------- - structure - The structure to stringify - - Returns - ------- - A string representation of `structure` - """ - r = self._renderer() - return r.render(structure, *args, **kwargs) - - def compile_and_render(self, obj: OEPMetadata, *args, **kwargs): - """ - Combination of :func:`~omi.dialects.base.dialect.Dialect.compile` and :func:`~omi.dialects.base.dialect.Dialect.render`. - """ - c = self._compiler() - r = self._renderer() - compiled = c.visit(obj, *args, **kwargs) - return r.render(compiled, *args, **kwargs) diff --git a/src/omi/dialects/base/parser.py b/src/omi/dialects/base/parser.py deleted file mode 100644 index a3529a2..0000000 --- a/src/omi/dialects/base/parser.py +++ /dev/null @@ -1,125 +0,0 @@ -from typing import TypeVar - -from omi.structure import OEPMetadata - -T = TypeVar("T") - - -class ParserException(Exception): - pass - - -class Parser: - """ - A parser is used to transform to read a specific metadata format and - transform it into the internal metadata representation. - """ - def parse(self, structure: T, *args, **kwargs) -> OEPMetadata: - """ - Transforms the input structure into metadata as used by the - OpenEnergyPlatform - - Parameters - ---------- - inp: str - The input string that should be parsed into OEP metadata - - Returns - ------- - OEPMetadata - OEP metadata represented by `inp` - """ - raise NotImplementedError - - def load_string(self, string: str, *args, **kwargs): - """ - Load a string into the structure represented by the dialect - Parameters - ---------- - string: str - - Returns - ------- - Translates the passed string into the format used as input for this parser - """ - raise NotImplementedError - - def parse_from_string( - self, - string: str, - load_args=None, - parse_args=None, - load_kwargs=None, - parse_kwargs=None, - ) -> OEPMetadata: - """ - Parse a string into :class:`~omi.structure.OEPMetadata` - - Parameters - ---------- - string - - Returns - ------- - - """ - return self.parse( - self.load_string(string, *(load_args or []), **(load_kwargs or {})), - *(parse_args or []), - **(parse_kwargs or {}) - ) - - @staticmethod - def __unpack_file(file, **kwargs): - """ - - Parameters - ---------- - - Returns - ------- - - """ - with open(file, **kwargs, encoding='utf-8') as inp: - return inp.read() - - def parse_from_file(self, file_path, *args, **kwargs): - return self.parse_from_string(self.__unpack_file(file_path), *args, **kwargs) - - def is_valid(self, inp: str) -> bool: - """ - Verify whether `inp` is a sting representation that is parsable by this - parser - - Parameters - ---------- - inp: str - String to verify - - Returns - ------- - bool: - Indicated whether this object is parsable or not - - """ - raise NotImplementedError - - def is_file_valid(self, file: str, **kwargs): - """ - Verify whether the contents of the file under `file` is parsable by this - parser - - Parameters - ---------- - file: str - Path to the file to validate - - **kwargs: - - Returns - ------- - bool: - Returns `True` iff the file's content is parsable - - """ - return self.is_valid(self.__unpack_file(file, **kwargs)) diff --git a/src/omi/dialects/base/register.py b/src/omi/dialects/base/register.py deleted file mode 100644 index a52c4b5..0000000 --- a/src/omi/dialects/base/register.py +++ /dev/null @@ -1,15 +0,0 @@ -from omi.dialects.base.dialect import Dialect - -DIALECT_DICT = {} - - -def register(identifier: str): - def inner(dialect_class: Dialect): - DIALECT_DICT[identifier] = dialect_class - return dialect_class - - return inner - - -def get_dialect(identifier: str) -> Dialect: - return DIALECT_DICT[identifier] diff --git a/src/omi/dialects/base/renderer.py b/src/omi/dialects/base/renderer.py deleted file mode 100644 index 5fa7afd..0000000 --- a/src/omi/dialects/base/renderer.py +++ /dev/null @@ -1,34 +0,0 @@ -class Renderer: - def render(self, inp, *args, **kwargs) -> str: - """ - Transforms the given structure string into a string - - Parameters - ---------- - inp - The structure to render - - Returns - ------- - str - A string representation of `inp` - """ - raise NotImplementedError - - @staticmethod - def __unpack_file(*args, **kwargs): - """ - - Parameters - ---------- - - Returns - ------- - - """ - with open(*args, **kwargs) as inp: - return inp.read() - - def render_to_file(self, inp, file_path, *args, **kwargs): - with open(file_path, "w") as outfile: - outfile.write(self.render(inp, *args, **kwargs)) diff --git a/src/omi/dialects/oep/__init__.py b/src/omi/dialects/oep/__init__.py deleted file mode 100644 index 6c8388f..0000000 --- a/src/omi/dialects/oep/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from omi.dialects.oep.dialect import OEP_V_1_3_Dialect -from omi.dialects.oep.dialect import OEP_V_1_4_Dialect -from omi.dialects.oep.dialect import OEP_V_1_5_Dialect diff --git a/src/omi/dialects/oep/compiler.py b/src/omi/dialects/oep/compiler.py deleted file mode 100644 index 49dc431..0000000 --- a/src/omi/dialects/oep/compiler.py +++ /dev/null @@ -1,415 +0,0 @@ -import datetime -import logging - -from omi import structure -from omi.dialects.base.compiler import Compiler -from omi.oem_structures import oem_v15 - - -def compile_date_or_none(x, format=None): - if isinstance(x, (datetime.datetime, datetime.date)): - if format: - return x.strftime(format) - else: - return x.isoformat() - else: - return x - - -class JSONCompiler(Compiler): - __METADATA_VERSION = "OEP-1.4.0" - OMIT_NONE_FIELDS = False - - def _construct_dict(self, *args, omit_none=None, **kwargs): - """ - Accepts a list of arguments of shape (name: str, field: Compileable) and returns a dictionary that maps - name -> self.visit(field). If `omit_none` is true, fields that are `None` are ignored. - Parameters - ---------- - args - omit_none - kwargs - - Returns - ------- - - """ - omit_none = self.OMIT_NONE_FIELDS - d = { - field_name: self.visit(field) - for field_name, field in args - if (not omit_none) or (field is not None) - } - d.update(**kwargs) - return d - - def visit_context(self, context: structure.Context, *args, **kwargs): - result = self._construct_dict( - ("homepage", context.homepage), - ("documentation", context.documentation), - ("sourceCode", context.source_code), - ("contact", context.contact), - ("grantNo", context.grant_number), - ) - if context.funding_agency is not None: - result["fundingAgency"] = context.funding_agency.name - result["fundingAgencyLogo"] = context.funding_agency.logo - if context.publisher is not None: - result["publisherLogo"] = context.publisher.logo - logging.info( - f"The context is parsed from file with the following values: {context}" - ) - logging.info( - f"The context class is compiled to the following python dict: {result}" - ) - return result - - def visit_contribution(self, contribution: structure.Contribution, *args, **kwargs): - result = self._construct_dict( - ("title", contribution.contributor.name), - ("email", contribution.contributor.email), - ("object", contribution.object), - ("comment", contribution.comment), - ("date", compile_date_or_none(contribution.date, "%Y-%m-%d")), - ) - logging.info( - f"The contributions are parsed from file with the following values: {contribution}" - ) - logging.info( - f"The contributions class is compiled to the following python dict: {result}" - ) - return result - - def visit_language(self, language: structure.Language, *args, **kwargs): - return str(language) - - def visit_spatial(self, spatial: structure.Spatial, *args, **kwargs): - return self._construct_dict( - ("location", spatial.location), - ("extent", spatial.extent), - ("resolution", spatial.resolution), - ) - - def visit_timestamp_orientation( - self, tso: structure.TimestampOrientation, *args, **kwargs - ): - if tso == structure.TimestampOrientation.left: - return "left" - elif tso == structure.TimestampOrientation.middle: - return "middle" - elif tso == structure.TimestampOrientation.right: - return "right" - else: - raise NotImplementedError - - def visit_temporal(self, temporal: structure.Temporal, *args, **kwargs): - start = None - end = None - if temporal.ts_start is not None: - start = compile_date_or_none(temporal.ts_start) - if temporal.ts_end is not None: - end = compile_date_or_none(temporal.ts_end) - return self._construct_dict( - ( - "referenceDate", - compile_date_or_none(temporal.reference_date, "%Y-%m-%d"), - ), - timeseries=self._construct_dict( - ("start", start), - ("end", end), - ("resolution", temporal.ts_resolution), - ("alignment", temporal.ts_orientation), - ("aggregationType", temporal.aggregation), - ), - ) - - def visit_source(self, source: structure.Source, *args, **kwargs): - return self._construct_dict( - ("title", source.title), - ("description", source.description), - ("path", source.path), - ("licenses", source.licenses), - ) - - def visit_license(self, lic: structure.License, *args, **kwargs): - return self._construct_dict( - ("name", lic.identifier), - ("title", lic.name), - ("path", lic.path), - ) - - def visit_terms_of_use(self, terms_of_use: structure.TermsOfUse): - license_kwargs = ( - self.visit(terms_of_use.license) if terms_of_use.license else {} - ) - return self._construct_dict( - ("instruction", terms_of_use.instruction), - ("attribution", terms_of_use.attribution), - **license_kwargs, - ) - - def visit_resource(self, resource: structure.Resource, *args, **kwargs): - return self._construct_dict( - ("profile", resource.profile), - ("name", resource.name), - ("path", resource.path), - ("format", resource.format), - ("encoding", resource.encoding), - ("schema", resource.schema), - ("dialect", resource.dialect), - ) - - def visit_field(self, field: structure.Field, *args, **kwargs): - return self._construct_dict( - ("name", field.name), - ("description", field.description), - ("type", field.type), - ("unit", field.unit), - ) - - def visit_schema(self, schema: structure.Schema, *args, **kwargs): - return self._construct_dict( - ("primaryKey", schema.primary_key), - ("foreignKeys", schema.foreign_keys), - ("fields", schema.fields), - ) - - def visit_dialect(self, dialect: structure.Dialect, *args, **kwargs): - return self._construct_dict( - ("delimiter", dialect.delimiter), - ("decimalSeparator", dialect.decimal_separator), - ) - - def visit_foreign_key(self, foreign_key: structure.ForeignKey, *args, **kwargs): - if foreign_key.references: - source_fields, target_fields, target_resources = zip( - *map(self.visit, foreign_key.references) - ) - target_resource = target_resources[0] - - return self._construct_dict( - ("fields", source_fields), - reference=self._construct_dict( - ("resource", target_resource), - ("fields", target_fields), - ), - ) - else: - raise Exception("Missing reference in foreign key") - - def visit_reference(self, reference: structure.Reference, *args, **kwargs): - return ( - reference.source.name, - reference.target.name, - reference.target.resource.name, - ) - - def visit_review(self, review: structure.Review, *args, **kwargs): - return self._construct_dict(("path", review.path), badge=review.badge) - - def visit_meta_comment(self, comment: structure.MetaComment, *args, **kwargs): - return self._construct_dict( - ("metadata", comment.metadata_info), - ("dates", comment.dates), - ("units", comment.units), - ("languages", comment.languages), - ("licenses", comment.licenses), - ("review", comment.review), - ("null", comment.none), - ) - - def visit_metadata(self, metadata: structure.OEPMetadata, *args, **kwargs): - publication_date = None - if metadata.publication_date is not None: - publication_date = compile_date_or_none( - metadata.publication_date, "%Y-%m-%d" - ) - return self._construct_dict( - ("name", metadata.name), - ("title", metadata.title), - ("id", metadata.identifier), - ("description", metadata.description), - ("keywords", metadata.keywords), - ("publicationDate", publication_date), - ("context", metadata.context), - ("spatial", metadata.spatial), - ("temporal", metadata.temporal), - ("review", metadata.review), - ("language", metadata.languages), - ("sources", metadata.sources), - ("licenses", metadata.license), - ("contributors", metadata.contributions), - ("resources", metadata.resources), - ("_comment", metadata.comment), - metaMetadata=self._construct_dict( - ("metadataVersion", self.__METADATA_VERSION), - metadataLicense=self._construct_dict( - name="CC0-1.0", - title="Creative Commons Zero v1.0 Universal", - path="https://creativecommons.org/publicdomain/zero/1.0/", - ), - ), - ) - - -class JSONCompilerOEM15(JSONCompiler): - """ - Compiles OEMetadata version JSONCompilerOEM15.__METADATA_VERSION . - - Args: - JSONCompiler (object): Parent Class provides compiler methods for all - metadata fields that have not been changed in - the metadata structure. - """ - - __METADATA_VERSION = "OEP-1.5.2" - - def visit(self, obj, *args, **kwargs): - """ - Calls the respective compiler for :class:`~omi.structure.Compilable` objects - respective to :attr:`Compilable.__compiler_name__` - - - Parameters - ---------- - obj - Object to compile - - Returns - ------- - Metadata representation of `obj` - - """ - if isinstance(obj, list): - return [self.visit(x) for x in obj if x is not None] - if isinstance(obj, oem_v15.Compilable): - meth = getattr(self, "visit_{name}".format(name=obj.__compiler_name__)) - return meth(obj, *args, **kwargs) - else: - return obj - - def visit_subject(self, subject: oem_v15.Subject, *args, **kwargs): - return self._construct_dict(("name", subject.name), ("path", subject.path)) - - def visit_timestamp_orientation( - self, tso: oem_v15.TimestampOrientation, *args, **kwargs - ): - if tso == oem_v15.TimestampOrientation.left: - return "left" - elif tso == oem_v15.TimestampOrientation.middle: - return "middle" - elif tso == oem_v15.TimestampOrientation.right: - return "right" - else: - raise NotImplementedError - - def visit_timeseries(self, timeseries: oem_v15.Timeseries, *args, **kwargs): - start = None - end = None - if timeseries.ts_start is not None: - start = compile_date_or_none(timeseries.ts_start) - if timeseries.ts_end is not None: - end = compile_date_or_none(timeseries.ts_end) - return self._construct_dict( - ("start", start), - ("end", end), - ("resolution", timeseries.ts_resolution), - ("alignment", timeseries.ts_orientation), - ("aggregationType", timeseries.aggregation), - ) - - def visit_temporal(self, temporal: oem_v15.Temporal, *args, **kwargs): - return self._construct_dict( - ( - "referenceDate", - compile_date_or_none(temporal.reference_date, "%Y-%m-%d"), - ), - ("timeseries", temporal.timeseries_collection), - ) - - def visit_license(self, lic: oem_v15.License, *args, **kwargs): - return self._construct_dict( - ("name", lic.name), - ("title", lic.title), - ("path", lic.path), - ) - - def visit_isAbout(self, isAbout: oem_v15.IsAbout, *args, **kwargs): - return self._construct_dict(("name", isAbout.name), ("path", isAbout.path)) - - def visit_valueReference( - self, valueReference: oem_v15.ValueReference, *args, **kwargs - ): - return self._construct_dict( - ("value", valueReference.value), - ("name", valueReference.name), - ("path", valueReference.path), - ) - - def visit_field(self, field: oem_v15.Field, *args, **kwargs): - return self._construct_dict( - ("name", field.name), - ("description", field.description), - ("type", field.type), - ("isAbout", field.isAbout), - ("valueReference", field.valueReference), - ("unit", field.unit), - ) - - def visit_meta_comment(self, comment: oem_v15.MetaComment, *args, **kwargs): - return self._construct_dict( - ("metadata", comment.metadata_info), - ("dates", comment.dates), - ("units", comment.units), - ("languages", comment.languages), - ("licenses", comment.licenses), - ("review", comment.review), - ("null", comment.null), - ("todo", comment.todo), - ) - - def visit_metadata(self, metadata: oem_v15.OEPMetadata, *args, **kwargs): - publication_date = None - if metadata.publication_date is not None: - publication_date = compile_date_or_none( - metadata.publication_date, "%Y-%m-%d" - ) - return self._construct_dict( - ("name", metadata.name), - ("title", metadata.title), - ("id", metadata.identifier), - ("description", metadata.description), - ("subject", metadata.subject), - ("language", metadata.languages), - ("keywords", metadata.keywords), - ("publicationDate", publication_date), - ("context", metadata.context), - ("spatial", metadata.spatial), - ("temporal", metadata.temporal), - ("sources", metadata.sources), - ("licenses", metadata.license), - ("contributors", metadata.contributions), - ("resources", metadata.resources), - ("@id", metadata.databus_identifier), - ("@context", metadata.databus_context), - ("review", metadata.review), - metaMetadata=self._construct_dict( - ("metadataVersion", self.__METADATA_VERSION), - metadataLicense=self._construct_dict( - name="CC0-1.0", - title="Creative Commons Zero v1.0 Universal", - path="https://creativecommons.org/publicdomain/zero/1.0/", - ), - ), - _comment=self._construct_dict( - metadata="Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/oemetadata)", - dates="Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - units="Use a space between numbers and units (100 m)", - languages="Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - licenses="License name must follow the SPDX License List (https://spdx.org/licenses/)", - review="Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/blob/master/data-review/manual/review_manual.md)", - null="If not applicable use: null", - todo="If a value is not yet available, use: todo", - ), - **kwargs, - ) diff --git a/src/omi/dialects/oep/conversion.py b/src/omi/dialects/oep/conversion.py deleted file mode 100644 index b428307..0000000 --- a/src/omi/dialects/oep/conversion.py +++ /dev/null @@ -1,357 +0,0 @@ -""" -The conversion in OMI is used to translate metadata version, usually from low to high version. - -The Converter class is the base class that provides base funtionality to enable a specific version translateion. - -The Translation class includes all functionality to create missing fields and supply default, none or user input values for each new field. -The translated metadata will be build and can be saved to a file by using convinience methodes provides by the converter or manually saved -to file using OMI's dialect15.compile_and_render(). - -BUGS: -- oeo keys are not included -- value reference and is about got wrong name format in json -""" - -import json -import logging -import pathlib -from datetime import datetime - -from omi import structure -from omi.dialects import get_dialect -from omi.dialects.base.dialect import Dialect -from omi.oem_structures import oem_v15 - - -# NOTE: Maybe change this to abstract class and implement methods in concrete child classes -class Converter: - """ - Base Converter class for oemetadata version conversion. - Provides basic converstion functions and helpers. - All concrete conversion classes should inheret from this class. - - """ - - def __init__( - self, - dielact_id: str = "oep-v1.5", # latest version - metadata: structure.OEPMetadata = None, - ) -> None: - self.dialect_id = dielact_id - self.metadata = metadata - self.omi_version = "OMI-v0.0.8" - - def validate_str_version_format(self): - return NotImplementedError - - def sanitize_oem(self, oemetadata: dict) -> oem_v15.OEPMetadata: - """ - Remove all "" or " " values. Additionaly it is possible to specify a specific - field that will set to none. Key that got a none value will result in a json null - that will not be visible in a json document. - - Args: - oemetadata (oem_v15.OEPMetadata): _description_ - - Returns: - oem_v15.OEPMetadata: _description_ - """ - - omi_dialect = self.detect_oemetadata_dialect(oemetadata) - metadata = omi_dialect._parser().parse(oemetadata) - print(type(omi_dialect)) - - if ( - metadata["metaMetadata"]["metadataVersion"] == "oep-v1.5.1" - ): # NOTE hardcoded - oemetadata_obj: oem_v15.OEPMetadata - # sanitize .... - else: - oemetadata_obj: structure.OEPMetadata - # sanitize .... - - return oemetadata_obj - - def format_version_string(self, version_string: str = None) -> str: - if version_string is not None: - version_string = version_string.lower() - parts = version_string.split(sep="-") - self.dialect_id = parts[0] + "-v" + parts[1][:-2] - return self.dialect_id - - def detect_oemetadata_dialect(self, metadata=None) -> Dialect: - if metadata is None: - try: - version: str = self.metadata["metaMetadata"]["metadataVersion"] - self.dialect_id = self.format_version_string(version_string=version) - logging.info(f"The dectected dialect is: {self.dialect_id}") - except Exception as e: - logging.warning( - { - "exception": f"{e}", - "message": f"Could not detect the dialect based on the Oemetadata json string. The key related to meta-metadata information might not be present in the input metadata json file. Fallback to the default dialect: '{self.dialect_id}'.", - } - ) - else: - try: - version: str = metadata["metaMetadata"]["metadataVersion"] - self.dialect_id = self.format_version_string(version_string=version) - logging.info(f"The dectected dialect is: {self.dialect_id}") - except Exception as e: - logging.warning( - { - "exception": f"{e}", - "message": f"Could not detect the dialect based on the Oemetadata json string. The key related to meta-metadata information might not be present in the input metadata json file. Fallback to the default dialect: '{self.dialect_id}'.", - } - ) - - return get_dialect(identifier=self.dialect_id) - - # NOTE: Add omi version to user? - def set_contribution( - self, - metadata: oem_v15.OEPMetadata, - user: str = "OMI-v0.0.8", - user_email: str = None, - ) -> oem_v15.OEPMetadata: - to_metadata = "oep-v1.5.1" # NOTE hardcoded - contribution = oem_v15.Contribution( - contributor=oem_v15.Person(name=user, email=user_email), - date=datetime.now(), - obj="Metadata conversion", - comment="Update metadata to " - + to_metadata - + " using OMIs metadata conversion tool.", - ) - - metadata = metadata.contributions.append(contribution) - - return metadata - - def convert_oemetadata(): - pass - - -class Metadata14To15Translation(Converter): - """ - Converts/translates the oemetadata object generated based on the input oemetadata.json file to oemetadata-v1.5.1 structure. - - Args: - Converter : Base converter class - """ - - def remove_temporal( - self, metadata14: structure.OEPMetadata - ) -> structure.OEPMetadata: - metadata14.temporal = None - return metadata14 - - @staticmethod - def create_subject(subject: oem_v15.Subject, name: str = "", path: str = ""): - subject = subject() - subject.name = name - subject.path = path - return subject - - @staticmethod - def create_oeo_id(oeo_id: str = None): - return oeo_id - - @staticmethod - def create_oeo_context(oeo_context: str = None): - return oeo_context - - # NOTE: need? - @staticmethod - def create_meta_comment_null( - meta_comment_null: str = "If not applicable use: null", # hardcoded - ): - return meta_comment_null - - @staticmethod - def create_meta_comment_todo( - meta_comment_todo: str = "If a value is not yet available, use: todo", # hardcoded - ): - return meta_comment_todo - - @staticmethod - def create_is_about(is_about: oem_v15.IsAbout, name: str = "", path: str = ""): - is_about = is_about() - is_about.name = name - is_about.path = path - return is_about - - @staticmethod - def create_value_reference( - value_reference: oem_v15.ValueReference, - value: str = "", - name: str = "", - path: str = "", - ): - value_reference = value_reference() - value_reference.value = value - value_reference.name = name - value_reference.path = path - return value_reference - - def convert_timestamp_orientation(self, ts: str): - new_ts = oem_v15.TimestampOrientation.create(ts) - return new_ts - - # NOTE maybe move timeseries element from convert temporal - def convert_timeseries(self, metadata14_temporal: structure.Temporal): - timeseries = None - if metadata14_temporal.ts_start and metadata14_temporal.ts_end is not None: - timeseries = oem_v15.Timeseries( - start=metadata14_temporal.ts_start, - end=metadata14_temporal.ts_end, - resolution=metadata14_temporal.ts_resolution, - ts_orientation=self.convert_timestamp_orientation( - metadata14_temporal.ts_orientation.name - ), - aggregation=metadata14_temporal.aggregation, - ) - return timeseries - - def convert_temporal( - self, - metadata14_temporal: structure.Temporal, - ): - temporal = None - if metadata14_temporal is not None: - temporal = oem_v15.Temporal( - reference_date=metadata14_temporal.reference_date, - timeseries_collection=[self.convert_timeseries(metadata14_temporal)], - ) # NOTE: assume there will be a single timeseries as input because OEM-v1.4 did not support multiple timeseries elements - return temporal - - def convert_meta_comment( - self, metadata14_meta_comment: structure.MetaComment - ) -> oem_v15.MetaComment: - - meta_comment = None - if metadata14_meta_comment is not None: - meta_comment = oem_v15.MetaComment( - metadata_info=metadata14_meta_comment.metadata_info, - dates=metadata14_meta_comment.dates, - units=metadata14_meta_comment.units, - languages=metadata14_meta_comment.languages, - licenses=metadata14_meta_comment.licenses, - review=metadata14_meta_comment.review, - null=self.create_meta_comment_null(), - todo=self.create_meta_comment_todo(), - ) - - return meta_comment - - def convert_ressources_field(self, metadata14_ressources_field: list = None): - field: oem_v15.Field - ressources_fields = [] - if metadata14_ressources_field is not None: - for field in metadata14_ressources_field: - ressources_field = oem_v15.Field( - name=field.name, - description=field.description, - field_type=field.type, - isAbout=[self.create_is_about(oem_v15.IsAbout)], - valueReference=[ - self.create_value_reference(oem_v15.ValueReference) - ], - unit=field.unit, - resource=field.resource, - ) - ressources_fields.append(ressources_field) - else: - ressources_fields = None - - return ressources_fields - - def convert_ressource(self, metadata14_ressources: list): - ressource: oem_v15.Resource - ressources = [] - for ressource in metadata14_ressources: - single_ressource = oem_v15.Resource( - name=ressource.name, - path=ressource.path, - profile=ressource.profile, - resource_format=ressource.format, - encoding=ressource.encoding, - schema=oem_v15.Schema( - fields=self.convert_ressources_field(ressource.schema.fields), - primary_key=ressource.schema.primary_key, - foreign_keys=ressource.schema.foreign_keys, - ), - dialect=ressource.dialect, - ) - ressources.append(single_ressource) - - return ressources - - def build_metadata15(self, metadata: structure.OEPMetadata): - converted_metadata = oem_v15.OEPMetadata( - name=metadata.name, - title=metadata.title, - identifier=metadata.identifier, - description=metadata.description, - subject=[ - self.create_subject(oem_v15.Subject) - ], # NOTE add just one dummy subject object, maybe its better to keep it empty? # add value from user input?? - languages=metadata.languages, - keywords=metadata.keywords, - publication_date=metadata.publication_date, - context=metadata.context, - spatial=metadata.spatial, - temporal=self.convert_temporal( - metadata.temporal - ), # NOTE add value from user input?? - sources=metadata.sources, - terms_of_use=metadata.license, - contributions=metadata.contributions, - resources=self.convert_ressource(metadata.resources), - databus_identifier=self.create_oeo_id(), # NOTE add value from user input?? - databus_context=self.create_oeo_context(), # NOTE add value from user input?? - review=metadata.review, - comment=self.convert_meta_comment(metadata.comment), - ) - - return converted_metadata - - -def read_input_json(file_path: pathlib.Path = "tests/data/metadata_v14.json"): - with open(file_path, "r", encoding="utf-8") as f: - jsn = json.load(f) - - return jsn - - -def save_to_file(metadata: oem_v15.OEPMetadata, file_path: pathlib.Path): - - with open(file_path, "w", encoding="utf-8") as outfile: - outfile.write(metadata) - - -def run_conversion( - to_metadata: str, from_metadata: str, convert=Metadata14To15Translation -): - metadata_file = read_input_json(from_metadata) - convert = convert(metadata=metadata_file) - dialect_input = convert.detect_oemetadata_dialect() - metadata = dialect_input._parser().parse(metadata_file) - convert.set_contribution(metadata) - - converted = convert.build_metadata15(metadata) - - dialect15 = get_dialect("oep-v1.5")() - s = dialect15.compile_and_render(obj=converted) - save_to_file(s, to_metadata) - - return s - - -if __name__ == "__main__": - - # Run conversion with test data - run_conversion( - to_metadata="1_test_results/metadata/conversion_out_oem151.json", - from_metadata="tests/data/metadata_v14.json", - ) diff --git a/src/omi/dialects/oep/dialect.py b/src/omi/dialects/oep/dialect.py deleted file mode 100644 index bca1355..0000000 --- a/src/omi/dialects/oep/dialect.py +++ /dev/null @@ -1,30 +0,0 @@ -from omi.dialects.base.dialect import Dialect -from omi.dialects.base.register import register -from omi.dialects.oep.compiler import JSONCompiler -from omi.dialects.oep.compiler import JSONCompilerOEM15 -from omi.dialects.oep.parser import JSONParser_1_3 -from omi.dialects.oep.parser import JSONParser_1_4 -from omi.dialects.oep.parser import JSONParser_1_5 -from omi.dialects.oep.renderer import JSONRenderer -from omi.oem_structures import oem_v15 - - -@register("oep-v1.3") -class OEP_V_1_3_Dialect(Dialect): - _parser = JSONParser_1_3 - _compiler = None - _renderer = JSONRenderer - - -@register("oep-v1.4") -class OEP_V_1_4_Dialect(Dialect): - _parser = JSONParser_1_4 - _compiler = JSONCompiler - _renderer = JSONRenderer - - -@register("oep-v1.5") -class OEP_V_1_5_Dialect(Dialect): - _parser = JSONParser_1_5 - _compiler = JSONCompilerOEM15 - _renderer = JSONRenderer diff --git a/src/omi/dialects/oep/parser.py b/src/omi/dialects/oep/parser.py deleted file mode 100644 index e670480..0000000 --- a/src/omi/dialects/oep/parser.py +++ /dev/null @@ -1,1300 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -import json -import logging -import pathlib -import re - -import dateutil -import jsonschema -from jsonschema import ValidationError -# oemetadata -from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA -from metadata.v130.schema import OEMETADATA_V130_SCHEMA -from metadata.v140.schema import OEMETADATA_V140_SCHEMA -from metadata.v141.schema import OEMETADATA_V141_SCHEMA -from metadata.v150.schema import OEMETADATA_V150_SCHEMA -from metadata.v151.schema import OEMETADATA_V151_SCHEMA - -from omi import structure -from omi.dialects.base.parser import Parser -from omi.dialects.base.parser import ParserException -from omi.oem_structures import oem_v15 - -ALL_OEM_SCHEMAS = [ - OEMETADATA_LATEST_SCHEMA, - OEMETADATA_V151_SCHEMA, - OEMETADATA_V150_SCHEMA, - OEMETADATA_V141_SCHEMA, - OEMETADATA_V140_SCHEMA, - OEMETADATA_V130_SCHEMA, -] - - -def parse_date_or_none(x, fieldname=None, element=None): - if x is None: - pass - elif type(x) == int: - # e.g just a year or a unix timestamp - # NOTE: isinstance(x, int) is also True for a bool, - # which we dont want - pass - elif isinstance(x, str): - # IMPORTANT NOTE: only use dateutil.parser if date part is complete - # if you parse something like '2020' or '2020-01', it will silently - # fill in the missing month/day from the current date! - # in this case, we keep the string, if it is at least is the correct pattern - - if re.match("^[123][0-9]{3}(|-[0-9]{1,2})$", x): - # only year or year-month: keep string - pass - elif re.match("^[123][0-9]{3}-[0-9]{1,2}-[0-9]{1,2}", x): - try: - date_time = dateutil.parser.parse(x) - except Exception: - raise ParserException( - f"In fields {fieldname} {element} element is a invalid value for date: {x}" - ) - if re.match("^[123][0-9]{3}-[0-9]{1,2}-[0-9]{1,2}$", x): - # date only - x = date_time.date() - else: - x = date_time - else: - raise ParserException( - f"In fields {fieldname} {element} element is a invalid value for date: {x}" - ) - else: - raise ParserException( - f"In fields {fieldname} {element} element is a invalid type for date: {type(x)}" - ) - return x - - -def create_report_json( - error_data, # type list[dict] - save_at: pathlib.Path = "reports/", - filename: str = "report.json", -): - # if len(error_data) >= 1: - pathlib.Path(save_at).mkdir(parents=True, exist_ok=True) - with open(f"{save_at}{filename}", "w", encoding="utf-8") as fp: - json.dump(error_data, fp, indent=4, sort_keys=False) - - print( - f"Created error report containing {len(error_data)} errors at: {save_at}{filename}" - ) - - -class JSONParser(Parser): - def normalize_key_names_of_input(iput: dict): - pass - - def load_string(self, string: str, *args, **kwargs): - return json.loads(string) - - def get_json_validator(self, schema: OEMETADATA_LATEST_SCHEMA): - """ - Get the jsonschema validator that matches the schema. - Also checks if the schmea is valid. - - Args: - schema (OEMETADATA_LATEST_SCHEMA): - - Returns: - validator: jsonschema.Draft202012Validator - """ - jsonschema.Draft202012Validator.check_schema(schema) - validator = jsonschema.Draft202012Validator(schema=schema) - return validator - - def get_any_schema_valid( - self, - metadata: dict, - schemas: list = ALL_OEM_SCHEMAS, - ): - """ - Additional helper funtion - get any schema that is valid for the metadata. - Returns The first valid schema or None - - Args: - schemas (list): _description_ - metadata (dict): _description_ - - Returns: - _type_: _description_ - """ - - valid_schemas = [] - for schema in schemas: - if len(valid_schemas) <= 1: - continue - elif self.is_valid(inp=metadata, schema=schema): - valid_schemas.append(schema) - - if len(valid_schemas) >= 1: - valid_schemas = None - return valid_schemas - - def get_schema_by_metadata_version(self, metadata: dict): - oem_13 = ["1.3", "OEP-1.3"] - oem_14 = "OEP-1.4.0" - oem_141 = "OEP-1.4.1" - oem_15 = "OEP-1.5.0" - oem_151 = "OEP-1.5.1" - - schema = None - - if metadata.get("metadata_version"): - if metadata.get("metadata_version") in oem_13: - schema = OEMETADATA_V130_SCHEMA - - if metadata.get("metaMetadata"): - if metadata.get("metaMetadata")["metadataVersion"] == oem_14: - schema = OEMETADATA_V140_SCHEMA - if metadata.get("metaMetadata")["metadataVersion"] == oem_141: - schema = OEMETADATA_V141_SCHEMA - if metadata.get("metaMetadata")["metadataVersion"] == oem_15: - schema = OEMETADATA_V150_SCHEMA - if metadata.get("metaMetadata")["metadataVersion"] == oem_151: - schema = OEMETADATA_V151_SCHEMA - - # fallback to latest schema if metadata does not contian the exprected metadata version sting - if schema is None: - logging.info( - "Metadata does not contain the expected 'metaMetadata' or 'metadata_version' key. Fallback to latest schema." - ) - schema = OEMETADATA_LATEST_SCHEMA - return schema - - def validate(self, metadata: dict, schema: dict = None, save_report=True): - """ - Check whether the given dictionary adheres to the the json-schema - and oemetadata specification. If errors are found a jsonschema error - report is created in directory 'reports/'. - - Parameters - ---------- - metadata - The dictionary to validate - schema: optional - The jsonschema used for validation. - Default is None. - Returns - ------- - Nothing - """ - - report = [] - if not schema: - schema = self.get_schema_by_metadata_version(metadata=metadata) - validator = self.get_json_validator(schema) - - for error in sorted(validator.iter_errors(instance=metadata), key=str): - # https://python-jsonschema.readthedocs.io/en/stable/errors/#handling-validation-errors - error_dict = { - "oemetadata schema version": schema.get("$id"), - # "json path": error.absolute_path, - "instance path": [i for i in error.absolute_path], - "value that raised the error": error.instance, - "error message": error.message, - "schema_path": [i for i in error.schema_path], - } - report.append(error_dict) - - if save_report: - create_report_json(report) - - return report - - def is_valid(self, inp: dict, schema): - # 1 - valid JSON? - if isinstance(inp, str): - try: - jsn = json.loads(inp) - except ValueError: - return False - else: - jsn = inp - - # 2 - valid OEMETADATA - try: - validator = self.get_json_validator(schema) - validator.validate(jsn) - return True - except ValidationError: - return False - - -class JSONParser_1_3(JSONParser): - def is_valid(self, inp: dict, schema=OEMETADATA_V130_SCHEMA): - # 1 - valid JSON? - if isinstance(inp, str): - try: - jsn = json.loads(inp, encode="utf-8") - except ValueError: - return False - else: - jsn = inp - - # 2 - valid OEMETADATA - try: - validator = self.get_json_validator(schema) - validator.validate(jsn) - return True - except ValidationError: - return False - - def parse(self, json_old, *args, **kwargs): - # context section - context = None - - # filling the spatial section - if "spatial" in json_old: - old_spatial = json_old.get("spatial") - spatial = structure.Spatial( - extent=old_spatial.get("extent"), - resolution=old_spatial.get("resolution"), - ) - else: - spatial = None - - # filling the temporal section - old_temporal = json_old.get("temporal") - if old_temporal is None: - temporal = None - else: - temporal = structure.Temporal( - reference_date=parse_date_or_none(old_temporal.get("reference_date")) - ) - - # filling the source section - # For future reference: There is an important semantic difference between `source = None` and `sources = []` - # The former means that there is no information regarding sources the latter means that there are no sources. - # This is holds for all lists around here - old_sources = json_old.get("sources") - if old_sources is None: - sources = None - else: - sources = [ - structure.Source( - title=old_source.get("name"), - description=old_source.get("description"), - path=old_source.get("url"), - licenses=[ - structure.TermsOfUse(attribution=old_source.get("copyright")) - ], - ) - for old_source in old_sources - ] - - # filling the license section - old_license = json_old.get("license") - if old_license is None: - licenses = None # not []! (see sources) - else: - licenses = [ - structure.TermsOfUse( - lic=structure.License( - identifier=old_license.get("id"), - name=old_license.get("name"), - path=old_license.get("url"), - ), - instruction=old_license.get("instruction"), - attribution=old_license.get("copyright"), - ) - ] - - # filling the contributers section - old_contributors = json_old.get("contributors") - if old_contributors is None: - contributions = None - else: - contributions = [ - structure.Contribution( - contributor=structure.Person( - name=old_contributor.get("name"), - email=old_contributor.get("email"), - ), - date=parse_date_or_none(old_contributor.get("date")), - comment=old_contributor.get("comment"), - ) - for old_contributor in old_contributors - ] - - # extending with script-user information - - old_resources = json_old.get("resources") - if old_resources is None: - resources = None - else: - resources = [] - if len(old_resources) == 0: - raise ParserException( - "The field Resource field is empty! Please provide a description of your data resources e.g. a table schema." - ) - for resource in old_resources: - old_fields = resource.get("fields") - if old_fields is None: - fields = None - else: - fields = [ - structure.Field( - name=field.get("name"), - description=field.get("description"), - unit=field.get("unit"), - ) - for field in old_fields - ] - schema = structure.Schema(fields=fields) - resources.append( - structure.Resource( - name=resource.get("name"), - resource_format="PostgreSQL", - schema=schema, - ) - ) - - review = None - - comment = None - - metadata = structure.OEPMetadata( - title=json_old.get("title"), - description=json_old.get("description"), - languages=json_old.get("language"), - identifier=None, - context=context, - spatial=spatial, - temporal=temporal, - sources=sources, - terms_of_use=licenses, - contributions=contributions, - resources=resources, - review=review, - comment=comment, - ) - return metadata - - -class JSONParser_1_4(JSONParser): - def is_valid(self, inp: dict, schema=OEMETADATA_V141_SCHEMA): - # 1 - valid JSON? - if isinstance(inp, str): - try: - jsn = json.loads(inp, encode="utf-8") - except ValueError: - return False - else: - jsn = inp - - # 2 - valid OEMETADATA - try: - validator = self.get_json_validator(schema) - validator.validate(jsn) - return True - except ValidationError: - return False - - def parse_term_of_use(self, old_license: dict): - return structure.TermsOfUse( - lic=structure.License( - identifier=old_license.get("name"), - name=old_license.get("title"), - path=old_license.get("path"), - ), - instruction=old_license.get("instruction"), - attribution=old_license.get("attribution"), - ) - - def parse(self, json_old: dict, *args, **kwargs): - # context section - if "id" not in json_old: - raise ParserException( - "The metadata string does not contain an id. This field is required." - ) - - inp_context = json_old.get("context") - if inp_context is None: - context = None - else: - funding_agency = None - if "fundingAgency" in inp_context: - funding_agency = structure.Agency( - name=inp_context.get("fundingAgency"), - logo=inp_context.get("fundingAgencyLogo"), - ) - - context = structure.Context( - homepage=inp_context.get("homepage"), - documentation=inp_context.get("documentation"), - source_code=inp_context.get("sourceCode"), - contact=inp_context.get("contact"), - grant_number=inp_context.get("grantNo"), - funding_agency=funding_agency, - publisher=structure.Agency(logo=inp_context.get("publisherLogo")) - if "publisherLogo" in inp_context - else None, - ) - - # filling the spatial section - old_spatial = json_old.get("spatial") - if old_spatial is None: - spatial = None - else: - spatial = structure.Spatial( - location=old_spatial.get("location"), - extent=old_spatial.get("extent"), - resolution=old_spatial.get("resolution"), - ) - - # filling the temporal section - inp_temporal = json_old.get("temporal") - if inp_temporal is None: - temporal = None - else: - inp_timeseries = inp_temporal.get("timeseries") - timeseries = {} - if inp_timeseries is not None: - timeseries = dict( - start=parse_date_or_none(inp_timeseries.get("start")), - end=parse_date_or_none(inp_timeseries.get("end")), - resolution=inp_timeseries.get("resolution"), - ts_orientation=structure.TimestampOrientation.create( - inp_timeseries.get("alignment") - ) - if "alignment" in inp_timeseries - and inp_timeseries["alignment"] is not None - else None, - aggregation=inp_timeseries.get("aggregationType"), - ) - temporal = structure.Temporal( - reference_date=parse_date_or_none(inp_temporal.get("referenceDate")), - **timeseries, - ) - - # filling the source section - old_sources = json_old.get("sources") - if old_sources is None: - sources = None - else: - sources = [ - structure.Source( - title=old_source.get("title"), - description=old_source.get("description"), - path=old_source.get("path"), - licenses=[ - self.parse_term_of_use(l) - for l in old_source.get("licenses", []) - ], - ) - for old_source in old_sources - ] - - # filling the license section - old_licenses = json_old.get("licenses") - if old_licenses is None: - licenses = None - else: - licenses = [ - self.parse_term_of_use(old_license) for old_license in old_licenses - ] - - # filling the contributers section - old_contributors = json_old.get("contributors") - if old_contributors is None: - contributors = None - else: - contributors = [ - structure.Contribution( - contributor=structure.Person( - name=old_contributor.get("title"), - email=old_contributor.get("email"), - ), - date=parse_date_or_none( - old_contributor.get("date"), f"{cont_element}contributors.data" - ), - obj=old_contributor.get("object"), - comment=old_contributor.get("comment"), - ) - for cont_element, old_contributor in enumerate(old_contributors) - ] - - # extending with script-user information - old_resources = json_old.get("resources") - if old_resources is None: - resources = None - # Code added to raise exception when resource is empty - else: - if len(old_resources) == 0: - raise ParserException("Resource field doesn't have any child entity") - resources = [] - for resource in old_resources: - old_schema = resource.get("schema") - if old_schema is None: - schema = None - else: - old_fields = old_schema.get("fields") - if old_fields is None: - fields = None - else: - fields = [ - structure.Field( - name=field.get("name"), - description=field.get("description"), - field_type=field.get("type"), - unit=field.get("unit"), - ) - for field in old_fields - ] - field_dict = {field.name: field for field in fields or []} - old_foreign_keys = old_schema.get("foreignKeys", []) - foreign_keys = [] - for fk in old_foreign_keys: - old_reference = fk.get("reference") - if old_reference is None: - raise ParserException("Foreign key without reference:", fk) - source_fields = [ - field_dict[field_name] - for field_name in fk.get("fields", []) - ] - old_referenced_fields = old_reference.get("fields") - if old_referenced_fields is None: - referenced_fields = None - else: - referenced_fields = [ - structure.Field(name=fk_field) - for fk_field in old_referenced_fields - ] - referenced_resource = structure.Resource( - name=old_reference.get("resource"), - schema=structure.Schema(fields=referenced_fields), - ) - for rf in referenced_fields: - rf.resource = referenced_resource - references = [ - structure.Reference(s, t) - for s, t in zip(source_fields, referenced_fields) - ] - foreign_keys.append(structure.ForeignKey(references=references)) - schema = structure.Schema( - fields=fields, - primary_key=resource["schema"].get("primaryKey"), - foreign_keys=foreign_keys, - ) - old_dialect = resource.get("dialect") - if old_dialect is None: - dialect = None - else: - dialect = structure.Dialect( - delimiter=resource["dialect"].get("delimiter"), - decimal_separator=resource["dialect"].get("decimalSeparator"), - ) - resources.append( - structure.Resource( - profile=resource.get("profile"), - name=resource.get("name"), - path=resource.get("path"), - resource_format=resource.get("format"), - encoding=resource.get("encoding"), - schema=schema, - dialect=dialect, - ) - ) - - inp_review = json_old.get("review") - if inp_review is None: - review = None - else: - review = structure.Review( - path=inp_review.get("path"), badge=inp_review.get("badge") - ) - - inp_comment = json_old.get("_comment") - if inp_comment is None: - comment = None - else: - comment = structure.MetaComment( - metadata_info=inp_comment.get("metadata"), - dates=inp_comment.get("dates"), - units=inp_comment.get("units"), - languages=inp_comment.get("languages"), - licenses=inp_comment.get("licenses"), - review=inp_comment.get("review"), - none=inp_comment.get("null"), - ) - - metadata = structure.OEPMetadata( - name=json_old.get("name"), - title=json_old.get("title"), - identifier=json_old["id"], - description=json_old.get("description"), - languages=json_old.get("language"), - keywords=json_old.get("keywords"), - publication_date=parse_date_or_none(json_old.get("publicationDate")), - context=context, - spatial=spatial, - temporal=temporal, - sources=sources, - terms_of_use=licenses, - contributions=contributors, - resources=resources, - review=review, - comment=comment, - ) - return metadata - - def assert_1_3_metastring(self, json_string: str): - """Checks string conformity to OEP Metadata Standard Version 1.3 - - Parameters - ---------- - json_string: str - The JSON string to be checked. - - Returns - ------- - bool - True if valid, Raises Exception otherwise. - """ - - keys = [ - "title", - "description", - "language", - "spatial", - "temporal", - "sources", - "license", - "contributions", - "resources", - "metadata_version", - ] - subkeys_spatial = ["location", "extent", "resolution"] - subkeys_temporal = ["reference_date", "start", "end", "resolution"] - subkeys_license = ["id", "name", "version", "url", "instruction", "copyright"] - object_subkeys = { - "spatial": subkeys_spatial, - "temporal": subkeys_temporal, - "license": subkeys_license, - } - subkeys_sources = [ - "name", - "description", - "url", - "license", - "copyright", - ] # in list of objects - subkeys_contributors = [ - "name", - "email", - "date", - "comment", - ] # in list of objects - subkeys_resources = ["name", "format", "fields"] # in list of objects - list_subkeys = { - "sources": subkeys_sources, - "contributions": subkeys_contributors, - "resources": subkeys_resources, - } - subkeys_resources_fields = ["name", "description", "unit"] # in list of objects - - json_dict = json.loads(json_string) - try: - # check if all top level keys are present - for i in keys: - if not i in json_dict.keys(): - raise Exception( - 'The String did not contain the key "{0}"'.format(i) - ) - # check for all keys in second level objects - for key in object_subkeys: - for subkey in object_subkeys[key]: - if not subkey in json_dict[key]: - raise Exception( - 'The "{0}" object did not contain a "{1}" key'.format( - key, subkey - ) - ) - # check for all objects in lists if they contain all required keys - for key in list_subkeys: - for list_element in json_dict[key]: - for subkey in list_subkeys[key]: - if not subkey in list_element: - raise Exception( - 'An object in "{0}" is missing a "{1}" key'.format( - key, subkey - ) - ) - except Exception as error: - print( - "The input String does not conform to metadatastring version 1.3 standard" - ) - print(error) - - # TODO make function check all subkeys as well - def has_rogue_keys(self, json_string): - """Checks all keys if they are part of the metadata specification. Gives warnings if not. - - Parameters - ---------- - json_string: str - The JSON string to be checked. - - Returns - ------- - """ - - json_dict = json.loads(json_string) - allowed_keys = [ - "title", - "description", - "language", - "spatial", - "temporal", - "sources", - "license", - "contributions", - "resources", - "metadata_version", - ] - for j in json_dict.keys(): - if not j in allowed_keys: - print('Warning: "{0}" is not among the allowed keys'.format(j)) - - def get_table_name(self, metadata_file): - """Provides the tablename information from the metadata_file - - Parameters - ---------- - metadata_file: str - The metadata script from where the tablename is extracted from. - - Returns - ------- - tablename: str - returns the tablename. - """ - - raise NotImplementedError - - -# TODO: Update parser below - - -class JSONParser_1_5(JSONParser): - def is_valid(self, inp: dict, schema=OEMETADATA_LATEST_SCHEMA): - # 1 - valid JSON? - if isinstance(inp, str): - try: - jsn = json.loads(inp, encode="utf-8") - except ValueError: - return False - else: - jsn = inp - - # 2 - valid OEMETADATA - try: - validator = self.get_json_validator(schema) - validator.validate(jsn) - return True - except ValidationError: - return False - - def parse_from_string( - self, - string: str, - load_args=None, - parse_args=None, - load_kwargs=None, - parse_kwargs=None, - ) -> oem_v15.OEPMetadata: - """ - Parse a string into :class:`~omi.oem_structures.oem_v15.OEPMetadata` - - Parameters - ---------- - string - - Returns - ------- - - """ - return self.parse( - self.load_string(string, *(load_args or []), **(load_kwargs or {})), - *(parse_args or []), - **(parse_kwargs or {}), - ) - - def get_any_value_not_none( - self, - element: dict, - keys, - get_return_default=None, # keys: list[str] - reove as not support by py3.8 - ): - """ - Get the value for a key in a dict - but try multiple key names, in - case they have changed in earlier oemetadata versions. - - Args: - element (dict): dict element of the input metadata - keys (list[str]): list of key name options - get_return_default (_type_, optional): A default return value if key is not present. Defaults to None. - - Returns: - any: By default it is the value at the key or None - but can be any as the value is not strict. - """ - - for key_name in keys: - _element = element.get(key_name, get_return_default) - if _element is None: - continue - - return _element - - def parse_term_of_use(self, old_license: dict): - return oem_v15.TermsOfUse( - lic=oem_v15.License( - name=old_license.get("name"), - title=old_license.get("title"), - path=old_license.get("path"), - ), - instruction=old_license.get("instruction"), - attribution=old_license.get("attribution"), - ) - - def ensure_json_keys_lowercase(json_old: dict): - element = json_old # element must be part of json_old not hole json_old - if isinstance(element, dict): - pass - - if isinstance(element, list): - pass - - def parse(self, json_old: dict, *args, **kwargs): - """_summary_ - - Args: - json_old (dict): _description_ - - Raises: - ParserException: _description_ - ParserException: _description_ - ParserException: _description_ - - Returns: - _type_: _description_ - """ - - if "id" not in json_old: - raise ParserException("metadata string does not contain an id") - - # filling the subject section - old_subjects = json_old.get("subject") - if old_subjects is None: - subject = None - else: - subject = [ - oem_v15.Subject( - name=old_subject.get("name"), path=old_subject.get("path") - ) - for old_subject in old_subjects - ] - - # context section - inp_context: dict = json_old.get("context") - if inp_context is None: - context = None - else: - funding_agency = None - if "fundingAgency" in inp_context: - funding_agency = oem_v15.Agency( - name=inp_context.get("fundingAgency"), - logo=inp_context.get("fundingAgencyLogo"), - ) - - context = oem_v15.Context( - homepage=inp_context.get("homepage"), - documentation=inp_context.get("documentation"), - source_code=inp_context.get("sourceCode"), - contact=inp_context.get("contact"), - grant_number=inp_context.get("grantNo"), - funding_agency=funding_agency, - publisher=oem_v15.Agency(logo=inp_context.get("publisherLogo")) - if "publisherLogo" in inp_context - else None, - ) - - # filling the spatial section - old_spatial: dict = json_old.get("spatial") - if old_spatial is None: - spatial = None - else: - spatial = oem_v15.Spatial( - location=old_spatial.get("location"), - extent=old_spatial.get("extent"), - resolution=old_spatial.get("resolution"), - ) - - # filling the temporal section - inp_temporal: dict = json_old.get("temporal") - if inp_temporal is None: - temporal = None - else: - inp_timeseries: dict = inp_temporal.get("timeseries", []) - if inp_timeseries is None: - timeseries = None - else: - timeseries = [ - oem_v15.Timeseries( - start=parse_date_or_none(ts.get("start")), - end=parse_date_or_none(ts.get("end")), - resolution=ts.get("resolution"), - ts_orientation=oem_v15.TimestampOrientation.create( - ts.get("alignment") - ) - if "alignment" in ts and ts["alignment"] is not None - else None, - aggregation=ts.get("aggregationType"), - ) - for ts in inp_timeseries - ] - temporal = oem_v15.Temporal( - reference_date=parse_date_or_none(inp_temporal.get("referenceDate")), - # TODO: does ** kwargs work on list? - timeseries_collection=timeseries, - ) - - def parse_sources_lincese_including_former_key_names(element: dict): - licenses_new = "licenses" - licenses_old = "license" - - if isinstance(element.get(licenses_new), list): - return [self.parse_term_of_use(l) for l in element.get(licenses_new)] - - if isinstance(element.get(licenses_old), str): - name = element.get(licenses_old) - - # avoide empty structures like [{}] - if name is None: - _result = [] - else: - from_13_license = oem_v15.License(name=name) - _result = [oem_v15.TermsOfUse(lic=from_13_license)] - - return _result - - def parse_source_including_former_key_names(key: dict): - # sources key name options - including key names pre oem v1.4 - key_name_options = { - "title_equal": ["title", "name"], - "path_equal": ["path", "url"], - "licenses_equal": ["licenses", "license"], - } - - source = oem_v15.Source( - title=self.get_any_value_not_none( - element=key, keys=key_name_options.get("title_equal") - ), - description=key.get("description"), - path=self.get_any_value_not_none( - element=key, keys=key_name_options.get("path_equal") - ), - licenses=parse_sources_lincese_including_former_key_names(element=key), - ) - - return source - - # filling the source section - # expected to be a list but can also be a dict in old versions - old_sources: list = json_old.get("sources") - if old_sources is None: - sources = None - else: - sources = [ - parse_source_including_former_key_names(key=old_source) - for old_source in old_sources - ] - - def parse_old_licenses_including_former_key_names(element: dict): - """ - Parse license from imput data - also handle key name variations from - early oemetadata versions. - """ - key_name_options = { - "licenses_equal": ["licenses", "license"], - } - - return self.get_any_value_not_none( - element, key_name_options.get("licenses_equal") - ) - - def parse_license_including_former_structure(licenses_element): - """ - The lincences key was got a structural differnece in former oemetada versions. - In Version 1.3 the key was called lincense and was a singe object/dict, in the - current version this key is calles licences and is a list of objects/dicts. - Also the key names in the dicht are deviating. - """ - if isinstance(licenses_element, list): - _result = [ - self.parse_term_of_use(old_license) for old_license in old_licenses - ] - - if isinstance(licenses_element, dict): - _mapping_former_keys = { - "name": licenses_element.get("id"), - "title": licenses_element.get("name"), - "path": licenses_element.get("url"), - "instruction": licenses_element.get("instruction"), - "attribution": licenses_element.get("copyright"), - } - - _result = [self.parse_term_of_use(old_license=_mapping_former_keys)] - - return _result - - # filling the license section - old_licenses = parse_old_licenses_including_former_key_names(element=json_old) - if old_licenses is None: - licenses = None - else: - licenses = parse_license_including_former_structure( - licenses_element=old_licenses - ) - - # filling the contributers section - old_contributors = json_old.get("contributors") - if old_contributors is None: - contributors = None - else: - contributors = [ - oem_v15.Contribution( - contributor=oem_v15.Person( - name=self.get_any_value_not_none( - element=old_contributor, keys=["title", "name"] - ), - email=old_contributor.get("email"), - ), - date=parse_date_or_none( - old_contributor.get("date"), "contributors.data", cont_element - ), - obj=old_contributor.get("object"), - comment=old_contributor.get("comment"), - ) - for cont_element, old_contributor in enumerate(old_contributors) - ] - - # extending with script-user information - old_resources = json_old.get("resources") - if old_resources is None: - resources = None - # Code added to raise exception when resource is empty - else: - if len(old_resources) == 0: - raise ParserException( - "The resources field is empty! Please provide a description of you data resources e.g. a table schema. See https://github.com/OpenEnergyPlatform/oemetadata/blob/master/metadata/latest/metadata_key_description.md#resource-keys." - ) - resources = [] - for resource in old_resources: - old_schema = resource.get("schema") - if old_schema is None: - schema = None - else: - # filling the fields section - old_fields = old_schema.get("fields") - if old_fields is None: - fields = None - logging.info(f"Parse fields from: {old_fields}") - else: - fields = [] - - for field in old_fields: - # filling the is about section - old_is_abouts = field.get("isAbout") - if old_is_abouts is None: - isAbout = None - else: - isAbout = [ - oem_v15.IsAbout( - name=old_is_about.get("name"), - path=old_is_about.get("path"), - ) - for old_is_about in old_is_abouts - ] - - # filling the value reference section - old_value_references = field.get("valueReference") - if old_value_references is None: - valueReference = None - else: - valueReference = [ - oem_v15.ValueReference( - value=old_value_reference.get("value"), - name=old_value_reference.get("name"), - path=old_value_reference.get("path"), - ) - for old_value_reference in old_value_references - ] - - fields.append( - oem_v15.Field( - name=field.get("name"), - description=field.get("description"), - field_type=field.get("type"), - isAbout=isAbout, - valueReference=valueReference, - unit=field.get("unit"), - ) - ) - - field_dict = {field.name: field for field in fields or []} - old_foreign_keys = old_schema.get("foreignKeys", []) - foreign_keys = [] - for fk in old_foreign_keys: - old_reference = fk.get("reference") - if old_reference is None: - raise ParserException( - "The Foreign key you provided is missing reference information:", - fk, - ) - source_fields = [ - field_dict[field_name] - for field_name in fk.get("fields", []) - ] - old_referenced_fields = old_reference.get("fields") - if old_referenced_fields is None: - referenced_fields = None - else: - referenced_fields = [ - oem_v15.Field(name=fk_field) - for fk_field in old_referenced_fields - ] - referenced_resource = oem_v15.Resource( - name=old_reference.get("resource"), - schema=oem_v15.Schema(fields=referenced_fields), - ) - for rf in referenced_fields: - rf.resource = referenced_resource - references = [ - oem_v15.Reference(s, t) - for s, t in zip(source_fields, referenced_fields) - ] - foreign_keys.append(oem_v15.ForeignKey(references=references)) - schema = oem_v15.Schema( - fields=fields, - primary_key=resource["schema"].get("primaryKey"), - foreign_keys=foreign_keys, - ) - - old_dialect = resource.get("dialect") - if old_dialect is None: - dialect = None - else: - dialect = oem_v15.Dialect( - delimiter=resource["dialect"].get("delimiter"), - decimal_separator=resource["dialect"].get("decimalSeparator"), - ) - resources.append( - oem_v15.Resource( - profile=resource.get("profile"), - name=resource.get("name"), - path=resource.get("path"), - resource_format=resource.get("format"), - encoding=resource.get("encoding"), - schema=schema, - dialect=dialect, - ) - ) - - inp_review = json_old.get("review") - if inp_review is None: - review = None - else: - review = oem_v15.Review( - path=inp_review.get("path"), badge=inp_review.get("badge") - ) - - inp_comment = json_old.get("_comment") - if inp_comment is None: - comment = None - else: - comment = oem_v15.MetaComment( - metadata_info=inp_comment.get("metadata"), - dates=inp_comment.get("dates"), - units=inp_comment.get("units"), - languages=inp_comment.get("languages"), - licenses=inp_comment.get("licenses"), - review=inp_comment.get("review"), - null=inp_comment.get("null"), - todo=inp_comment.get("todo"), - ) - - metadata = oem_v15.OEPMetadata( - name=json_old.get("name"), - title=json_old.get("title"), - identifier=json_old["id"], - description=json_old.get("description"), - subject=subject, - languages=json_old.get("language"), - keywords=json_old.get("keywords"), - publication_date=parse_date_or_none(json_old.get("publicationDate")), - context=context, - spatial=spatial, - temporal=temporal, - sources=sources, - terms_of_use=licenses, - contributions=contributors, - resources=resources, - databus_identifier=json_old.get("@id"), - databus_context=json_old.get("@context"), - review=review, - comment=comment, - ) - return metadata - - # TODO make function check all subkeys as well - def has_rogue_keys(self, json_string): - """Checks all keys if they are part of the metadata specification. Gives warnings if not. - - Parameters - ---------- - json_string: str - The JSON string to be checked. - - Returns - ------- - """ - - json_dict = json.loads(json_string) - allowed_keys = [ - "title", - "description", - "language", - "spatial", - "temporal", - "sources", - "license", - "contributions", - "resources", - "metadata_version", - ] - for j in json_dict.keys(): - if not j in allowed_keys: - print('Warning: "{0}" is not among the allowed keys'.format(j)) - - def get_table_name(self, metadata_file): - """Provides the tablename information from the metadata_file - - Parameters - ---------- - metadata_file: str - The metadata script from where the tablename is extracted from. - - Returns - ------- - tablename: str - returns the tablename. - """ - - raise NotImplementedError diff --git a/src/omi/dialects/oep/renderer.py b/src/omi/dialects/oep/renderer.py deleted file mode 100644 index 5ace540..0000000 --- a/src/omi/dialects/oep/renderer.py +++ /dev/null @@ -1,84 +0,0 @@ -import json -from collections import OrderedDict - -from omi.dialects.base.renderer import Renderer - - -class JSONRenderer(json.JSONEncoder, Renderer): - """ - This enconder sets up a structured oder of the json string when transforming - it from a python OrderedDict - """ - - def __init__(self, *args, **kwargs): - super(JSONRenderer, self).__init__(*args, **kwargs) - self.current_indent = 0 - self.current_indent_str = "" - - def encode(self, o): - # Special Processing for lists - if isinstance(o, (list, tuple)): - primitives_only = True - for item in o: - if isinstance(item, (list, tuple, OrderedDict)): - primitives_only = False - break - output = [] - if primitives_only: - for item in o: - output.append(json.dumps(item, ensure_ascii=False)) - return "[ " + ", ".join(output) + " ]" - else: - self.current_indent += 2 - self.current_indent_str = "".join( - [" " for x in range(self.current_indent)] - ) - liste = [] - for item in o: - output = [] - # This is performed if in the list is a OrderedDict - if isinstance(item, OrderedDict): - for key, value in item.items(): - output.append(json.dumps(key) + ": " + self.encode(value)) - - liste.append( - "\n" - + 2 * self.current_indent_str - + "{" - + (",\n" + 2 * self.current_indent_str).join(output) - + "}" - ) - - else: - raise AssertionError( - "Only OrderedDicts in lists are properly structured. Please redefine it in the encode function." - ) - output.append(self.current_indent_str + self.encode(item)) - return "[\n" + ",".join(output) + "]" - - self.current_indent -= 2 - self.current_indent_str = "".join( - [" " for x in range(self.current_indent)] - ) - - return "[" + ",".join(liste) + "]" - - elif isinstance(o, OrderedDict): - output = [] - self.current_indent += 4 - self.current_indent_str = "".join([" " for x in range(self.current_indent)]) - for key, value in o.items(): - output.append( - self.current_indent_str - + json.dumps(key) - + ": " - + self.encode(value) - ) - self.current_indent -= 4 - self.current_indent_str = "".join([" " for x in range(self.current_indent)]) - return "{\n" + ",\n".join(output) + "}" - else: - return json.dumps(o, ensure_ascii=False) - - def render(self, inp, *args, **kwargs): - return self.encode(inp) diff --git a/src/omi/dialects/rdf/__init__.py b/src/omi/dialects/rdf/__init__.py deleted file mode 100644 index f72e61b..0000000 --- a/src/omi/dialects/rdf/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from omi.dialects.rdf.dialect import OEP_V_1_4_RDF_Dialect diff --git a/src/omi/dialects/rdf/compiler.py b/src/omi/dialects/rdf/compiler.py deleted file mode 100644 index e63829a..0000000 --- a/src/omi/dialects/rdf/compiler.py +++ /dev/null @@ -1,405 +0,0 @@ -from typing import Dict -from typing import Tuple - -from rdflib import BNode -from rdflib import Graph -from rdflib import Literal -from rdflib import URIRef -from rdflib.graph import Node -from rdflib.namespace import DCTERMS -from rdflib.namespace import FOAF -from rdflib.namespace import RDF -from rdflib.namespace import XSD - -from omi import structure -from omi.dialects.base.compiler import Compiler -from omi.dialects.rdf.licenses import LICENSE_DICT -from omi.dialects.rdf.namespace import ADMS -from omi.dialects.rdf.namespace import DCAT -from omi.dialects.rdf.namespace import DCATDE -from omi.dialects.rdf.namespace import OEO -from omi.dialects.rdf.namespace import SCHEMA -from omi.dialects.rdf.namespace import SKOS -from omi.dialects.rdf.namespace import SPDX - -LANG_DICT = { - "eng": "http://publications.europa.eu/resource/authority/language/ENG", - "en-GB": "http://publications.europa.eu/resource/authority/language/ENG", - "ger": "http://publications.europa.eu/resource/authority/language/GER", - "en-US": "", - "de-DE": "http://publications.europa.eu/resource/authority/language/GER", - "fr-FR": "", -} - - -class RDFCompiler(Compiler): - def __init__(self, graph: Graph = None): - if graph is None: - self.graph = Graph() - self.graph.namespace_manager.bind("foaf", FOAF) - self.graph.namespace_manager.bind("dct", DCTERMS) - self.graph.namespace_manager.bind("dcat", DCAT) - self.graph.namespace_manager.bind("dcatde", DCATDE) - self.graph.namespace_manager.bind("oeo", OEO) - self.graph.namespace_manager.bind("schema", SCHEMA) - self.graph.namespace_manager.bind("skos", SKOS) - self.graph.namespace_manager.bind("adms", ADMS) - self.graph.namespace_manager.bind("spdx", SPDX) - else: - self.graph = graph - - def visit_agency(self, agency: structure.Agency, *args, **kwargs): - node = BNode() - self._add_literal_or_None(node, DCTERMS.title, agency.name) - self._add_literal_or_None(node, OEO.has_logo, agency.logo) - return node - - def visit_context(self, context: structure.Context, *args, **kwargs): - - return ( - Literal(context.homepage), - Literal(context.contact), - Literal(context.documentation), - Literal(context.source_code), - Literal(context.grant_number), - self.visit(context.funding_agency), - self.visit(context.publisher), - ) - - def visit_person(self, person: structure.Person, *args, **kwargs): - - node = BNode() - self.graph.add((node, RDF.type, FOAF.Person)) - self._add_literal_or_None(node, FOAF.name, person.name) - self._add_literal_or_None(node, FOAF.mbox, person.email) - return node - - def visit_contribution(self, contribution: structure.Contribution, *args, **kwargs): - c = BNode() - self.graph.add( - ( - c, - DCTERMS.contributor, - self.visit(contribution.contributor, *args, **kwargs), - ) - ) - self._add_literal_or_None( - c, OEO.date, contribution.date.strftime("%Y-%m-%d"), datatype=XSD.date - ) - self._add_literal_or_None(c, OEO.comment, contribution.comment) - self._add_literal_or_None(c, OEO.object, contribution.object) - return c - - def visit_language(self, language: structure.Language, *args, **kwargs): - return URIRef(LANG_DICT[language]) - - def visit_spatial(self, spatial: structure.Spatial, *args, **kwargs): - node = BNode() - self._add_literal_or_None(node, SKOS.prefLabel, spatial.extent) - self._add_literal_or_None(node, OEO.has_spatial_resolution, spatial.resolution) - self._add_literal_or_None(node, OEO.location, spatial.location) - return node - - def visit_temporal(self, temporal: structure.Temporal, *args, **kwargs): - node = BNode() - self.graph.add((node, RDF.type, DCTERMS.PeriodOfTime)) - self._add_literal_or_None(node, SCHEMA.startDate, temporal.ts_start) - self._add_literal_or_None(node, SCHEMA.endDate, temporal.ts_end) - self._add_literal_or_None(node, OEO.has_time_resolution, temporal.ts_resolution) - self._add_literal_or_None(node, OEO.referenceDate, temporal.reference_date) - self.graph.add( - (node, OEO.has_timestamp_alignment, self.visit(temporal.ts_orientation)) - ) - self._add_literal_or_None(node, OEO.uses_aggregation, temporal.aggregation) - return node - - def visit_timestamp_orientation( - self, ts_orientation: structure.TimestampOrientation, *args, **kwargs - ): - if ts_orientation == structure.TimestampOrientation.left: - return OEO.left_orientation - elif ts_orientation == structure.TimestampOrientation.middle: - return OEO.middle_orientation - elif ts_orientation == structure.TimestampOrientation.right: - return OEO.right_orientation - else: - raise Exception("Unknown timestamp orientation") - - def visit_source(self, source: structure.Source, *args, **kwargs): - node = BNode() - self._add_literal_or_None(node, DCTERMS.title, source.title) - self._add_literal_or_None(node, DCTERMS.description, source.description) - self._add_literal_or_None(node, FOAF.page, source.path) - for l in source.licenses: - li = self.visit(l, **kwargs) - self.graph.add((node, OEO.has_terms_of_use, li)) - return node - - def visit_terms_of_use(self, tou: structure.TermsOfUse, *args, **kwargs): - node = BNode() - self._add_literal_or_None( - node, DCATDE.licenseAttributionByText, tou.attribution - ) - self._add_literal_or_None(node, OEO.has_instruction, tou.instruction) - self.graph.add((node, DCAT.license, self.visit(tou.license, **kwargs))) - return node - - def visit_license(self, lic: structure.License, *args, license_dict=None, **kwargs): - if False: # lic.name in LICENSE_DICT: - li = URIRef(LICENSE_DICT[lic.identifier]) - else: - if license_dict is not None and lic.identifier in license_dict: - li = license_dict[lic.identifier] - else: - li = BNode() - self.graph.add((li, RDF.type, DCAT.LicenseDocument)) - if lic.other_references: - for ref in lic.other_references: - self._add_literal_or_None(li, SPDX.seeAlso, ref) - self._add_literal_or_None(li, FOAF.page, lic.path) - self._add_literal_or_None(li, SPDX.licenseId, lic.identifier) - if lic.text: - self._add_literal_or_None(li, SPDX.licenseText, lic.text) - self._add_literal_or_None(li, SPDX.name, lic.name) - if license_dict is not None and lic.identifier is not None: - license_dict[lic.identifier] = li - return li - - def visit_resource( - self, - resource: structure.Resource, - *args, - resource_dict: Dict[str, Tuple[Node, Dict[str, Node]]] = None, - **kwargs - ): - s = BNode() - self.graph.add((s, RDF.type, DCAT.Distribution)) - self._add_literal_or_None(s, DCTERMS.title, resource.name) - self._add_literal_or_None(s, DCAT.accessURL, resource.path) - self._add_literal_or_None(s, OEO.has_format, resource.format) # dct:format ? - self._add_literal_or_None(s, OEO.profile, resource.profile) - self._add_literal_or_None(s, OEO.encoding, resource.encoding) - if resource.dialect is not None: - self.graph.add((s, OEO.has_dialect, self.visit(resource.dialect))) - fields, pks, fks = self.visit(resource.schema, s, resource_dict=resource_dict) - for f in fields: - self.graph.add((s, OEO.field, f)) - for pk in pks: - self.graph.add((s, OEO.primaryKey, pk)) - for fk in fks: - self.graph.add((s, OEO.has_foreignKey, fk)) - return s - - def visit_schema( - self, - schema: structure.Schema, - *args, - resource_dict: Dict[str, Tuple[Node, Dict[str, Node]]] = None, - **kwargs - ): - resource_node = args[0] - field_dict = dict() - fields = [] - resource_dict = resource_dict or dict() - for field in schema.fields: - fnode = self.visit(field, *args, **kwargs) - fields.append(fnode) - field_dict[field.name] = fnode - - pks = [field_dict[pk] for pk in schema.primary_key or []] - - resource_name = schema.fields[0].resource.name - - if resource_name in resource_dict: - resource_dict[resource_name][1].update(field_dict) - else: - resource_dict[resource_name] = (resource_node, field_dict) - - fks = [ - self.visit(fk, *args, resource_dict=resource_dict, **kwargs) - for fk in schema.foreign_keys or [] - ] - - return fields, pks, fks - - def visit_dialect(self, dialect: structure.Dialect, *args, **kwargs): - node = BNode() - self._add_literal_or_None(node, OEO.delimiter, dialect.delimiter) - self._add_literal_or_None(node, OEO.decimalSeparator, dialect.decimal_separator) - return node - - def visit_field(self, field: structure.Field, *args, **kwargs): - field_uri = BNode() - self.graph.add((field_uri, RDF.type, OEO.DatabaseField)) - self._add_literal_or_None(field_uri, DCTERMS.title, field.name) - self._add_literal_or_None(field_uri, DCTERMS.description, field.description) - self._add_literal_or_None(field_uri, OEO.type, field.type) - self._add_literal_or_None(field_uri, OEO.unit, field.unit) - return field_uri - - def visit_foreign_key( - self, foreign_key: structure.ForeignKey, *args, resource_dict=None, **kwargs - ): - fk_node = BNode() - for r in foreign_key.references: - self.graph.add( - ( - fk_node, - OEO.has_reference, - self.visit(r, *args, resource_dict=resource_dict, **kwargs), - ) - ) - return fk_node - - def visit_reference( - self, - reference: structure.Reference, - *args, - resource_dict: Dict[str, Tuple[Node, Dict[str, Node]]] = None, - **kwargs - ): - r_node = BNode() - self.graph.add( - (r_node, OEO.has_source, self._get_field(reference.source, resource_dict)) - ) - target = self._get_or_create_field( - reference.target, resource_dict, *args, **kwargs - ) - self.graph.add((r_node, OEO.has_target, target)) - return r_node - - def visit_review(self, review: structure.Review, *args, **kwargs): - node = BNode() - self.graph.add((node, FOAF.page, URIRef(review.path))) - self._add_literal_or_None(node, OEO.has_badge, review.badge) - return node - - def visit_meta_comment(self, comment: structure.MetaComment, *args, **kwargs): - com = BNode() - self._add_literal_or_None(com, OEO.metadata_info, comment.metadata_info) - self._add_literal_or_None(com, OEO.dates_info, comment.dates) - self._add_literal_or_None(com, OEO.units_info, comment.units) - self._add_literal_or_None(com, OEO.languages_info, comment.languages) - self._add_literal_or_None(com, OEO.licenses_info, comment.licenses) - self._add_literal_or_None(com, OEO.review_info, comment.review) - self._add_literal_or_None(com, OEO.none_info, comment.none) - return com - - def visit_metadata(self, metadata: structure.OEPMetadata, *args, **kwargs): - datasetURI = URIRef(metadata.identifier) - - license_dict = kwargs.get("license_dict", {}) - - self.graph.add((datasetURI, RDF.type, DCAT.Dataset)) - self._add_literal_or_None(datasetURI, ADMS.Identifier, metadata.name) - self._add_literal_or_None(datasetURI, DCTERMS.title, metadata.title) - self._add_literal_or_None(datasetURI, DCTERMS.description, metadata.description) - - for lang in metadata.languages: - self._add_literal_or_None(datasetURI, DCTERMS.language, self.visit(lang)) - - for k in metadata.keywords: - self._add_literal_or_None(datasetURI, DCAT.keyword, k) - - self.graph.add( - ( - datasetURI, - OEO.publicationDate, - Literal( - metadata.publication_date.strftime("%Y-%m-%d"), datatype=XSD.date - ), - ) - ) - - homepage, contact, documentation, source_code, grant_number, funding_agency, publisher = self.visit( - metadata.context - ) - - self.graph.add((datasetURI, FOAF.homepage, homepage)) - self.graph.add((datasetURI, DCAT.contactpoint, contact)) - self.graph.add((datasetURI, OEO.documentation, documentation)) - self.graph.add((datasetURI, OEO.sourceCode, source_code)) - self.graph.add((datasetURI, OEO.grantNo, grant_number)) - - if funding_agency: - self.graph.add((datasetURI, OEO.has_funding_agency, funding_agency)) - - if publisher: - self.graph.add((datasetURI, OEO.has_publisher, publisher)) - - self.graph.add((datasetURI, DCTERMS.spatial, self.visit(metadata.spatial))) - self.graph.add((datasetURI, DCTERMS.temporal, self.visit(metadata.temporal))) - for s in metadata.sources: - self.graph.add( - (datasetURI, DCTERMS.source, self.visit(s, license_dict=license_dict)) - ) - for l in metadata.license: - self.graph.add( - ( - datasetURI, - OEO.has_terms_of_use, - self.visit(l, license_dict=license_dict), - ) - ) - - for c in metadata.contributions: - self.graph.add((datasetURI, OEO.has_contribution, self.visit(c))) - for r in metadata.resources: - self.graph.add((datasetURI, OEO.has_resource, self.visit(r))) - - self.graph.add((datasetURI, OEO.has_review, self.visit(metadata.review))) - - self.graph.add( - ( - datasetURI, - OEO.metadataLicense, - URIRef("https://creativecommons.org/publicdomain/zero/1.0/legalcode"), - ) - ) - - self.graph.add((datasetURI, OEO.comment, self.visit(metadata.comment))) - - return datasetURI - - def _get_or_create_field( - self, - field: structure.Field, - resource_dict: Dict[str, Tuple[Node, Dict[str, Node]]], - *args, - **kwargs - ): - try: - if field.resource.name not in resource_dict: - self.visit_resource(field.resource, resource_dict=resource_dict) - return self._get_field(field, resource_dict) - except FieldNotFoundError: - f = self.visit_field(field, *args, **kwargs) - res_node, field_dict = resource_dict[field.resource.name] - self.graph.add((res_node, OEO.field, f)) - field_dict[field.name] = f - return f - - def _get_field( - self, - field: structure.Field, - resource_dict: Dict[str, Tuple[Node, Dict[str, Node]]], - ): - res = resource_dict.get(field.resource.name) - if res is None: - raise ResourceNotFoundError(field.resource.name) - node = res[1].get(field.name) - if node is None: - raise FieldNotFoundError(field.name) - return node - - def _add_literal_or_None(self, subject: Node, predicate, obj: str, **kwargs): - if obj is not None: - self.graph.add((subject, predicate, Literal(obj, **kwargs))) - - -class FieldNotFoundError(Exception): - pass - - -class ResourceNotFoundError(Exception): - pass diff --git a/src/omi/dialects/rdf/dialect.py b/src/omi/dialects/rdf/dialect.py deleted file mode 100644 index 68b00e1..0000000 --- a/src/omi/dialects/rdf/dialect.py +++ /dev/null @@ -1,19 +0,0 @@ -from omi.dialects.base.dialect import Dialect -from omi.dialects.base.register import register -from omi.dialects.rdf.compiler import RDFCompiler -from omi.dialects.rdf.parser import RDFParser -from omi.dialects.rdf.renderer import GraphRenderer -from omi.structure import OEPMetadata - - -@register("oep-rdf-v1.4") -class OEP_V_1_4_RDF_Dialect(Dialect): - _parser = RDFParser - _compiler = RDFCompiler - _renderer = GraphRenderer - - def compile_and_render(self, obj: OEPMetadata, *args, **kwargs): - c = self._compiler() - r = self._renderer() - c.visit(obj, *args, **kwargs) - return r.render(c.graph, *args, **kwargs).decode("utf-8") diff --git a/src/omi/dialects/rdf/licenses.py b/src/omi/dialects/rdf/licenses.py deleted file mode 100644 index 6c08219..0000000 --- a/src/omi/dialects/rdf/licenses.py +++ /dev/null @@ -1,401 +0,0 @@ -import itertools - -SPDX_LICENSES = { - "0BSD": "https://spdx.org/licenses/0BSD.html", - "AAL": "https://spdx.org/licenses/AAL.html", - "ADSL": "https://spdx.org/licenses/ADSL.html", - "AFL-1.1": "https://spdx.org/licenses/AFL-1.1.html", - "AFL-1.2": "https://spdx.org/licenses/AFL-1.2.html", - "AFL-2.0": "https://spdx.org/licenses/AFL-2.0.html", - "AFL-2.1": "https://spdx.org/licenses/AFL-2.1.html", - "AFL-3.0": "https://spdx.org/licenses/AFL-3.0.html", - "AGPL-1.0": "https://spdx.org/licenses/AGPL-1.0.html", - "AGPL-1.0-only": "https://spdx.org/licenses/AGPL-1.0-only.html", - "AGPL-1.0-or-later": "https://spdx.org/licenses/AGPL-1.0-or-later.html", - "AGPL-3.0": "https://spdx.org/licenses/AGPL-3.0.html", - "AGPL-3.0-only": "https://spdx.org/licenses/AGPL-3.0-only.html", - "AGPL-3.0-or-later": "https://spdx.org/licenses/AGPL-3.0-or-later.html", - "AMDPLPA": "https://spdx.org/licenses/AMDPLPA.html", - "AML": "https://spdx.org/licenses/AML.html", - "AMPAS": "https://spdx.org/licenses/AMPAS.html", - "ANTLR-PD": "https://spdx.org/licenses/ANTLR-PD.html", - "APAFML": "https://spdx.org/licenses/APAFML.html", - "APL-1.0": "https://spdx.org/licenses/APL-1.0.html", - "APSL-1.0": "https://spdx.org/licenses/APSL-1.0.html", - "APSL-1.1": "https://spdx.org/licenses/APSL-1.1.html", - "APSL-1.2": "https://spdx.org/licenses/APSL-1.2.html", - "APSL-2.0": "https://spdx.org/licenses/APSL-2.0.html", - "Abstyles": "https://spdx.org/licenses/Abstyles.html", - "Adobe-2006": "https://spdx.org/licenses/Adobe-2006.html", - "Adobe-Glyph": "https://spdx.org/licenses/Adobe-Glyph.html", - "Afmparse": "https://spdx.org/licenses/Afmparse.html", - "Aladdin": "https://spdx.org/licenses/Aladdin.html", - "Apache-1.0": "https://spdx.org/licenses/Apache-1.0.html", - "Apache-1.1": "https://spdx.org/licenses/Apache-1.1.html", - "Apache-2.0": "https://spdx.org/licenses/Apache-2.0.html", - "Artistic-1.0": "https://spdx.org/licenses/Artistic-1.0.html", - "Artistic-1.0-Perl": "https://spdx.org/licenses/Artistic-1.0-Perl.html", - "Artistic-1.0-cl8": "https://spdx.org/licenses/Artistic-1.0-cl8.html", - "Artistic-2.0": "https://spdx.org/licenses/Artistic-2.0.html", - "BSD-1-Clause": "https://spdx.org/licenses/BSD-1-Clause.html", - "BSD-2-Clause": "https://spdx.org/licenses/BSD-2-Clause.html", - "BSD-2-Clause-FreeBSD": "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html", - "BSD-2-Clause-NetBSD": "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html", - "BSD-2-Clause-Patent": "https://spdx.org/licenses/BSD-2-Clause-Patent.html", - "BSD-3-Clause": "https://spdx.org/licenses/BSD-3-Clause.html", - "BSD-3-Clause-Attribution": "https://spdx.org/licenses/BSD-3-Clause-Attribution.html", - "BSD-3-Clause-Clear": "https://spdx.org/licenses/BSD-3-Clause-Clear.html", - "BSD-3-Clause-LBNL": "https://spdx.org/licenses/BSD-3-Clause-LBNL.html", - "BSD-3-Clause-No-Nuclear-License": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html", - "BSD-3-Clause-No-Nuclear-License-2014": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html", - "BSD-3-Clause-No-Nuclear-Warranty": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html", - "BSD-4-Clause": "https://spdx.org/licenses/BSD-4-Clause.html", - "BSD-4-Clause-UC": "https://spdx.org/licenses/BSD-4-Clause-UC.html", - "BSD-Protection": "https://spdx.org/licenses/BSD-Protection.html", - "BSD-Source-Code": "https://spdx.org/licenses/BSD-Source-Code.html", - "BSL-1.0": "https://spdx.org/licenses/BSL-1.0.html", - "Bahyph": "https://spdx.org/licenses/Bahyph.html", - "Barr": "https://spdx.org/licenses/Barr.html", - "Beerware": "https://spdx.org/licenses/Beerware.html", - "BitTorrent-1.0": "https://spdx.org/licenses/BitTorrent-1.0.html", - "BitTorrent-1.1": "https://spdx.org/licenses/BitTorrent-1.1.html", - "BlueOak-1.0.0": "https://spdx.org/licenses/BlueOak-1.0.0.html", - "Borceux": "https://spdx.org/licenses/Borceux.html", - "CATOSL-1.1": "https://spdx.org/licenses/CATOSL-1.1.html", - "CC-BY-1.0": "https://spdx.org/licenses/CC-BY-1.0.html", - "CC-BY-2.0": "https://spdx.org/licenses/CC-BY-2.0.html", - "CC-BY-2.5": "https://spdx.org/licenses/CC-BY-2.5.html", - "CC-BY-3.0": "https://spdx.org/licenses/CC-BY-3.0.html", - "CC-BY-4.0": "https://spdx.org/licenses/CC-BY-4.0.html", - "CC-BY-NC-1.0": "https://spdx.org/licenses/CC-BY-NC-1.0.html", - "CC-BY-NC-2.0": "https://spdx.org/licenses/CC-BY-NC-2.0.html", - "CC-BY-NC-2.5": "https://spdx.org/licenses/CC-BY-NC-2.5.html", - "CC-BY-NC-3.0": "https://spdx.org/licenses/CC-BY-NC-3.0.html", - "CC-BY-NC-4.0": "https://spdx.org/licenses/CC-BY-NC-4.0.html", - "CC-BY-NC-ND-1.0": "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html", - "CC-BY-NC-ND-2.0": "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html", - "CC-BY-NC-ND-2.5": "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html", - "CC-BY-NC-ND-3.0": "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html", - "CC-BY-NC-ND-4.0": "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html", - "CC-BY-NC-SA-1.0": "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html", - "CC-BY-NC-SA-2.0": "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html", - "CC-BY-NC-SA-2.5": "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html", - "CC-BY-NC-SA-3.0": "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html", - "CC-BY-NC-SA-4.0": "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html", - "CC-BY-ND-1.0": "https://spdx.org/licenses/CC-BY-ND-1.0.html", - "CC-BY-ND-2.0": "https://spdx.org/licenses/CC-BY-ND-2.0.html", - "CC-BY-ND-2.5": "https://spdx.org/licenses/CC-BY-ND-2.5.html", - "CC-BY-ND-3.0": "https://spdx.org/licenses/CC-BY-ND-3.0.html", - "CC-BY-ND-4.0": "https://spdx.org/licenses/CC-BY-ND-4.0.html", - "CC-BY-SA-1.0": "https://spdx.org/licenses/CC-BY-SA-1.0.html", - "CC-BY-SA-2.0": "https://spdx.org/licenses/CC-BY-SA-2.0.html", - "CC-BY-SA-2.5": "https://spdx.org/licenses/CC-BY-SA-2.5.html", - "CC-BY-SA-3.0": "https://spdx.org/licenses/CC-BY-SA-3.0.html", - "CC-BY-SA-4.0": "https://spdx.org/licenses/CC-BY-SA-4.0.html", - "CC0-1.0": "https://spdx.org/licenses/CC0-1.0.html", - "CDDL-1.0": "https://spdx.org/licenses/CDDL-1.0.html", - "CDDL-1.1": "https://spdx.org/licenses/CDDL-1.1.html", - "CDLA-Permissive-1.0": "https://spdx.org/licenses/CDLA-Permissive-1.0.html", - "CDLA-Sharing-1.0": "https://spdx.org/licenses/CDLA-Sharing-1.0.html", - "CECILL-1.0": "https://spdx.org/licenses/CECILL-1.0.html", - "CECILL-1.1": "https://spdx.org/licenses/CECILL-1.1.html", - "CECILL-2.0": "https://spdx.org/licenses/CECILL-2.0.html", - "CECILL-2.1": "https://spdx.org/licenses/CECILL-2.1.html", - "CECILL-B": "https://spdx.org/licenses/CECILL-B.html", - "CECILL-C": "https://spdx.org/licenses/CECILL-C.html", - "CERN-OHL-1.1": "https://spdx.org/licenses/CERN-OHL-1.1.html", - "CERN-OHL-1.2": "https://spdx.org/licenses/CERN-OHL-1.2.html", - "CNRI-Jython": "https://spdx.org/licenses/CNRI-Jython.html", - "CNRI-Python": "https://spdx.org/licenses/CNRI-Python.html", - "CNRI-Python-GPL-Compatible": "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.html", - "CPAL-1.0": "https://spdx.org/licenses/CPAL-1.0.html", - "CPL-1.0": "https://spdx.org/licenses/CPL-1.0.html", - "CPOL-1.02": "https://spdx.org/licenses/CPOL-1.02.html", - "CUA-OPL-1.0": "https://spdx.org/licenses/CUA-OPL-1.0.html", - "Caldera": "https://spdx.org/licenses/Caldera.html", - "ClArtistic": "https://spdx.org/licenses/ClArtistic.html", - "Condor-1.1": "https://spdx.org/licenses/Condor-1.1.html", - "Crossword": "https://spdx.org/licenses/Crossword.html", - "CrystalStacker": "https://spdx.org/licenses/CrystalStacker.html", - "Cube": "https://spdx.org/licenses/Cube.html", - "D-FSL-1.0": "https://spdx.org/licenses/D-FSL-1.0.html", - "DOC": "https://spdx.org/licenses/DOC.html", - "DSDP": "https://spdx.org/licenses/DSDP.html", - "Dotseqn": "https://spdx.org/licenses/Dotseqn.html", - "ECL-1.0": "https://spdx.org/licenses/ECL-1.0.html", - "ECL-2.0": "https://spdx.org/licenses/ECL-2.0.html", - "EFL-1.0": "https://spdx.org/licenses/EFL-1.0.html", - "EFL-2.0": "https://spdx.org/licenses/EFL-2.0.html", - "EPL-1.0": "https://spdx.org/licenses/EPL-1.0.html", - "EPL-2.0": "https://spdx.org/licenses/EPL-2.0.html", - "EUDatagrid": "https://spdx.org/licenses/EUDatagrid.html", - "EUPL-1.0": "https://spdx.org/licenses/EUPL-1.0.html", - "EUPL-1.1": "https://spdx.org/licenses/EUPL-1.1.html", - "EUPL-1.2": "https://spdx.org/licenses/EUPL-1.2.html", - "Entessa": "https://spdx.org/licenses/Entessa.html", - "ErlPL-1.1": "https://spdx.org/licenses/ErlPL-1.1.html", - "Eurosym": "https://spdx.org/licenses/Eurosym.html", - "FSFAP": "https://spdx.org/licenses/FSFAP.html", - "FSFUL": "https://spdx.org/licenses/FSFUL.html", - "FSFULLR": "https://spdx.org/licenses/FSFULLR.html", - "FTL": "https://spdx.org/licenses/FTL.html", - "Fair": "https://spdx.org/licenses/Fair.html", - "Frameworx-1.0": "https://spdx.org/licenses/Frameworx-1.0.html", - "FreeImage": "https://spdx.org/licenses/FreeImage.html", - "GFDL-1.1": "https://spdx.org/licenses/GFDL-1.1.html", - "GFDL-1.1-only": "https://spdx.org/licenses/GFDL-1.1-only.html", - "GFDL-1.1-or-later": "https://spdx.org/licenses/GFDL-1.1-or-later.html", - "GFDL-1.2": "https://spdx.org/licenses/GFDL-1.2.html", - "GFDL-1.2-only": "https://spdx.org/licenses/GFDL-1.2-only.html", - "GFDL-1.2-or-later": "https://spdx.org/licenses/GFDL-1.2-or-later.html", - "GFDL-1.3": "https://spdx.org/licenses/GFDL-1.3.html", - "GFDL-1.3-only": "https://spdx.org/licenses/GFDL-1.3-only.html", - "GFDL-1.3-or-later": "https://spdx.org/licenses/GFDL-1.3-or-later.html", - "GL2PS": "https://spdx.org/licenses/GL2PS.html", - "GPL-1.0": "https://spdx.org/licenses/GPL-1.0.html", - "GPL-1.0+": "https://spdx.org/licenses/GPL-1.0+.html", - "GPL-1.0-only": "https://spdx.org/licenses/GPL-1.0-only.html", - "GPL-1.0-or-later": "https://spdx.org/licenses/GPL-1.0-or-later.html", - "GPL-2.0": "https://spdx.org/licenses/GPL-2.0.html", - "GPL-2.0+": "https://spdx.org/licenses/GPL-2.0+.html", - "GPL-2.0-only": "https://spdx.org/licenses/GPL-2.0-only.html", - "GPL-2.0-or-later": "https://spdx.org/licenses/GPL-2.0-or-later.html", - "GPL-2.0-with-GCC-exception": "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html", - "GPL-2.0-with-autoconf-exception": "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html", - "GPL-2.0-with-bison-exception": "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html", - "GPL-2.0-with-classpath-exception": "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html", - "GPL-2.0-with-font-exception": "https://spdx.org/licenses/GPL-2.0-with-font-exception.html", - "GPL-3.0": "https://spdx.org/licenses/GPL-3.0.html", - "GPL-3.0+": "https://spdx.org/licenses/GPL-3.0+.html", - "GPL-3.0-only": "https://spdx.org/licenses/GPL-3.0-only.html", - "GPL-3.0-or-later": "https://spdx.org/licenses/GPL-3.0-or-later.html", - "GPL-3.0-with-GCC-exception": "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html", - "GPL-3.0-with-autoconf-exception": "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html", - "Giftware": "https://spdx.org/licenses/Giftware.html", - "Glide": "https://spdx.org/licenses/Glide.html", - "Glulxe": "https://spdx.org/licenses/Glulxe.html", - "HPND": "https://spdx.org/licenses/HPND.html", - "HPND-sell-variant": "https://spdx.org/licenses/HPND-sell-variant.html", - "HaskellReport": "https://spdx.org/licenses/HaskellReport.html", - "IBM-pibs": "https://spdx.org/licenses/IBM-pibs.html", - "ICU": "https://spdx.org/licenses/ICU.html", - "IJG": "https://spdx.org/licenses/IJG.html", - "IPA": "https://spdx.org/licenses/IPA.html", - "IPL-1.0": "https://spdx.org/licenses/IPL-1.0.html", - "ISC": "https://spdx.org/licenses/ISC.html", - "ImageMagick": "https://spdx.org/licenses/ImageMagick.html", - "Imlib2": "https://spdx.org/licenses/Imlib2.html", - "Info-ZIP": "https://spdx.org/licenses/Info-ZIP.html", - "Intel": "https://spdx.org/licenses/Intel.html", - "Intel-ACPI": "https://spdx.org/licenses/Intel-ACPI.html", - "Interbase-1.0": "https://spdx.org/licenses/Interbase-1.0.html", - "JPNIC": "https://spdx.org/licenses/JPNIC.html", - "JSON": "https://spdx.org/licenses/JSON.html", - "JasPer-2.0": "https://spdx.org/licenses/JasPer-2.0.html", - "LAL-1.2": "https://spdx.org/licenses/LAL-1.2.html", - "LAL-1.3": "https://spdx.org/licenses/LAL-1.3.html", - "LGPL-2.0": "https://spdx.org/licenses/LGPL-2.0.html", - "LGPL-2.0+": "https://spdx.org/licenses/LGPL-2.0+.html", - "LGPL-2.0-only": "https://spdx.org/licenses/LGPL-2.0-only.html", - "LGPL-2.0-or-later": "https://spdx.org/licenses/LGPL-2.0-or-later.html", - "LGPL-2.1": "https://spdx.org/licenses/LGPL-2.1.html", - "LGPL-2.1+": "https://spdx.org/licenses/LGPL-2.1+.html", - "LGPL-2.1-only": "https://spdx.org/licenses/LGPL-2.1-only.html", - "LGPL-2.1-or-later": "https://spdx.org/licenses/LGPL-2.1-or-later.html", - "LGPL-3.0": "https://spdx.org/licenses/LGPL-3.0.html", - "LGPL-3.0+": "https://spdx.org/licenses/LGPL-3.0+.html", - "LGPL-3.0-only": "https://spdx.org/licenses/LGPL-3.0-only.html", - "LGPL-3.0-or-later": "https://spdx.org/licenses/LGPL-3.0-or-later.html", - "LGPLLR": "https://spdx.org/licenses/LGPLLR.html", - "LPL-1.0": "https://spdx.org/licenses/LPL-1.0.html", - "LPL-1.02": "https://spdx.org/licenses/LPL-1.02.html", - "LPPL-1.0": "https://spdx.org/licenses/LPPL-1.0.html", - "LPPL-1.1": "https://spdx.org/licenses/LPPL-1.1.html", - "LPPL-1.2": "https://spdx.org/licenses/LPPL-1.2.html", - "LPPL-1.3a": "https://spdx.org/licenses/LPPL-1.3a.html", - "LPPL-1.3c": "https://spdx.org/licenses/LPPL-1.3c.html", - "Latex2e": "https://spdx.org/licenses/Latex2e.html", - "Leptonica": "https://spdx.org/licenses/Leptonica.html", - "LiLiQ-P-1.1": "https://spdx.org/licenses/LiLiQ-P-1.1.html", - "LiLiQ-R-1.1": "https://spdx.org/licenses/LiLiQ-R-1.1.html", - "LiLiQ-Rplus-1.1": "https://spdx.org/licenses/LiLiQ-Rplus-1.1.html", - "Libpng": "https://spdx.org/licenses/Libpng.html", - "Linux-OpenIB": "https://spdx.org/licenses/Linux-OpenIB.html", - "MIT": "https://spdx.org/licenses/MIT.html", - "MIT-0": "https://spdx.org/licenses/MIT-0.html", - "MIT-CMU": "https://spdx.org/licenses/MIT-CMU.html", - "MIT-advertising": "https://spdx.org/licenses/MIT-advertising.html", - "MIT-enna": "https://spdx.org/licenses/MIT-enna.html", - "MIT-feh": "https://spdx.org/licenses/MIT-feh.html", - "MITNFA": "https://spdx.org/licenses/MITNFA.html", - "MPL-1.0": "https://spdx.org/licenses/MPL-1.0.html", - "MPL-1.1": "https://spdx.org/licenses/MPL-1.1.html", - "MPL-2.0": "https://spdx.org/licenses/MPL-2.0.html", - "MPL-2.0-no-copyleft-exception": "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html", - "MS-PL": "https://spdx.org/licenses/MS-PL.html", - "MS-RL": "https://spdx.org/licenses/MS-RL.html", - "MTLL": "https://spdx.org/licenses/MTLL.html", - "MakeIndex": "https://spdx.org/licenses/MakeIndex.html", - "MirOS": "https://spdx.org/licenses/MirOS.html", - "Motosoto": "https://spdx.org/licenses/Motosoto.html", - "Multics": "https://spdx.org/licenses/Multics.html", - "Mup": "https://spdx.org/licenses/Mup.html", - "NASA-1.3": "https://spdx.org/licenses/NASA-1.3.html", - "NBPL-1.0": "https://spdx.org/licenses/NBPL-1.0.html", - "NCSA": "https://spdx.org/licenses/NCSA.html", - "NGPL": "https://spdx.org/licenses/NGPL.html", - "NLOD-1.0": "https://spdx.org/licenses/NLOD-1.0.html", - "NLPL": "https://spdx.org/licenses/NLPL.html", - "NOSL": "https://spdx.org/licenses/NOSL.html", - "NPL-1.0": "https://spdx.org/licenses/NPL-1.0.html", - "NPL-1.1": "https://spdx.org/licenses/NPL-1.1.html", - "NPOSL-3.0": "https://spdx.org/licenses/NPOSL-3.0.html", - "NRL": "https://spdx.org/licenses/NRL.html", - "NTP": "https://spdx.org/licenses/NTP.html", - "Naumen": "https://spdx.org/licenses/Naumen.html", - "Net-SNMP": "https://spdx.org/licenses/Net-SNMP.html", - "NetCDF": "https://spdx.org/licenses/NetCDF.html", - "Newsletr": "https://spdx.org/licenses/Newsletr.html", - "Nokia": "https://spdx.org/licenses/Nokia.html", - "Noweb": "https://spdx.org/licenses/Noweb.html", - "Nunit": "https://spdx.org/licenses/Nunit.html", - "OCCT-PL": "https://spdx.org/licenses/OCCT-PL.html", - "OCLC-2.0": "https://spdx.org/licenses/OCLC-2.0.html", - "ODC-By-1.0": "https://spdx.org/licenses/ODC-By-1.0.html", - "ODbL-1.0": "https://spdx.org/licenses/ODbL-1.0.html", - "OFL-1.0": "https://spdx.org/licenses/OFL-1.0.html", - "OFL-1.1": "https://spdx.org/licenses/OFL-1.1.html", - "OGL-UK-1.0": "https://spdx.org/licenses/OGL-UK-1.0.html", - "OGL-UK-2.0": "https://spdx.org/licenses/OGL-UK-2.0.html", - "OGL-UK-3.0": "https://spdx.org/licenses/OGL-UK-3.0.html", - "OGTSL": "https://spdx.org/licenses/OGTSL.html", - "OLDAP-1.1": "https://spdx.org/licenses/OLDAP-1.1.html", - "OLDAP-1.2": "https://spdx.org/licenses/OLDAP-1.2.html", - "OLDAP-1.3": "https://spdx.org/licenses/OLDAP-1.3.html", - "OLDAP-1.4": "https://spdx.org/licenses/OLDAP-1.4.html", - "OLDAP-2.0": "https://spdx.org/licenses/OLDAP-2.0.html", - "OLDAP-2.0.1": "https://spdx.org/licenses/OLDAP-2.0.1.html", - "OLDAP-2.1": "https://spdx.org/licenses/OLDAP-2.1.html", - "OLDAP-2.2": "https://spdx.org/licenses/OLDAP-2.2.html", - "OLDAP-2.2.1": "https://spdx.org/licenses/OLDAP-2.2.1.html", - "OLDAP-2.2.2": "https://spdx.org/licenses/OLDAP-2.2.2.html", - "OLDAP-2.3": "https://spdx.org/licenses/OLDAP-2.3.html", - "OLDAP-2.4": "https://spdx.org/licenses/OLDAP-2.4.html", - "OLDAP-2.5": "https://spdx.org/licenses/OLDAP-2.5.html", - "OLDAP-2.6": "https://spdx.org/licenses/OLDAP-2.6.html", - "OLDAP-2.7": "https://spdx.org/licenses/OLDAP-2.7.html", - "OLDAP-2.8": "https://spdx.org/licenses/OLDAP-2.8.html", - "OML": "https://spdx.org/licenses/OML.html", - "OPL-1.0": "https://spdx.org/licenses/OPL-1.0.html", - "OSET-PL-2.1": "https://spdx.org/licenses/OSET-PL-2.1.html", - "OSL-1.0": "https://spdx.org/licenses/OSL-1.0.html", - "OSL-1.1": "https://spdx.org/licenses/OSL-1.1.html", - "OSL-2.0": "https://spdx.org/licenses/OSL-2.0.html", - "OSL-2.1": "https://spdx.org/licenses/OSL-2.1.html", - "OSL-3.0": "https://spdx.org/licenses/OSL-3.0.html", - "OpenSSL": "https://spdx.org/licenses/OpenSSL.html", - "PDDL-1.0": "https://spdx.org/licenses/PDDL-1.0.html", - "PHP-3.0": "https://spdx.org/licenses/PHP-3.0.html", - "PHP-3.01": "https://spdx.org/licenses/PHP-3.01.html", - "Plexus": "https://spdx.org/licenses/Plexus.html", - "PostgreSQL": "https://spdx.org/licenses/PostgreSQL.html", - "Python-2.0": "https://spdx.org/licenses/Python-2.0.html", - "QPL-1.0": "https://spdx.org/licenses/QPL-1.0.html", - "Qhull": "https://spdx.org/licenses/Qhull.html", - "RHeCos-1.1": "https://spdx.org/licenses/RHeCos-1.1.html", - "RPL-1.1": "https://spdx.org/licenses/RPL-1.1.html", - "RPL-1.5": "https://spdx.org/licenses/RPL-1.5.html", - "RPSL-1.0": "https://spdx.org/licenses/RPSL-1.0.html", - "RSA-MD": "https://spdx.org/licenses/RSA-MD.html", - "RSCPL": "https://spdx.org/licenses/RSCPL.html", - "Rdisc": "https://spdx.org/licenses/Rdisc.html", - "Ruby": "https://spdx.org/licenses/Ruby.html", - "SAX-PD": "https://spdx.org/licenses/SAX-PD.html", - "SCEA": "https://spdx.org/licenses/SCEA.html", - "SGI-B-1.0": "https://spdx.org/licenses/SGI-B-1.0.html", - "SGI-B-1.1": "https://spdx.org/licenses/SGI-B-1.1.html", - "SGI-B-2.0": "https://spdx.org/licenses/SGI-B-2.0.html", - "SISSL": "https://spdx.org/licenses/SISSL.html", - "SISSL-1.2": "https://spdx.org/licenses/SISSL-1.2.html", - "SMLNJ": "https://spdx.org/licenses/SMLNJ.html", - "SMPPL": "https://spdx.org/licenses/SMPPL.html", - "SNIA": "https://spdx.org/licenses/SNIA.html", - "SPL-1.0": "https://spdx.org/licenses/SPL-1.0.html", - "SWL": "https://spdx.org/licenses/SWL.html", - "Saxpath": "https://spdx.org/licenses/Saxpath.html", - "Sendmail": "https://spdx.org/licenses/Sendmail.html", - "Sendmail-8.23": "https://spdx.org/licenses/Sendmail-8.23.html", - "SimPL-2.0": "https://spdx.org/licenses/SimPL-2.0.html", - "Sleepycat": "https://spdx.org/licenses/Sleepycat.html", - "Spencer-86": "https://spdx.org/licenses/Spencer-86.html", - "Spencer-94": "https://spdx.org/licenses/Spencer-94.html", - "Spencer-99": "https://spdx.org/licenses/Spencer-99.html", - "StandardML-NJ": "https://spdx.org/licenses/StandardML-NJ.html", - "SugarCRM-1.1.3": "https://spdx.org/licenses/SugarCRM-1.1.3.html", - "TAPR-OHL-1.0": "https://spdx.org/licenses/TAPR-OHL-1.0.html", - "TCL": "https://spdx.org/licenses/TCL.html", - "TCP-wrappers": "https://spdx.org/licenses/TCP-wrappers.html", - "TMate": "https://spdx.org/licenses/TMate.html", - "TORQUE-1.1": "https://spdx.org/licenses/TORQUE-1.1.html", - "TOSL": "https://spdx.org/licenses/TOSL.html", - "TU-Berlin-1.0": "https://spdx.org/licenses/TU-Berlin-1.0.html", - "TU-Berlin-2.0": "https://spdx.org/licenses/TU-Berlin-2.0.html", - "UPL-1.0": "https://spdx.org/licenses/UPL-1.0.html", - "Unicode-DFS-2015": "https://spdx.org/licenses/Unicode-DFS-2015.html", - "Unicode-DFS-2016": "https://spdx.org/licenses/Unicode-DFS-2016.html", - "Unicode-TOU": "https://spdx.org/licenses/Unicode-TOU.html", - "Unlicense": "https://spdx.org/licenses/Unlicense.html", - "VOSTROM": "https://spdx.org/licenses/VOSTROM.html", - "VSL-1.0": "https://spdx.org/licenses/VSL-1.0.html", - "Vim": "https://spdx.org/licenses/Vim.html", - "W3C": "https://spdx.org/licenses/W3C.html", - "W3C-19980720": "https://spdx.org/licenses/W3C-19980720.html", - "W3C-20150513": "https://spdx.org/licenses/W3C-20150513.html", - "WTFPL": "https://spdx.org/licenses/WTFPL.html", - "Watcom-1.0": "https://spdx.org/licenses/Watcom-1.0.html", - "Wsuipa": "https://spdx.org/licenses/Wsuipa.html", - "X11": "https://spdx.org/licenses/X11.html", - "XFree86-1.1": "https://spdx.org/licenses/XFree86-1.1.html", - "XSkat": "https://spdx.org/licenses/XSkat.html", - "Xerox": "https://spdx.org/licenses/Xerox.html", - "Xnet": "https://spdx.org/licenses/Xnet.html", - "YPL-1.0": "https://spdx.org/licenses/YPL-1.0.html", - "YPL-1.1": "https://spdx.org/licenses/YPL-1.1.html", - "ZPL-1.1": "https://spdx.org/licenses/ZPL-1.1.html", - "ZPL-2.0": "https://spdx.org/licenses/ZPL-2.0.html", - "ZPL-2.1": "https://spdx.org/licenses/ZPL-2.1.html", - "Zed": "https://spdx.org/licenses/Zed.html", - "Zend-2.0": "https://spdx.org/licenses/Zend-2.0.html", - "Zimbra-1.3": "https://spdx.org/licenses/Zimbra-1.3.html", - "Zimbra-1.4": "https://spdx.org/licenses/Zimbra-1.4.html", - "Zlib": "https://spdx.org/licenses/Zlib.html", - "bzip2-1.0.5": "https://spdx.org/licenses/bzip2-1.0.5.html", - "bzip2-1.0.6": "https://spdx.org/licenses/bzip2-1.0.6.html", - "copyleft-next-0.3.0": "https://spdx.org/licenses/copyleft-next-0.3.0.html", - "copyleft-next-0.3.1": "https://spdx.org/licenses/copyleft-next-0.3.1.html", - "curl": "https://spdx.org/licenses/curl.html", - "diffmark": "https://spdx.org/licenses/diffmark.html", - "dvipdfm": "https://spdx.org/licenses/dvipdfm.html", - "eCos-2.0": "https://spdx.org/licenses/eCos-2.0.html", - "eGenix": "https://spdx.org/licenses/eGenix.html", - "gSOAP-1.3b": "https://spdx.org/licenses/gSOAP-1.3b.html", - "gnuplot": "https://spdx.org/licenses/gnuplot.html", - "iMatix": "https://spdx.org/licenses/iMatix.html", - "libpng-2.0": "https://spdx.org/licenses/libpng-2.0.html", - "libtiff": "https://spdx.org/licenses/libtiff.html", - "mpich2": "https://spdx.org/licenses/mpich2.html", - "psfrag": "https://spdx.org/licenses/psfrag.html", - "psutils": "https://spdx.org/licenses/psutils.html", - "wxWindows": "https://spdx.org/licenses/wxWindows.html", - "xinetd": "https://spdx.org/licenses/xinetd.html", - "xpp": "https://spdx.org/licenses/xpp.html", - "zlib-acknowledgement": "https://spdx.org/licenses/zlib-acknowledgement.html", -} - -ALL_LICENSE_DICTS = [SPDX_LICENSES] - -LICENSE_DICT = dict( - itertools.chain.from_iterable(dct.items() for dct in ALL_LICENSE_DICTS) -) - -__all__ = [LICENSE_DICT] diff --git a/src/omi/dialects/rdf/namespace.py b/src/omi/dialects/rdf/namespace.py deleted file mode 100644 index a1989ad..0000000 --- a/src/omi/dialects/rdf/namespace.py +++ /dev/null @@ -1,9 +0,0 @@ -from rdflib import Namespace - -DCAT = Namespace("http://www.w3.org/ns/dcat#") -OEO = Namespace("http://openenergy-platform.org/ontology/v0.0.1/oeo/") -DCATDE = Namespace("http://dcat-ap.de/def/dcatde/") -SCHEMA = Namespace("http://schema.org/") -SKOS = Namespace("http://www.w3.org/2004/02/skos/core#") -SPDX = Namespace("http://spdx.org/rdf/terms#") -ADMS = Namespace("http://www.w3.org/ns/adms#") diff --git a/src/omi/dialects/rdf/parser.py b/src/omi/dialects/rdf/parser.py deleted file mode 100644 index 4cf0ab8..0000000 --- a/src/omi/dialects/rdf/parser.py +++ /dev/null @@ -1,346 +0,0 @@ -from typing import Dict -from typing import Iterable -from typing import Tuple - -from dateutil.parser import parse as parse_date -from rdflib import Graph -from rdflib.graph import Node -from rdflib.graph import URIRef -from rdflib.namespace import DCTERMS -from rdflib.namespace import FOAF -from rdflib.namespace import RDF -from rdflib.namespace import RDFS - -from omi import structure as struc -from omi.dialects.base.parser import Parser -from omi.dialects.rdf.namespace import ADMS -from omi.dialects.rdf.namespace import DCAT -from omi.dialects.rdf.namespace import DCATDE -from omi.dialects.rdf.namespace import OEO -from omi.dialects.rdf.namespace import SCHEMA -from omi.dialects.rdf.namespace import SKOS -from omi.dialects.rdf.namespace import SPDX - - -def _only(gen): - r = _one_or_none(gen) - if r is None: - raise Exception("No matching elements") - return r - - -def _one_str_or_none(gen): - r = _one_or_none(gen) - if r is None: - return None - return str(r) - - -def _one_or_none(gen): - l = list(gen) - if not l: - return None - if len(l) > 1: - raise Exception("Found more than one match:" + str(l)) - return l[0] - - -class RDFParser(Parser): - def load_string(self, string: str, *args, **kwargs): - g = Graph() - g.parse(data=string, format="ttl") - return g - - def parse(self, graph, *args, **kwargs): - for dataset in {s for s, _, _ in graph}.difference({o for _, _, o in graph}): - if dataset in graph.subjects(RDF.type, DCAT.Dataset): - return self.parse_metadata(graph, dataset) - - def parse_date(self, node: Node): - return parse_date(node) - - def parse_context(self, graph: Graph, parent: Node) -> struc.Context: - fa = _only(graph.objects(parent, OEO.has_funding_agency)) - kwargs = {} - if fa is not None: - kwargs["funding_agency"] = struc.Agency( - name=_one_str_or_none(graph.objects(fa, DCTERMS.title)), - logo=_one_str_or_none(graph.objects(fa, OEO.has_logo)), - ) - pa = _only(graph.objects(parent, OEO.has_publisher)) - if pa is not None: - kwargs["publisher"] = struc.Agency( - name=_one_str_or_none(graph.objects(pa, DCTERMS.title)), - logo=_one_str_or_none(graph.objects(pa, OEO.has_logo)), - ) - return struc.Context( - contact=_one_str_or_none(graph.objects(parent, DCAT.contactpoint)), - documentation=_one_str_or_none(graph.objects(parent, OEO.documentation)), - grant_number=_one_str_or_none(graph.objects(parent, OEO.grantNo)), - homepage=_one_str_or_none(graph.objects(parent, FOAF.homepage)), - source_code=_one_str_or_none(graph.objects(parent, OEO.sourceCode)), - **kwargs - ) - - def parse_contributor(self, graph: Graph, parent: Node) -> struc.Contribution: - return struc.Contribution( - contributor=self.parse_person( - graph, _only(graph.objects(parent, DCTERMS.contributor)) - ), - date=self.parse_date(_only(graph.objects(parent, OEO.date))), - obj=_one_str_or_none(graph.objects(parent, OEO.object)), - comment=_one_str_or_none(graph.objects(parent, OEO.comment)), - ) - - def parse_person(self, graph, parent: Node): - return struc.Person( - name=_one_str_or_none(graph.objects(parent, FOAF.name)), - email=_one_str_or_none(graph.objects(parent, FOAF.mbox)), - ) - - def parse_spatial(self, graph: Graph, parent: Node) -> struc.Spatial: - return struc.Spatial( - extent=_one_str_or_none(graph.objects(parent, SKOS.prefLabel)), - location=_one_str_or_none(graph.objects(parent, OEO.location)), - resolution=_one_str_or_none( - graph.objects(parent, OEO.has_spatial_resolution) - ), - ) - - def parse_temporal(self, graph: Graph, parent: Node) -> struc.Temporal: - - orientation = self.parse_timestamp_orientation( - _only(graph.objects(parent, OEO.has_timestamp_alignment)) - ) - - return struc.Temporal( - start=self.parse_date(_only(graph.objects(parent, SCHEMA.startDate))), - end=self.parse_date(_only(graph.objects(parent, SCHEMA.endDate))), - ts_orientation=orientation, - reference_date=self.parse_date( - _only(graph.objects(parent, OEO.referenceDate)) - ), - resolution=_one_str_or_none(graph.objects(parent, OEO.has_time_resolution)), - aggregation=_one_str_or_none(graph.objects(parent, OEO.uses_aggregation)), - ) - - def parse_timestamp_orientation(self, node): - if node == OEO.left_orientation: - return struc.TimestampOrientation.left - elif node == OEO.middle_orientation: - return struc.TimestampOrientation.middle - elif node == OEO.right_orientation: - return struc.TimestampOrientation.right - else: - raise Exception("Unknown timestamp orientation: {}".format(node)) - - def parse_source(self, graph: Graph, parent: Node) -> struc.Source: - return struc.Source( - title=_one_str_or_none(graph.objects(parent, DCTERMS.title)), - description=_one_str_or_none(graph.objects(parent, DCTERMS.description)), - path=_one_str_or_none(graph.objects(parent, FOAF.page)), - licenses=[ - self.parse_terms_of_use(graph, tos) - for tos in graph.objects(parent, OEO.has_terms_of_use) - ], - ) - - def parse_terms_of_use(self, graph: Graph, parent: Node) -> struc.TermsOfUse: - if isinstance(parent, URIRef): - return None - else: - - return struc.TermsOfUse( - lic=self.parse_license( - graph, _only(graph.objects(parent, DCAT.license)) - ), - attribution=str( - _only(graph.objects(parent, DCATDE.licenseAttributionByText)) - ), - instruction=_one_str_or_none( - graph.objects(parent, OEO.has_instruction) - ), - ) - - def parse_license(self, graph, parent: Node): - kw = dict() - for c in graph.objects(parent, RDFS.comment): - kw["comment"] = _one_str_or_none(c) - refs = list(graph.objects(parent, RDFS.seeAlso)) - return struc.License( - name=_one_str_or_none(graph.objects(parent, SPDX.name)), - identifier=_one_str_or_none(graph.objects(parent, SPDX.licenseId)), - path=_one_str_or_none(graph.objects(parent, FOAF.page)), - other_references=refs if refs else None, - text=_one_str_or_none(graph.objects(parent, SPDX.licenseText)), - **kw - ) - - def parse_resource( - self, - graph: Graph, - parent: Node, - resources: Dict[str, Tuple[struc.Resource, Dict[str, struc.Field]]] = None, - ) -> struc.Resource: - rname = _one_str_or_none(graph.objects(parent, DCTERMS.title)) - resources = resources or dict() - if resources and rname in resources: - return resources[rname][0] - else: - dialect_node = _one_or_none(graph.objects(parent, OEO.has_dialect)) - dialect = self.parse_dialect(graph, dialect_node) if dialect_node else None - r = struc.Resource( - dialect=dialect, - encoding=_one_str_or_none(graph.objects(parent, OEO.encoding)), - name=rname, - path=_one_str_or_none(graph.objects(parent, DCAT.accessURL)), - profile=_one_str_or_none(graph.objects(parent, OEO.profile)), - resource_format=_one_str_or_none(graph.objects(parent, OEO.has_format)), - schema=None, - ) - r_fields = {} - resources[rname] = r, r_fields - schema = self.parse_schema(graph, parent, resources=resources) - r.schema = schema - for f in schema.fields: - if f.name not in r_fields: - r_fields[f.name] = f - return r - - def parse_schema( - self, - graph: Graph, - parent: Node, - resources: Dict[str, Tuple[Node, Iterable[Node]]] = None, - ) -> struc.Schema: - return struc.Schema( - fields=[ - self.parse_field(graph, f) for f in graph.objects(parent, OEO.field) - ], - primary_key=[ - self.parse_field(graph, f).name - for f in graph.objects(parent, OEO.primaryKey) - ], - foreign_keys=[ - self.parse_foreign_key(graph, f, resources=resources) - for f in graph.objects(parent, OEO.has_foreignKey) - ], - ) - - def parse_dialect(self, graph: Graph, parent: Node) -> struc.Dialect: - delim = _one_or_none(graph.objects(parent, DCTERMS.delimiter)) - if delim is not None: - delim = str(delim) - return struc.Dialect( - decimal_separator=_one_str_or_none( - graph.objects(parent, OEO.decimalSeparator) - ), - delimiter=delim, - ) - - def parse_field(self, graph: Graph, parent: Node) -> struc.Field: - return struc.Field( - name=_one_str_or_none(graph.objects(parent, DCTERMS.title)), - unit=_one_str_or_none(graph.objects(parent, OEO.unit)), - field_type=_one_str_or_none(graph.objects(parent, OEO.type)), - description=_one_str_or_none(graph.objects(parent, DCTERMS.description)), - ) - - def parse_foreign_key( - self, - graph: Graph, - parent: Node, - resources: Dict[str, Tuple[Node, Iterable[Node]]] = None, - ) -> struc.ForeignKey: - return struc.ForeignKey( - references=[ - self.parse_reference(graph, r) - for r in graph.objects(parent, OEO.has_reference) - ] - ) - - def parse_reference( - self, - graph: Graph, - parent: Node, - resources: Dict[str, Tuple[Node, Iterable[Node]]] = None, - ) -> struc.Reference: - target_node = _only(graph.objects(parent, OEO.has_target)) - target_field = self.parse_field(graph, target_node) - target_resource = self.parse_resource( - graph, _only(graph.subjects(OEO.field, target_node)) - ) - target_field.resource = target_resource - return struc.Reference( - source=self.parse_field( - graph, _only(graph.objects(parent, OEO.has_source)) - ), - target=target_field, - ) - - def parse_review(self, graph: Graph, parent: Node) -> struc.Review: - return struc.Review( - badge=_one_str_or_none(graph.objects(parent, OEO.has_badge)), - path=_one_str_or_none(graph.objects(parent, FOAF.page)), - ) - - def parse_meta_comment(self, graph: Graph, parent: Node) -> struc.MetaComment: - return struc.MetaComment( - dates=_one_str_or_none(graph.objects(parent, OEO.dates_info)), - languages=_one_str_or_none(graph.objects(parent, OEO.languages_info)), - licenses=_one_str_or_none(graph.objects(parent, OEO.licenses_info)), - metadata_info=_one_str_or_none(graph.objects(parent, OEO.metadata_info)), - none=_one_str_or_none(graph.objects(parent, OEO.none_info)), - review=_one_str_or_none(graph.objects(parent, OEO.review_info)), - units=_one_str_or_none(graph.objects(parent, OEO.units_info)), - ) - - def parse_metadata(self, graph: Graph, parent: Node) -> struc.OEPMetadata: - context = self.parse_context(graph, parent) - contributors = [ - self.parse_contributor(graph, c) - for c in graph.objects(parent, OEO.has_contribution) - ] - language = [str(l) for l in graph.objects(parent, DCTERMS.language)] - spatial = self.parse_spatial( - graph, _only(graph.objects(parent, DCTERMS.spatial)) - ) - - temporal = self.parse_temporal( - graph, _only(graph.objects(parent, DCTERMS.temporal)) - ) - comment = self.parse_meta_comment( - graph, _only(graph.objects(parent, OEO.comment)) - ) - resources = [ - self.parse_resource(graph, r) - for r in graph.objects(parent, OEO.has_resource) - ] - terms_of_use = [ - self.parse_terms_of_use(graph, l) - for l in graph.objects(parent, OEO.has_terms_of_use) - ] - sources = [ - self.parse_source(graph, s) for s in graph.objects(parent, DCTERMS.source) - ] - review = self.parse_review(graph, _only(graph.objects(parent, OEO.has_review))) - return struc.OEPMetadata( - comment=comment, - context=context, - contributions=contributors, - description=_one_str_or_none(graph.objects(parent, DCTERMS.description)), - identifier=str(parent), - keywords=list(map(str, graph.objects(parent, DCAT.keyword))), - languages=language, - name=_one_str_or_none(graph.objects(parent, ADMS.Identifier)), - terms_of_use=terms_of_use, - publication_date=self.parse_date( - _only(graph.objects(parent, OEO.publicationDate)) - ), - resources=resources, - review=review, - sources=sources, - spatial=spatial, - temporal=temporal, - title=_one_str_or_none(graph.objects(parent, DCTERMS.title)), - ) diff --git a/src/omi/dialects/rdf/renderer.py b/src/omi/dialects/rdf/renderer.py deleted file mode 100644 index a4a767b..0000000 --- a/src/omi/dialects/rdf/renderer.py +++ /dev/null @@ -1,8 +0,0 @@ -from rdflib.graph import Graph - -from omi.dialects.base.renderer import Renderer - - -class GraphRenderer(Renderer): - def render(self, inp: Graph, *args, **kwargs): - return inp.serialize(format="ttl") diff --git a/src/omi/inspection.py b/src/omi/inspection.py new file mode 100644 index 0000000..f7b4dd5 --- /dev/null +++ b/src/omi/inspection.py @@ -0,0 +1,133 @@ +"""Module to inspect data and create metadata from it.""" + +from collections.abc import Callable +from typing import Any + +from frictionless import Detector, Dialect, Resource +from frictionless.formats import CsvControl + +from omi import base + + +class InspectionError(Exception): + """Raised when an error occurs during inspection.""" + + +def infer_metadata(data: Any, metadata_format: str) -> dict: # noqa: ANN401 + """ + Guess metadata from data in given metadata format. + + Note: It expects semicolon-delimited data. + + Parameters + ---------- + data: Any + Data read from CSV file or other source frictionless may understand + metadata_format: str + Metadata format the inferred metadata should follow + + Returns + ------- + dict + OEMetadata guessed from data, containing name from CSV + """ + latest_metadata_version = base.get_latest_metadata_version(metadata_format) + template_metadata = base.get_metadata_specification(latest_metadata_version).template + if template_metadata is None: + raise InspectionError(f"No metadata template for metadata format {metadata_format} found.") + + fields, resource = __guess_fields_from_data(data) + inferred_metadata = METADATA_TEMPLATE_ENGINE[metadata_format](template_metadata, fields, resource) + return inferred_metadata + + +def __guess_fields_from_data(data: Any) -> tuple[list[dict[str, str]], Resource]: # noqa: ANN401 + """ + Field names and types of data columns are detected by Frictionless. + + Parameters + ---------- + data: Any + Data read from CSV file or other source frictionless may understand + + Returns + ------- + list[dict[str, str]] + List of fields holding name and type as strings + Resource + Extracted resource + """ + csv_control = CsvControl(delimiter=";") + dialect = Dialect(controls=[csv_control]) + detector = Detector(field_float_numbers=True) + resource = Resource( + source=data, + name="test", + profile="tabular-data-resource", + format="csv", + dialect=dialect, + detector=detector, + ) + # Must be run, before schema can be inspected + resource.infer() + fields = resource.schema.to_dict()["fields"] + return fields, resource + + +def __apply_fields_to_oep_metadata_template(metadata: dict, fields: list[dict[str, str]], resource: Resource) -> dict: + """ + Apply fields to metadata template for OEP metadata. + + Parameters + ---------- + metadata: dict + Metadata template + fields: list[dict[str, str]] + List of fields holding name and type as strings + resource: Resource + Extracted frictionless resource holding data + + Returns + ------- + dict + OEP metadata template holding guessed fields + """ + type_mapping = {str(str): "string", str(int): "integer", str(float): "float"} + + def convert_field(field: dict[str, str]) -> dict[str, str]: + """ + Convert frictionless field types to OEP types. + + This only includes conversion of number to float and detection of subtypes in arrays + (currently, only string, integer and float are detected as subtypes). + + Parameters + ---------- + field: dict[str, str] + Frictionless field description + + Returns + ------- + dict[str, str] + Field description with OEP supported types + """ + if field["type"] == "number": + return {"name": field["name"], "type": "float"} + if field["type"] == "array": + for row in rows: + if len(row[field["name"]]) == 0: + continue + item_type = str(type(row[field["name"]][0])) + return {"name": field["name"], "type": f"array {type_mapping[item_type]}"} + # All arrays are empty - so no further subtype can be detected + return {"name": field["name"], "type": "array"} + return field + + rows = resource.read_rows() + fields = [convert_field(field) for field in fields] + + metadata["resources"][0]["schema"]["fields"] = fields + return metadata + + +METADATA_TEMPLATE_ENGINE: dict[str, Callable] = {"OEP": __apply_fields_to_oep_metadata_template} diff --git a/src/omi/license.py b/src/omi/license.py new file mode 100644 index 0000000..f0f6f9e --- /dev/null +++ b/src/omi/license.py @@ -0,0 +1,128 @@ +"""Module to check licenses.""" + +import json +import re +from pathlib import Path + +from omi.base import get_metadata_version + +LICENCES_FILE = Path(__file__).parent / "data" / "licenses.json" + + +class LicenseError(Exception): + """Exception raised when a license is invalid.""" + + +def normalize_license_name(name: str) -> str: + """ + Normalize license name. + + Replace whitespaces with hyphens and convert to uppercase + + Parameters + ---------- + name: str + License name + + Returns + ------- + str + Normalized license name + """ + return re.sub(r"\s", "-", name).upper() + + +def read_licenses() -> set[str]: + """ + Read license IDs from SPDX licenses. + + Returns + ------- + set[str] + Set of license IDs + """ + with LICENCES_FILE.open("r", encoding="utf-8") as file: + licenses = json.load(file) + # Create a set of unique license ID values + return {license_info.get("licenseId").upper() for license_info in licenses["licenses"]} + + +def validate_license(license_id: str) -> bool: + """ + Validate single license ID. + + Parameters + ---------- + license_id: str + License ID + + Returns + ------- + bool + True if valid, False otherwise + """ + normalized_license = normalize_license_name(license_id) + if normalized_license not in LICENSES: + return False + return True + + +def validate_oemetadata_licenses(metadata: dict) -> None: + """ + Validate licenses in OEMetadata. + + Parameters + ---------- + metadata: dict + OEMetadata dictionary + + Raises + ------ + LicenseError + Raised if license is invalid or no license is found + + Returns + ------- + None + if licenses are valid, otherwise LicenseError is raised + """ + if metadata is None: + msg = "Metadata is empty." + raise LicenseError(msg) + + version = get_metadata_version(metadata) + licenses_info = _find_license_field(metadata, version) + + for resource_index, licenses in licenses_info: + if not licenses: + raise LicenseError(f"No license information available in the metadata for resource: {resource_index + 1}.") + for i, license_ in enumerate(licenses or []): + if not license_.get("name"): + raise LicenseError( + f"The license name is missing in resource {resource_index + 1}, license {i + 1} ({license_}).", + ) + + if not validate_license(license_["name"]): + raise LicenseError( + f"The (normalized) license name '{license_['name']}' in resource" + f"{resource_index + 1}, license {i + 1} " + "was not found in the SPDX licenses list. " + "(See https://github.com/spdx/license-list-data/blob/main/json/licenses.json).", + ) + + +def _find_license_field(metadata: dict, version: str) -> list: + version = get_metadata_version(metadata) + if version == "OEMetadata-2.0.1": + # Include resource index with each license for traceability + licenses_per_resource = [ + (i, resource.get("licenses")) for i, resource in enumerate(metadata.get("resources", [])) + ] + else: + # Return -1 as a placeholder index for top-level licenses + licenses_per_resource = [(0, metadata.get("licenses", []))] + + return licenses_per_resource + + +LICENSES = read_licenses() diff --git a/src/omi/oem_structures/__init__.py b/src/omi/oem_structures/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/omi/oem_structures/oem_v15.py b/src/omi/oem_structures/oem_v15.py deleted file mode 100644 index 866aa48..0000000 --- a/src/omi/oem_structures/oem_v15.py +++ /dev/null @@ -1,391 +0,0 @@ -""" -This module extends the internal data structure -with the latest changes of the OEMetadata standard. - -An OEMeadata version specific dialect can import it. - -This bypasses the limitation of OMI to rely on a single -internal representation of the data structure, since -OEMetadata is not a static structure and OMI must be -be able to validate multiple OEMetadata versions. -""" -# TODO: maybe change all inheritance to omi.structure to -# avoide alot of redundancy - -from datetime import datetime -from enum import Enum -from typing import Iterable - -from omi.structure import Compilable - - -class Language(Compilable): - __compiler_name__ = "language" - - -class Subject(Compilable): - __compiler_name__ = "subject" - - def __init__(self, name: str = None, path: str = None): - self.name = name - self.path = path - - -class Spatial(Compilable): - __compiler_name__ = "spatial" - - def __init__( - self, location: str = None, extent: str = None, resolution: str = None - ): - self.location = location - self.extent = extent - self.resolution = resolution - - -class TimestampOrientation(Compilable, Enum): - __compiler_name__ = "timestamp_orientation" - left = 0 - middle = 1 - right = 2 - - @staticmethod - def create(value: str) -> "TimestampOrientation": - if value == "left": - return TimestampOrientation.left - elif value == "middle": - return TimestampOrientation.middle - elif value == "right": - return TimestampOrientation.right - else: - raise Exception("Unknown timestamp orientation:", value) - - -class Timeseries(Compilable): - __compiler_name__ = "timeseries" - - def __init__( - self, - start: datetime = None, - end: datetime = None, - resolution: str = None, - ts_orientation: TimestampOrientation = None, - aggregation: str = None, - ): - self.ts_start = start - self.ts_end = end - self.ts_resolution = resolution - self.ts_orientation = ts_orientation - self.aggregation = aggregation - - -class Temporal(Compilable): - __compiler_name__ = "temporal" - - def __init__( - self, - reference_date: datetime = None, - timeseries_collection: Iterable[Timeseries] = None, - ): - self.reference_date = reference_date - self.timeseries_collection = timeseries_collection - - -class License(Compilable): - __compiler_name__ = "license" - - def __init__( - self, - name: str = None, - title: str = None, - path: str = None, - # instruction: str = None, - # attribution: str = None, - # other_references: Iterable[str] = None, - ): - self.name = name - self.title = title - self.path = path - # self.instruction = instruction - # self.attribution = attribution - # self.other_references = other_references - - @staticmethod - def instance_name_from_id(identifier: str): - return "L_" + identifier.replace("-", "_").replace(".", "_").replace( - "+", "_plus" - ) - - -class TermsOfUse(Compilable): - __compiler_name__ = "terms_of_use" - - def __init__( - self, instruction: str = None, attribution: str = None, lic: License = None - ): - self.license = lic - self.instruction = instruction - self.attribution = attribution - - - -class Source(Compilable): - __compiler_name__ = "source" - - def __init__( - self, - title: str = None, - description: str = None, - path: str = None, - licenses: Iterable[TermsOfUse] = None, - ): - self.title = title - self.description = description - self.path = path - self.licenses = licenses - - -class Person(Compilable): - __compiler_name__ = "person" - - def __init__(self, name: str = None, email: str = None): - self.name = name - self.email = email - - -class Contribution(Compilable): - __compiler_name__ = "contribution" - - def __init__( - self, - contributor: Person = None, - date: datetime = None, - obj: str = None, - comment: str = None, - ): - self.contributor = contributor - self.date = date - self.object = obj - self.comment = comment - - -class IsAbout(Compilable): - __compiler_name__ = "isAbout" - - def __init__(self, name: str = None, path: str = None): - self.name = name - self.path = path - - -class ValueReference(Compilable): - __compiler_name__ = "valueReference" - - def __init__(self, value: str = None, name: str = None, path: str = None): - self.value = value - self.name = name - self.path = path - - -class Field(Compilable): - __compiler_name__ = "field" - - def __init__( - self, - name: str = None, - description: str = None, - field_type: str = None, - isAbout: Iterable[IsAbout] = None, - valueReference: Iterable[ValueReference] = None, - unit: str = None, - resource: "Resource" = None, - ): - self.name = name - self.description = description - self.type = field_type - self.isAbout = isAbout - self.valueReference = valueReference - self.unit = unit - self.resource = resource - - def __repr__(self): - return "{}({})".format( - self.__class__.__name__, - ",".join( - "{}={}".format(key, val) - for key, val in self.__dict__.items() - if key != "resource" - ), - ) - - -class Agency(Compilable): - __compiler_name__ = "agency" - - def __init__(self, name: str = None, logo: str = None): - self.name = name - self.logo = logo - - -class Context(Compilable): - __compiler_name__ = "context" - - def __init__( - self, - homepage: str = None, - documentation: str = None, - source_code: str = None, - contact: str = None, - grant_number: str = None, - funding_agency: Agency = None, - publisher: Agency = None, - ): - self.homepage = homepage - self.documentation = documentation - self.source_code = source_code - self.contact = contact - self.grant_number = grant_number - self.funding_agency = funding_agency - self.publisher = publisher - - -class Reference(Compilable): - __compiler_name__ = "reference" - - def __init__(self, source: Field = None, target: Field = None): - self.source = source - self.target = target - - -class ForeignKey(Compilable): - __compiler_name__ = "foreign_key" - - def __init__(self, references: Iterable[Reference] = None): - self.references = references - - -class Schema(Compilable): - __compiler_name__ = "schema" - - def __init__( - self, - fields: Iterable[Field] = None, - primary_key: Iterable[str] = None, - foreign_keys: Iterable[ForeignKey] = None, - ): - self.fields = fields - self.primary_key = primary_key - self.foreign_keys = foreign_keys - - -class Dialect(Compilable): - __compiler_name__ = "dialect" - - def __init__(self, delimiter: str = None, decimal_separator: str = None): - self.delimiter = delimiter - self.decimal_separator = decimal_separator - - -class Resource(Compilable): - __compiler_name__ = "resource" - - def __init__( - self, - name: str = None, - path: str = None, - profile: str = None, - resource_format: str = None, - encoding: str = None, - schema: Schema = None, - dialect: Dialect = None, - ): - self.name = name - self.path = path - self.profile = profile - self.format = resource_format - self.encoding = encoding - self.schema = schema - if schema is not None: - for field in schema.fields: - field.resource = self - self.dialect = dialect - - -class MetaComment(Compilable): - __compiler_name__ = "meta_comment" - - def __init__( - self, - metadata_info: str = None, - dates: str = None, - units: str = None, - languages: str = None, - licenses: str = None, - review: str = None, - null: str = None, - todo: str = None, - ): - self.metadata_info = metadata_info - self.dates = dates - self.units = units - self.languages = languages - self.licenses = licenses - self.review = review - self.null = null - self.todo = todo - - -class Review(Compilable): - __compiler_name__ = "review" - - def __init__(self, path: str = None, badge: str = None): - self.path = path - self.badge = badge - - -class OEPMetadata(Compilable): - __compiler_name__ = "metadata" - __required__ = ["id"] - - def __init__( - self, - name: str = None, - title: str = None, - identifier: str = None, - description: str = None, - languages: Iterable[Language] = None, - subject: Iterable[Subject] = None, - keywords: Iterable[str] = None, - publication_date: datetime = None, - context: Context = None, - spatial: Spatial = None, - temporal: Temporal = None, - sources: Iterable[Source] = None, - terms_of_use: Iterable[TermsOfUse] = None, - contributions: Iterable[Contribution] = None, - resources: Iterable[Resource] = None, - databus_identifier: str = None, - databus_context: str = None, - review: Review = None, - comment: MetaComment = None, - ): - self.name = name - self.title = title - self.identifier = identifier - self.description = description - self.subject = subject - self.languages = languages - self.keywords = keywords - self.publication_date = publication_date - self.context = context - self.spatial = spatial - self.temporal = temporal - self.sources = sources - self.license = terms_of_use - self.contributions = contributions - self.resources = resources - self.databus_identifier = databus_identifier - self.databus_context = databus_context - self.review = review - self.comment = comment - - def has_keywords(self): - return self.keywords is not None diff --git a/src/omi/settings.py b/src/omi/settings.py new file mode 100644 index 0000000..0b1d46d --- /dev/null +++ b/src/omi/settings.py @@ -0,0 +1,3 @@ +"""Settings module for OMI.""" + +OEP_URL = "https://openenergyplatform.org" diff --git a/src/omi/structure.py b/src/omi/structure.py deleted file mode 100644 index 2ce0b80..0000000 --- a/src/omi/structure.py +++ /dev/null @@ -1,368 +0,0 @@ -from datetime import datetime -from enum import Enum -from typing import Iterable - - -class Compilable: - """ - An abstract class for all metadata components. - """ - - __compiler_name__ = None - """Used to identify the appropriate compiler function for this structure""" - - __required__ = None - __optional__ = None - - def __repr__(self): - return "{}({})".format( - self.__class__.__name__, - ",".join("{}={}".format(key, val) for key, val in self.__dict__.items()), - ) - - def __lt__(self, other): - for key in sorted(self.__dict__): - s = getattr(self, key) - o = getattr(other, key) - if s is None: - return True - elif s < o: - return True - elif s > o: - return False - return False - - def get_missing_fields(self): - for key in sorted(self.__dict__): - if key in self.__required__: - if s is None: - yield key - v = getattr(self, key) - if isinstance(v, Compilable): - for x in v.get_missing_fields(): - yield key + "." + x - - -class Language(Compilable): - __compiler_name__ = "language" - - -class Spatial(Compilable): - __compiler_name__ = "spatial" - - def __init__( - self, location: str = None, extent: str = None, resolution: str = None - ): - self.location = location - self.extent = extent - self.resolution = resolution - - -class TimestampOrientation(Compilable, Enum): - __compiler_name__ = "timestamp_orientation" - left = 0 - middle = 1 - right = 2 - - @staticmethod - def create(value: str) -> "TimestampOrientation": - if value == "left": - return TimestampOrientation.left - elif value == "middle": - return TimestampOrientation.middle - elif value == "right": - return TimestampOrientation.right - else: - raise Exception("Unknown timestamp orientation:", value) - - -class Temporal(Compilable): - __compiler_name__ = "temporal" - - def __init__( - self, - reference_date: datetime = None, - start: datetime = None, - end: datetime = None, - resolution: str = None, - ts_orientation: TimestampOrientation = None, - aggregation: str = None, - ): # TODO: This should not be a string... maybe - # we should use datetime instead? - self.reference_date = reference_date - self.ts_start = start - self.ts_end = end - self.ts_resolution = resolution - self.ts_orientation = ts_orientation - self.aggregation = aggregation - - -class License(Compilable): - __compiler_name__ = "license" - - def __init__( - self, - name: str = None, - identifier: str = None, - text: str = None, - path: str = None, - other_references: Iterable[str] = None, - comment: str = None, - ): - self.name = name - self.path = path - self.identifier = identifier - self.other_references = other_references - self.text = text - self.comment = comment - - @staticmethod - def instance_name_from_id(identifier: str): - return "L_" + identifier.replace("-", "_").replace(".", "_").replace( - "+", "_plus" - ) - - -class TermsOfUse(Compilable): - __compiler_name__ = "terms_of_use" - - def __init__( - self, instruction: str = None, attribution: str = None, lic: License = None - ): - self.instruction = instruction - self.attribution = attribution - self.license = lic - - -class Source(Compilable): - __compiler_name__ = "source" - - def __init__( - self, - title: str = None, - description: str = None, - path: str = None, - licenses: Iterable[TermsOfUse] = None, - ): - self.title = title - self.description = description - self.path = path - self.licenses = licenses - - -class Person(Compilable): - __compiler_name__ = "person" - - def __init__(self, name: str = None, email: str = None): - self.name = name - self.email = email - - -class Contribution(Compilable): - __compiler_name__ = "contribution" - - def __init__( - self, - contributor: Person = None, - date: datetime = None, - obj: str = None, - comment: str = None, - ): - self.contributor = contributor - self.date = date - self.object = obj - self.comment = comment - - -class Field(Compilable): - __compiler_name__ = "field" - - def __init__( - self, - name: str = None, - description: str = None, - field_type: str = None, - unit: str = None, - resource: "Resource" = None, - ): - self.name = name - self.description = description - self.type = field_type - self.unit = unit - self.resource = resource - - def __repr__(self): - return "{}({})".format( - self.__class__.__name__, - ",".join( - "{}={}".format(key, val) - for key, val in self.__dict__.items() - if key != "resource" - ), - ) - - -class Agency(Compilable): - __compiler_name__ = "agency" - - def __init__(self, name: str = None, logo: str = None): - self.name = name - self.logo = logo - - -class Context(Compilable): - __compiler_name__ = "context" - - def __init__( - self, - homepage: str = None, - documentation: str = None, - source_code: str = None, - contact: str = None, - grant_number: str = None, - funding_agency: Agency = None, - publisher: Agency = None, - ): - self.homepage = homepage - self.documentation = documentation - self.source_code = source_code - self.contact = contact - self.grant_number = grant_number - self.funding_agency = funding_agency - self.publisher = publisher - - -class Reference(Compilable): - __compiler_name__ = "reference" - - def __init__(self, source: Field = None, target: Field = None): - self.source = source - self.target = target - - -class ForeignKey(Compilable): - __compiler_name__ = "foreign_key" - - def __init__(self, references: Iterable[Reference] = None): - self.references = references - - -class Schema(Compilable): - __compiler_name__ = "schema" - - def __init__( - self, - fields: Iterable[Field] = None, - primary_key: Iterable[str] = None, - foreign_keys: Iterable[ForeignKey] = None, - ): - self.fields = fields - self.primary_key = primary_key - self.foreign_keys = foreign_keys - - -class Dialect(Compilable): - __compiler_name__ = "dialect" - - def __init__(self, delimiter: str = None, decimal_separator: str = None): - self.delimiter = delimiter - self.decimal_separator = decimal_separator - - -class Resource(Compilable): - __compiler_name__ = "resource" - - def __init__( - self, - name: str = None, - path: str = None, - profile: str = None, - resource_format: str = None, - encoding: str = None, - schema: Schema = None, - dialect: Dialect = None, - ): - self.name = name - self.path = path - self.profile = profile - self.format = resource_format - self.encoding = encoding - self.schema = schema - if schema is not None: - for field in schema.fields: - field.resource = self - self.dialect = dialect - - -class MetaComment(Compilable): - __compiler_name__ = "meta_comment" - - def __init__( - self, - metadata_info: str = None, - dates: str = None, - units: str = None, - languages: str = None, - licenses: str = None, - review: str = None, - none: str = None, - ): - self.metadata_info = metadata_info - self.dates = dates - self.units = units - self.languages = languages - self.licenses = licenses - self.review = review - self.none = none - - -class Review(Compilable): - __compiler_name__ = "review" - - def __init__(self, path: str = None, badge: str = None): - self.path = path - self.badge = badge - - -class OEPMetadata(Compilable): - __compiler_name__ = "metadata" - __required__ = ["id"] - - def __init__( - self, - name: str = None, - title: str = None, - identifier: str = None, - description: str = None, - languages: Iterable[Language] = None, - keywords: Iterable[str] = None, - publication_date: datetime = None, - context: Context = None, - spatial: Spatial = None, - temporal: Temporal = None, - sources: Iterable[Source] = None, - terms_of_use: Iterable[TermsOfUse] = None, - contributions: Iterable[Contribution] = None, - resources: Iterable[Resource] = None, - review: Review = None, - comment: MetaComment = None, - ): - self.name = name - self.title = title - self.identifier = identifier - self.description = description - self.languages = languages - self.keywords = keywords - self.publication_date = publication_date - self.context = context - self.spatial = spatial - self.temporal = temporal - self.sources = sources - self.license = terms_of_use - self.contributions = contributions - self.resources = resources - self.review = review - self.comment = comment - - def has_keywords(self): - return self.keywords is not None \ No newline at end of file diff --git a/src/omi/validation.py b/src/omi/validation.py new file mode 100644 index 0000000..6abf2e9 --- /dev/null +++ b/src/omi/validation.py @@ -0,0 +1,510 @@ +"""Validation module for OMI.""" + +from __future__ import annotations + +import json +import warnings + +import jsonschema +import pandas as pd +import requests +from frictionless import Field, Report, Resource, Schema +from frictionless.fields import ( + ArrayField, + BooleanField, + DateField, + DatetimeField, + IntegerField, + NumberField, + ObjectField, + StringField, +) + +from omi import license +from omi.base import ( + MetadataError, + get_metadata_from_oep_table, + get_metadata_specification, + get_metadata_version, +) +from omi.settings import OEP_URL + +FRICTIONLESS_FIELD_MAPPING = { + "string": StringField, + "text": StringField, + "integer": IntegerField, + "bigint": IntegerField, + "float": NumberField, + "float array": ArrayField, + "double precision": NumberField, + "boolean": BooleanField, + "date": DateField, + "datetime": DatetimeField, + "array": ArrayField, + "object": ObjectField, + "json": ObjectField, +} + + +class ValidationError(Exception): + """Exception raised when a validation fails.""" + + +def validate_metadata(metadata: dict | str) -> None: + """ + Validate metadata against related metadata schema. + + Parameters + ---------- + metadata: dict | str + Metadata as dict or as JSON string + + Returns + ------- + None + if metadata schema is valid. Otherwise it raises an exception. + """ + if isinstance(metadata, str): + metadata = parse_metadata(metadata) + metadata_version = get_metadata_version(metadata) + metadata_schema = get_metadata_specification(metadata_version) + try: + jsonschema.validate(metadata, metadata_schema.schema) + except jsonschema.exceptions.ValidationError as ve: + raise ValidationError(f"Error validating metadata against related metadata schema: {ve.message}") from ve + license.validate_oemetadata_licenses(metadata) + __validate_optional_fields_in_metadata(metadata, metadata_schema.schema) + + +def validate_data( + data: pd.DataFrame, + *, + metadata: dict | str | None = None, + oep_table: str | None = None, + oep_schema: str | None = None, + return_report: bool = False, +) -> None | Report: + """ + Validate data against given metadata or table definition on OEP including metadata on OEP (if set). + + Parameters + ---------- + data: pd.DataFrame + Data to validate + metadata: dict | str | None + Metadata in OEMetadata format. If given, data is validated against metadata schema. + oep_table: str | None + Table name on OEP. If given, data is validated against OEP table. + oep_schema: str | None + Schema name on OEP. If given, data is validated against OEP table. + return_report: bool + If set to True, instead of raising an error if data is invalid an error report is returned + + Raises + ------ + ValidationError + if data is not in pandas.DataFrame format + if field is missing in table or metadata definition + if data does not fit to OEP table definition and/or metadata schema (if `return_report` is set to True, + instead of raising an error a report is returned) + + Returns + ------- + None + if everything is valid. Otherwise, it raises an exception. + """ + if not isinstance(data, pd.DataFrame): + msg = "Data must be given as pandas.DataFrame." + raise ValidationError(msg) + if not metadata and (not oep_table or not oep_schema): + msg = "You must either set metadata or OEP table to validate data against." + raise ValidationError(msg) + if metadata and (oep_table or oep_schema): + msg = ( + "Cannot validate data against both metadata and OEP table. " + "Please set only metadata or OEP table name and schema." + ) + raise ValidationError( + msg, + ) + + if metadata: + if isinstance(metadata, str): + metadata = parse_metadata(metadata) + return validate_data_against_metadata(data, metadata, return_report=return_report) + return validate_data_against_oep_table(data, oep_table, oep_schema, return_report=return_report) + + +def validate_data_against_oep_table( + data: pd.DataFrame, + oep_table: str, + oep_schema: str, + *, + return_report: bool = True, +) -> None | Report: + """ + Validate data against given metadata. + + Parameters + ---------- + data: pandas.DataFrame + Data to validate + oep_table: str + OEP table name + oep_schema: str + OEP schema name + return_report: bool + If set to True, report is returned instead of raising an error. + + Returns + ------- + Report + Frictionless report if `return_report` is set to True, otherwise None is returned. + """ + if not oep_table or not oep_schema: + msg = "You must set OEP table AND schema." + raise ValidationError(msg) + + # First validate data against table definition + table_fields = __get_fields_from_oep_table(oep_table, oep_schema) + report = __validate_data_against_schema(data, table_fields) + if not report.valid: + if return_report: + return report + raise ValidationError(f"Data validation failed against OEP table definition. Reason: {report.tasks[0].errors}") + + # Second, validate data against metadata from table + try: + metadata = get_metadata_from_oep_table(oep_table, oep_schema) + except MetadataError: + return None + metadata_fields = __get_fields_from_metadata(metadata) + report = __validate_data_against_schema(data, metadata_fields) + if not report.valid: + if return_report: + return report + raise ValidationError( + f"Data validation failed against metadata from OEP table. Reason: {report.tasks[0].errors}", + ) + return None + + +def validate_data_against_metadata( + data: pd.DataFrame, + metadata: dict | str, + *, + return_report: bool = True, +) -> None | Report: + """ + Validate data against given metadata. + + Parameters + ---------- + data: pandas.DataFrame + Data to validate + metadata: dict | str + Metadata in OEMetadata format. + return_report: bool + If set to True, report is returned instead of raising an error. + + Returns + ------- + Report + Frictionless report if `return_report` is set to True, otherwise None is returned. + """ + if isinstance(metadata, str): + metadata = parse_metadata(metadata) + metadata_fields = __get_fields_from_metadata(metadata) + report = __validate_data_against_schema(data, metadata_fields) + if not report.valid: + if return_report: + return report + raise ValidationError(f"Data validation failed. Reason: {report.tasks[0].errors}") + return None + + +def validate_oep_table_against_metadata( # noqa: C901 + oep_table: str, + oep_schema: str, + metadata: dict | str | None = None, +) -> None: + """ + Validate OEP table against given metadata. + + Parameters + ---------- + oep_table: str + OEP table name + oep_schema: str + OEP schema name + metadata: dict | str | None + Metadata in OEMetadata format. If no metadata is given, metadata defined for OEP table on OEP is used. + + Raises + ------ + ValidationError + if OEP table schema does not fit metadata schema. + + Returns + ------- + None + if everything is valid. Otherwise, it raises an exception. + """ + if isinstance(metadata, str): + metadata = parse_metadata(metadata) + if metadata is None: + metadata = get_metadata_from_oep_table(oep_table, oep_schema) + + # First check if metadata is even valid: + validate_metadata(metadata) + + errors = [] + + # Check resource name: + if "resources" not in metadata: + warnings.warn("No resource section defined in metadata. Cannot compare schema definitions.", stacklevel=1) + if len(metadata["resources"]) > 1: + warnings.warn( + "Found more than one resource in metadata. Can only compare single resource with oep table definition.", + stacklevel=1, + ) + if "name" not in metadata["resources"][0]: + raise ValidationError( + f"Metadata resource has no name. It should be one of '{oep_table}', or '{oep_schema}.{oep_table}'.", + ) + if ( + metadata["resources"][0]["name"] != oep_table + and metadata["resources"][0]["name"] != f"{oep_schema}.{oep_table}" + ): + raise ValidationError( + f"Name '{metadata['resources'][0]['name']}' of metadata resource does not fit to oep table name. " + f"It should be one of '{oep_table}', or '{oep_schema}.{oep_table}'.", + ) + + # Compare fields and related types: + oep_table_fields = __get_fields_from_oep_table(oep_table, oep_schema) + metadata_fields = __get_fields_from_metadata(metadata) + # Map fields to same field type format (using frictionless format as comparison format) + mapped_oep_table_fields = { + field.name: field.type for field in __map_fields_to_frictionless_fields(oep_table_fields) + } + mapped_metadata_fields = {field.name: field.type for field in __map_fields_to_frictionless_fields(metadata_fields)} + for field_name, field_type in mapped_oep_table_fields.items(): + if field_name not in metadata_fields: + errors.append( + f"Field '{field_name}' from OEP table '{oep_schema}.{oep_table}' is missing in metadata schema.", + ) + continue + if field_type != mapped_metadata_fields[field_name]: + errors.append( + f"Field type '{oep_table_fields[field_name]}' from OEP table field '{field_name}' " + f"differs from type '{metadata_fields[field_name]}' defined in metadata schema.", + ) + for field_name in metadata_fields: + if field_name not in oep_table_fields: + errors.append(f"Field '{field_name}' not defined in OEP table '{oep_schema}.{oep_table}'.") # noqa: PERF401 + if not errors: + return + raise ValidationError(errors) + + +def parse_metadata(metadata_string: str) -> dict: + """ + Parse metadata string into a dictionary. + + Parameters + ---------- + metadata_string: str + Metadata given as JSOn string + + Returns + ------- + dict + Metadata as dictionary + """ + + def dict_raise_on_duplicates(ordered_pairs: dict) -> dict: + """ + Reject duplicate keys. + + From https://stackoverflow.com/a/14902564/5804947 + """ + d = {} + for k, v in ordered_pairs: + if k in d: + raise ValidationError(f"Duplicate keys in metadata: '{k}'") + d[k] = v + return d + + try: + json.loads(metadata_string, object_pairs_hook=dict_raise_on_duplicates) + except json.JSONDecodeError as jde: + start = max(0, jde.pos - 10) + end = min(len(metadata_string), jde.pos + 10) + context = metadata_string[start:end] + error_message = ( + f"Failed to decode JSON: " + f"{jde.msg} at line {jde.lineno}, column {jde.colno}, position {jde.pos}. " + f"Context around this position: '{context}'" + ) + raise ValidationError(error_message) from jde + + +def __validate_data_against_schema(data: pd.DataFrame, fields: dict[str, str]) -> Report: + """ + Validate data against related schema definition and return frictionless report. + + Parameters + ---------- + data: pandas.DataFrame + Date to validate + fields: dict[str, str] + Dictionary of fields and their types to validate data with + + Returns + ------- + Report + Frictionless report of validated data + """ + # Check if all fields oin metadata are represented in data + for field in fields: + if field not in data.columns: + raise ValidationError(f"Could not find column '{field}' in data.") + + ordered_fields = {} + for field in data.columns: + if field not in fields: + raise ValidationError(f"Could not find field '{field}' in schema.") + ordered_fields[field] = fields[field] + frictionless_fields = __map_fields_to_frictionless_fields(ordered_fields) + schema = Schema(fields=frictionless_fields, primary_key=["id"]) + resource = Resource( + data=data, + profile="tabular-data-resource", + schema=schema, + ) + report = resource.validate() + return report + + +def __validate_optional_fields_in_metadata(metadata: dict, schema: dict) -> None: + """ + Validate optional fields in metadata dictionary based on schema. Raise warnings if optional fields are missing. + + Parameters + ---------- + metadata: dict + Metadata as dictionary to check optional fields + schema: dict + JSONSchema for checking optional fields + + Returns + ------- + None + """ + + def check_properties(sub_meta: dict, sub_schema: dict, current_path: str) -> None: + """Check optional fields in metadata dictionary iteratively.""" + if "properties" not in sub_schema: + return + for field in sub_schema["properties"]: + if ("required" not in sub_schema or field not in sub_schema["required"]) and field not in sub_meta: + if current_path == "": + current_path = "top level" + warnings.warn(f"Optional field '{field}' not found in metadata at {current_path}.", stacklevel=2) + if field in sub_meta: + new_path = field if current_path == "" else f"{current_path}.{field}" + check_properties(sub_meta[field], sub_schema["properties"][field], new_path) + + check_properties(metadata, schema, "") + + +def __map_fields_to_frictionless_fields(fields: dict[str, str]) -> list[Field]: + """ + Map fields to Frictionless fields. + + Parameters + ---------- + fields: dict[str, str] + Dictionary of fields holding name and related type as string + + Raises + ------ + ValidationError + if field cannot be mapped to Frictionless field + + Returns + ------- + list[Field] + List of frictionless Fields + """ + frictionless_fields = [] + for field_name, field_type in fields.items(): + if field_type.endswith("[]"): + # This indicates an array field + frictionless_fields.append(ArrayField(name=field_name)) + continue + if field_type not in FRICTIONLESS_FIELD_MAPPING: + raise ValidationError( + f"Field '{field_name} with type '{field_type}' cannot be mapped to Frictionless fields", + ) + f_field = FRICTIONLESS_FIELD_MAPPING[field_type] + frictionless_fields.append(f_field(name=field_name)) + return frictionless_fields + + +def __get_fields_from_oep_table(oep_table: str, oep_schema: str) -> dict[str, str]: + """ + Get table fields and related types from OEP table. + + Parameters + ---------- + oep_table: str + Table name on OEP + oep_schema: str + Schema name on OEP + + Returns + ------- + dict[str, str] + Dictionary of table fields and related types. + """ + response = requests.get(f"{OEP_URL}/api/v0/schema/{oep_schema}/tables/{oep_table}/columns", timeout=90) + if response.status_code != requests.codes.ok: + raise ValidationError(f"Could not find table '{oep_table}' in schema '{oep_schema}' on OEP.") + table_fields = response.json() + return {name: field["data_type"] for name, field in table_fields.items()} + + +def __get_fields_from_metadata(metadata: dict) -> dict[str, str]: + """ + Get fields and related types from metadata. + + Parameters + ---------- + metadata: dict + Metadata in OEMetadata format. + + Raises + ------ + ValidationError + if fields cannot be extracted from metadata. + + Returns + ------- + dict[str, str] + Dictionary of fields and related types. + """ + if "resources" not in metadata: + msg = "No resources found in metadata." + raise ValidationError(msg) + if len(metadata["resources"]) > 1: + msg = "More than one rsource found in metadata. Can only validate single resource." + raise ValidationError(msg) + if "schema" not in metadata["resources"][0]: + msg = "No schema found in metadata resource." + raise ValidationError(msg) + if "fields" not in metadata["resources"][0]["schema"]: + msg = "No fields found in resource schema." + raise ValidationError(msg) + return {field["name"]: field["type"] for field in metadata["resources"][0]["schema"]["fields"]} diff --git a/src/omi/dialects/base/__init__.py b/tests/__init__.py similarity index 100% rename from src/omi/dialects/base/__init__.py rename to tests/__init__.py diff --git a/tests/data/metadata_v13.json b/tests/data/metadata_v13.json deleted file mode 100644 index 6702e83..0000000 --- a/tests/data/metadata_v13.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "title": "Conceived Example Table Meant for Creating an Illustrative Metadata String thereof", - "description": "An imaginary table that provides many features, offering a suitable source for metadata template entries", - "language": [ "eng" ], - "spatial": { - "location": "", - "extent": "Berlin", - "resolution": "1 m"}, - "temporal": { - "reference_date": "2018-11-13", - "start": "", - "end": "", - "resolution": ""}, - "sources": [ - {"name": "Technical review and evaluation of Issue", - "description": "Study financed by Organisation describes Issue. The study is authored by Jon Doe and Erika Mustermann", - "url": "https://doi.org/1.1/j.d.2000.01.001", - "license": "", - "copyright": "Publisher"}, - {"name": "Metastudy on Issue", - "description": "Study financed by State Actor evaluates Issue in regions. The study is authored by Jane Doe and Otto Normal", - "url": "https://doi.org/2.2/j.d.2022.02.022", - "license": "", - "copyright": "Publisher2"}], - "license": { - "id": "ODbL-1.0", - "name": "Open Data Commons Open Database License 1.0", - "version": "1", - "url": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "copyright": "Institute"}, - "contributors": [ - {"name": "Person McHuman", - "email": "person.mchuman@good-institute.net", - "date": "2011-1-11", - "comment": "Prepared the dataset"}, - {"name": "Indivia Mensch", - "email": "indivia.mensch@gute-organisation.org", - "date": "2012-2-12", - "comment": "Fixed Metadata String and date format "}], - "resources": [ - {"name": "example.datatable", - "format": "PostgreSQL", - "fields": [ - {"name": "id", - "description": "unambiguous unique numer", - "unit": "none"}, - {"name": "component_id", - "description": "Identifying numer of component. May repeat due to several occurences of the same component.", - "unit": "none"}, - {"name": "measurement", - "description": "Measured by Instrument", - "unit": "kWh"}, - {"name": "reference", - "description": "Bibtex String that references the information source.", - "unit": "none"}]}], - "metadata_version": "1.3"} diff --git a/tests/data/metadata_v13_converted.json b/tests/data/metadata_v13_converted.json deleted file mode 100644 index a281c1d..0000000 --- a/tests/data/metadata_v13_converted.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "title": "Conceived Example Table Meant for Creating an Illustrative Metadata String thereof", - "description": "An imaginary table that provides many features, offering a suitable source for metadata template entries", - "language": [ "eng" ], - "spatial": { - "extent": "Berlin", - "resolution": "1 m"}, - "temporal": { - "referenceDate": "2018-11-13", - "timeseries": {} -}, - "sources": [ - {"title": "Technical review and evaluation of Issue", - "description": "Study financed by Organisation describes Issue. The study is authored by Jon Doe and Erika Mustermann", - "path": "https://doi.org/1.1/j.d.2000.01.001", - "licenses": [{"attribution": "Publisher"}] - }, - {"title": "Metastudy on Issue", - "description": "Study financed by State Actor evaluates Issue in regions. The study is authored by Jane Doe and Otto Normal", - "path": "https://doi.org/2.2/j.d.2022.02.022", - "licenses": [{"attribution": "Publisher2" - }] - }], - "licenses": [ - {"instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "Institute", - "name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/"}], - "contributors": [ - {"title": "Person McHuman", - "email": "person.mchuman@good-institute.net", - "date": "2011-01-11", - "comment": "Prepared the dataset"}, - {"title": "Indivia Mensch", - "email": "indivia.mensch@gute-organisation.org", - "date": "2012-02-12", - "comment": "Fixed Metadata String and date format "}], - "resources": [ - { - "name": "example.datatable", - "format": "PostgreSQL", - "schema": { - "fields": [ - {"name": "id", - "description": "unambiguous unique numer", - "unit": "none"}, - {"name": "component_id", - "description": "Identifying numer of component. May repeat due to several occurences of the same component.", - "unit": "none"}, - {"name": "measurement", - "description": "Measured by Instrument", - "unit": "kWh"}, - {"name": "reference", - "description": "Bibtex String that references the information source.", - "unit": "none"}]}}], - "metaMetadata": { - "metadataVersion": "OEP-1.4.0", - "metadataLicense": { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/"}}} diff --git a/tests/data/metadata_v13_minimal.json b/tests/data/metadata_v13_minimal.json deleted file mode 100644 index e677875..0000000 --- a/tests/data/metadata_v13_minimal.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "id" -} diff --git a/tests/data/metadata_v14.json b/tests/data/metadata_v14.json deleted file mode 100644 index ca773ce..0000000 --- a/tests/data/metadata_v14.json +++ /dev/null @@ -1,247 +0,0 @@ -{ - "name": "oep_metadata_table_example_v14", - "title": "Good example title", - "id": "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14", - "description": "example metadata for example data", - "language": [ - "en-GB", - "en-US", - "de-DE", - "fr-FR" - ], - "keywords": [ - "example", - "template", - "test" - ], - "publicationDate": "2018-06-12", - "context": { - "homepage": "https://reiner-lemoine-institut.de/szenariendb/", - "documentation": "https://github.com/OpenEnergyPlatform/organisation/wiki/metadata", - "sourceCode": "https://github.com/OpenEnergyPlatform/examples/tree/master/metadata", - "contact": "https://github.com/Ludee", - "grantNo": "03ET4057", - "fundingAgency": "Bundesministerium für Wirtschaft und Energie", - "fundingAgencyLogo": "https://www.innovation-beratung-foerderung.de/INNO/Redaktion/DE/Bilder/Titelbilder/titel_foerderlogo_bmwi.jpg?__blob=poster&v=2", - "publisherLogo": "https://reiner-lemoine-institut.de//wp-content/uploads/2015/09/rlilogo.png" - }, - "spatial": { - "extent": "europe", - "resolution": "100 m" - }, - "temporal": { - "referenceDate": "2016-01-01", - "timeseries": { - "start": "2017-01-01T00:00:00+01:00", - "end": "2017-12-31T23:00:00+01:00", - "resolution": "1 h", - "alignment": "left", - "aggregationType": "sum" - } - }, - "sources": [ - { - "title": "OpenEnergyPlatform Metadata Example", - "description": "Metadata description", - "path": "https://github.com/OpenEnergyPlatform", - "licenses": [ - { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/legalcode", - "instruction": "You are free: To Share, To Create, To Adapt", - "attribution": "© Reiner Lemoine Institut" - } - ] - }, - { - "title": "OpenStreetMap", - "description": "A collaborative project to create a free editable map of the world", - "path": "https://www.openstreetmap.org/", - "licenses": [ - { - "name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© OpenStreetMap contributors" - } - ] - } - ], - "licenses": [ - { - "name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© Reiner Lemoine Institut © OpenStreetMap contributors" - } - ], - "contributors": [ - { - "title": "Ludee", - "date": "2016-06-16", - "object": "metadata", - "comment": "Create metadata" - }, - { - "title": "Ludee", - "date": "2016-11-22", - "object": "metadata", - "comment": "Update metadata" - }, - { - "title": "Ludee", - "date": "2016-11-22", - "object": "metadata", - "comment": "Update header and license" - }, - { - "title": "Ludee", - "date": "2017-03-16", - "object": "metadata", - "comment": "Add license to source" - }, - { - "title": "Ludee", - "date": "2017-03-28", - "object": "metadata", - "comment": "Add copyright to source and license" - }, - { - "title": "Ludee", - "date": "2017-05-30", - "object": "metadata", - "comment": "Release metadata version 1.3" - }, - { - "title": "Ludee", - "date": "2017-06-26", - "object": "metadata", - "comment": "Move referenceDate into temporal and remove array" - }, - { - "title": "Ludee", - "date": "2018-07-19", - "object": "metadata", - "comment": "Start metadata version 1.4" - }, - { - "title": "Ludee", - "date": "2018-07-26", - "object": "data", - "comment": "Rename table and files" - }, - { - "title": "Ludee", - "date": "2018-10-18", - "object": "metadata", - "comment": "Add contribution object" - }, - { - "title": "christian-rli", - "date": "2018-10-18", - "object": "metadata", - "comment": "Add datapackage compatibility" - }, - { - "title": "Ludee", - "date": "2018-11-02", - "object": "metadata", - "comment": "Release metadata version 1.4" - }, - { - "title": "christian-rli", - "date": "2019-02-05", - "object": "metadata", - "comment": "Apply template structure to example" - }, - { - "title": "Ludee", - "date": "2019-03-22", - "object": "metadata", - "comment": "Hotfix foreignKeys" - }, - { - "title": "Ludee", - "date": "2019-07-09", - "object": "metadata", - "comment": "Release metadata version OEP-1.3.0" - } - ], - "resources": [ - { - "profile": "tabular-data-resource", - "name": "model_draft.oep_metadata_table_example_v14", - "path": "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14", - "format": "PostgreSQL", - "encoding": "UTF-8", - "schema": { - "fields": [ - { - "name": "id", - "description": "Unique identifier", - "type": "serial" - }, - { - "name": "year", - "description": "Reference year", - "type": "integer" - }, - { - "name": "value", - "description": "Example value", - "type": "double precision", - "unit": "MW" - }, - { - "name": "geom", - "description": "Geometry", - "type": "geometry(Point, 4326)" - } - ], - "primaryKey": [ - "id" - ], - "foreignKeys": [ - { - "fields": [ - "year" - ], - "reference": { - "resource": "schema.table", - "fields": [ - "year" - ] - } - } - ] - }, - "dialect": { - "decimalSeparator": "." - } - } - ], - "review": { - "path": "https://github.com/OpenEnergyPlatform/data-preprocessing/wiki", - "badge": "platin" - }, - "metaMetadata": { - "metadataVersion": "OEP-1.4.0", - "metadataLicense": { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/" - } - }, - "_comment": { - "metadata": "Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/organisation/wiki/metadata)", - "dates": "Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - "units": "Use a space between numbers and units (100 m)", - "languages": "Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - "licenses": "License name must follow the SPDX License List (https://spdx.org/licenses/)", - "review": "Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/wiki)", - "null": "If not applicable use (null)" - } -} \ No newline at end of file diff --git a/tests/data/metadata_v14.ttl b/tests/data/metadata_v14.ttl deleted file mode 100644 index fb2e153..0000000 --- a/tests/data/metadata_v14.ttl +++ /dev/null @@ -1,202 +0,0 @@ -@prefix adms: . -@prefix dcat: . -@prefix dcatde: . -@prefix dct: . -@prefix foaf: . -@prefix oeo: . -@prefix rdf: . -@prefix rdfs: . -@prefix schema: . -@prefix skos: . -@prefix spdx: . -@prefix xml: . -@prefix xsd: . - - a dcat:Dataset ; - oeo:comment [ oeo:dates_info "Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)" ; - oeo:languages_info "Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)" ; - oeo:licenses_info "License name must follow the SPDX License List (https://spdx.org/licenses/)" ; - oeo:metadata_info "Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/organisation/wiki/metadata)" ; - oeo:none_info "If not applicable use (null)" ; - oeo:review_info "Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/wiki)" ; - oeo:units_info "Use a space between numbers and units (100 m)" ] ; - oeo:documentation "https://github.com/OpenEnergyPlatform/organisation/wiki/metadata" ; - oeo:grantNo "03ET4057" ; - oeo:has_contribution [ oeo:comment "Add datapackage compatibility" ; - oeo:date "2018-10-18"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "christian-rli" ] ], - [ oeo:comment "Update header and license" ; - oeo:date "2016-11-22"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Update metadata" ; - oeo:date "2016-11-22"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Start metadata version 1.4" ; - oeo:date "2018-07-19"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Rename table and files" ; - oeo:date "2018-07-26"^^xsd:date ; - oeo:object "data" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Move referenceDate into temporal and remove array" ; - oeo:date "2017-06-26"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Add contribution object" ; - oeo:date "2018-10-18"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Create metadata" ; - oeo:date "2016-06-16"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Hotfix foreignKeys" ; - oeo:date "2019-03-22"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Add license to source" ; - oeo:date "2017-03-16"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Release metadata version 1.4" ; - oeo:date "2018-11-02"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Apply template structure to example" ; - oeo:date "2019-02-05"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "christian-rli" ] ], - [ oeo:comment "Add copyright to source and license" ; - oeo:date "2017-03-28"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ], - [ oeo:comment "Release metadata version 1.3" ; - oeo:date "2017-05-30"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ] , - [ oeo:comment "Release metadata version OEP-1.3.0" ; - oeo:date "2019-07-09"^^xsd:date ; - oeo:object "metadata" ; - dct:contributor [ a foaf:Person ; - foaf:name "Ludee" ] ]; - oeo:has_resource [ a dcat:Distribution ; - oeo:encoding "UTF-8" ; - oeo:field _:N6d1fcbe69a154f9283bd5a0aadc815a5, - [ a oeo:DatabaseField ; - oeo:type "double precision" ; - oeo:unit "MW" ; - dct:description "Example value" ; - dct:title "value" ], - [ a oeo:DatabaseField ; - oeo:type "geometry(Point, 4326)" ; - dct:description "Geometry" ; - dct:title "geom" ], - _:Nfe3d1d343c024a7a9a22bd5bced82242 ; - oeo:has_dialect [ oeo:decimalSeparator "." ] ; - oeo:has_foreignKey [ oeo:has_reference [ oeo:has_source _:N6d1fcbe69a154f9283bd5a0aadc815a5 ; - oeo:has_target _:Nace2ec79248d4e8baca5a082a3cdb26a ] ] ; - oeo:has_format "PostgreSQL" ; - oeo:primaryKey _:Nfe3d1d343c024a7a9a22bd5bced82242 ; - oeo:profile "tabular-data-resource" ; - dct:title "model_draft.oep_metadata_table_example_v14" ; - dcat:accessURL "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14" ] ; - oeo:has_review [ oeo:has_badge "platin" ; - foaf:page ] ; - oeo:has_terms_of_use [ dcatde:licenseAttributionByText "© Reiner Lemoine Institut © OpenStreetMap contributors" ; - oeo:has_instruction "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!" ; - dcat:license _:odbl ] ; - oeo:metadataLicense ; - oeo:publicationDate "2018-06-12"^^xsd:date ; - oeo:sourceCode "https://github.com/OpenEnergyPlatform/examples/tree/master/metadata" ; - dct:description "example metadata for example data" ; - dct:language "de-DE", - "en-GB", - "en-US", - "fr-FR" ; - dct:source [ - dct:description "Metadata description" ; - oeo:has_terms_of_use [ - dcat:license _:cc0; - oeo:has_instruction "You are free: To Share, To Create, To Adapt" ; - dcatde:licenseAttributionByText "© Reiner Lemoine Institut" ; - ]; - dct:title "OpenEnergyPlatform Metadata Example" ; - foaf:page "https://github.com/OpenEnergyPlatform" - ],[ - dct:description "A collaborative project to create a free editable map of the world" ; - dct:title "OpenStreetMap" ; - oeo:has_terms_of_use [ - dcat:license _:odbl; - oeo:has_instruction "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!" ; - dcatde:licenseAttributionByText "© OpenStreetMap contributors" ; - ]; - foaf:page "https://www.openstreetmap.org/" - ] ; - dct:spatial [ oeo:has_spatial_resolution "100 m" ; - skos:prefLabel "europe" ] ; - dct:temporal [ a dct:PeriodOfTime ; - oeo:has_timestamp_alignment oeo:left_orientation ; - oeo:has_time_resolution "1 h" ; - oeo:referenceDate "2016-01-01T00:00:00"^^xsd:dateTime ; - schema:endDate "2017-12-31T23:00:00+01:00"^^xsd:dateTime ; - schema:startDate "2017-01-01T00:00:00+01:00"^^xsd:dateTime ; - oeo:uses_aggregation "sum"] ; - dct:title "Good example title" ; - adms:Identifier "oep_metadata_table_example_v14" ; - dcat:contactpoint "https://github.com/Ludee" ; - dcat:keyword "example", - "template", - "test" ; - oeo:has_funding_agency [ - dct:title "Bundesministerium für Wirtschaft und Energie"; - oeo:has_logo "https://www.innovation-beratung-foerderung.de/INNO/Redaktion/DE/Bilder/Titelbilder/titel_foerderlogo_bmwi.jpg?__blob=poster&v=2" - ]; - oeo:has_publisher [ - oeo:has_logo "https://reiner-lemoine-institut.de//wp-content/uploads/2015/09/rlilogo.png" - ]; - foaf:homepage "https://reiner-lemoine-institut.de/szenariendb/" . - -[] a dcat:Distribution ; - oeo:field _:Nace2ec79248d4e8baca5a082a3cdb26a ; - dct:title "schema.table" . - -_:N6d1fcbe69a154f9283bd5a0aadc815a5 a oeo:DatabaseField ; - oeo:type "integer" ; - dct:description "Reference year" ; - dct:title "year" . - -_:Nace2ec79248d4e8baca5a082a3cdb26a a oeo:DatabaseField ; - dct:title "year" . - -_:Nfe3d1d343c024a7a9a22bd5bced82242 a oeo:DatabaseField ; - oeo:type "serial" ; - dct:description "Unique identifier" ; - dct:title "id" . - -_:odbl a dcat:LicenseDocument ; - spdx:licenseId "ODbL-1.0" ; - spdx:name "Open Data Commons Open Database License 1.0" ; - foaf:page "https://opendatacommons.org/licenses/odbl/1.0/" . - -_:cc0 a dcat:LicenseDocument ; - spdx:licenseId "CC0-1.0" ; - spdx:name "Creative Commons Zero v1.0 Universal" ; - foaf:page "https://creativecommons.org/publicdomain/zero/1.0/legalcode" . diff --git a/tests/data/metadata_v14_minimal.json b/tests/data/metadata_v14_minimal.json deleted file mode 100644 index e677875..0000000 --- a/tests/data/metadata_v14_minimal.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "id": "id" -} diff --git a/tests/data/metadata_v14_withoutresource.json b/tests/data/metadata_v14_withoutresource.json deleted file mode 100644 index 13a8bfd..0000000 --- a/tests/data/metadata_v14_withoutresource.json +++ /dev/null @@ -1,89 +0,0 @@ -{"name": "oep_metadata_table_example_v14", -"title": "Good example title", -"id": "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14", -"description": "example metadata for example data", -"language": [ "en-GB", "en-US", "de-DE", "fr-FR" ], -"keywords": [ "example", "template", "test" ], -"publicationDate": "2018-06-12", -"context": - {"homepage": "https://reiner-lemoine-institut.de/szenariendb/", - "documentation": "https://github.com/OpenEnergyPlatform/organisation/wiki/metadata", - "sourceCode": "https://github.com/OpenEnergyPlatform/examples/tree/master/metadata", - "contact": "https://github.com/Ludee", - "grantNo": "03ET4057", - "fundingAgency": "Bundesministerium für Wirtschaft und Energie", - "fundingAgencyLogo": "https://www.innovation-beratung-foerderung.de/INNO/Redaktion/DE/Bilder/Titelbilder/titel_foerderlogo_bmwi.jpg?__blob=poster&v=2", - "publisherLogo": "https://reiner-lemoine-institut.de//wp-content/uploads/2015/09/rlilogo.png"}, -"spatial": - { - "extent": "europe", - "resolution": "100 m"}, -"temporal": - {"referenceDate": "2016-01-01", - "timeseries": - {"start": "2017-01-01T00:00+01", - "end": "2017-12-31T23:00+01", - "resolution": "1 h", - "alignment": "left", - "aggregationType": "sum"} }, -"sources": [ - {"title": "OpenEnergyPlatform Metadata Example", - "description": "Metadata description", - "path": "https://github.com/OpenEnergyPlatform", - "licenses": [ - {"name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/legalcode", - "instruction": "You are free: To Share, To Create, To Adapt", - "attribution": "© Reiner Lemoine Institut"} ] }, - {"title": "OpenStreetMap", - "description": "A collaborative project to create a free editable map of the world", - "path": "https://www.openstreetmap.org/", - "licenses": [ - {"name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© OpenStreetMap contributors"} ] } ], -"licenses": [ - {"name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© Reiner Lemoine Institut © OpenStreetMap contributors"}], -"contributors": [ - {"title": "Ludee", "date": "2016-06-16", "object": "metadata", "comment": "Create metadata"}, - {"title": "Ludee", "date": "2016-11-22", "object": "metadata", "comment": "Update metadata"}, - {"title": "Ludee", "date": "2016-11-22", "object": "metadata", "comment": "Update header and license"}, - {"title": "Ludee", "date": "2017-03-16", "object": "metadata", "comment": "Add license to source"}, - {"title": "Ludee", "date": "2017-03-28", "object": "metadata", "comment": "Add copyright to source and license"}, - {"title": "Ludee", "date": "2017-05-30", "object": "metadata", "comment": "Release metadata version 1.3"}, - {"title": "Ludee", "date": "2017-06-26", "object": "metadata", "comment": "Move referenceDate into temporal and remove array"}, - {"title": "Ludee", "date": "2018-07-19", "object": "metadata", "comment": "Start metadata version 1.4"}, - {"title": "Ludee", "date": "2018-07-26", "object": "data", "comment": "Rename table and files"}, - {"title": "Ludee", "date": "2018-10-18", "object": "metadata", "comment": "Add contribution object"}, - {"title": "christian-rli", "date": "2018-10-18", "object": "metadata", "comment": "Add datapackage compatibility"}, - {"title": "Ludee", "date": "2018-11-02", "object": "metadata", "comment": "Release metadata version 1.4"}, - {"title": "christian-rli", "date": "2019-02-05", "object": "metadata", "comment": "Apply template structure to example"}, - {"title": "Ludee", "date": "2019-03-22", "object": "metadata", "comment": "Hotfix foreignKeys"}, - {"title": "Ludee", "date": "2019-07-09", "object": "metadata", "comment": "Release metadata version OEP-1.3.0"} ], -"resources": [ - ], -"review": { - "path": "https://github.com/OpenEnergyPlatform/data-preprocessing/wiki", - "badge": "platin"}, -"metaMetadata": - {"metadataVersion": "OEP-1.4.0", - "metadataLicense": - {"name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/"} }, -"_comment": - {"metadata": "Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/organisation/wiki/metadata)", - "dates": "Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - "units": "Use a space between numbers and units (100 m)", - "languages": "Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - "licenses": "License name must follow the SPDX License List (https://spdx.org/licenses/)", - "review": "Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/wiki)", - "null": "If not applicable use (null)"} } - diff --git a/tests/data/metadata_v15.json b/tests/data/metadata_v15.json deleted file mode 100644 index 68d455d..0000000 --- a/tests/data/metadata_v15.json +++ /dev/null @@ -1,262 +0,0 @@ -{ - "name": "oep_metadata_table_example_v151", - "title": "Example title for metadata example - Version 1.5.1", - "id": "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v151", - "description": "This is an metadata example for example data. There is a corresponding table on the OEP for each metadata version.", - "language": [ - "en-GB", - "en-US", - "de-DE", - "fr-FR" - ], - "subject": [ - { - "name": "energy", - "path": "https://openenergy-platform.org/ontology/oeo/OEO_00000150" - }, - { - "name": "test dataset", - "path": "https://openenergy-platform.org/ontology/oeo/OEO_00000408" - } - ], - "keywords": [ - "energy", - "example", - "template", - "test" - ], - "publicationDate": "2022-02-15", - "context": { - "homepage": "https://reiner-lemoine-institut.de/lod-geoss/", - "documentation": "https://openenergy-platform.org/tutorials/jupyter/OEMetadata/", - "sourceCode": "https://github.com/OpenEnergyPlatform/oemetadata/tree/master", - "contact": "https://github.com/Ludee", - "grantNo": "03EI1005", - "fundingAgency": "Bundesministerium für Wirtschaft und Klimaschutz", - "fundingAgencyLogo": "https://commons.wikimedia.org/wiki/File:BMWi_Logo_2021.svg#/media/File:BMWi_Logo_2021.svg", - "publisherLogo": "https://reiner-lemoine-institut.de//wp-content/uploads/2015/09/rlilogo.png" - }, - "spatial": { - "extent": "europe", - "resolution": "100 m" - }, - "temporal": { - "referenceDate": "2016-01-01", - "timeseries": [ - { - "start": "2017-01-01T00:00:00+01:00", - "end": "2017-12-31T23:00:00+01:00", - "resolution": "1 h", - "alignment": "left", - "aggregationType": "sum" - }, - { - "start": "2018-01-01T00:00:00+01:00", - "end": "2019-06-01T23:00:00+01:00", - "resolution": "15 min", - "alignment": "right", - "aggregationType": "sum" - } - ] - }, - "sources": [ - { - "title": "OpenEnergyPlatform Metadata Example", - "description": "Metadata description", - "path": "https://github.com/OpenEnergyPlatform", - "licenses": [ - { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/legalcode", - "instruction": "You are free: To Share, To Create, To Adapt", - "attribution": "© Reiner Lemoine Institut" - } - ] - }, - { - "title": "OpenStreetMap", - "description": "A collaborative project to create a free editable map of the world", - "path": "https://www.openstreetmap.org/", - "licenses": [ - { - "name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© OpenStreetMap contributors" - } - ] - } - ], - "licenses": [ - { - "name": "ODbL-1.0", - "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", - "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - "attribution": "© Reiner Lemoine Institut © OpenStreetMap contributors" - } - ], - "contributors": [ - { - "title": "Ludee", - "date": "2021-11-15", - "object": "metadata", - "comment": "Release metadata version OEP-1.5.0" - }, - { - "title": "Ludee", - "date": "2022-02-15", - "object": "metadata", - "comment": "Release metadata version OEP-1.5.1" - } - ], - "resources": [ - { - "profile": "tabular-data-resource", - "name": "model_draft.oep_metadata_table_example_v151", - "path": "http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v151", - "format": "PostgreSQL", - "encoding": "UTF-8", - "schema": { - "fields": [ - { - "name": "id", - "description": "Unique identifier", - "type": "serial", - "isAbout": [ - {} - ], - "valueReference": [ - {} - ] - }, - { - "name": "name", - "description": "Example name", - "type": "text", - "isAbout": [ - { - "name": "written name", - "path": "https://openenergy-platform.org/ontology/oeo/IAO_0000590" - } - ], - "valueReference": [ - {} - ] - }, - { - "name": "type", - "description": "Type of wind farm", - "type": "text", - "isAbout": [ - { - "name": "wind farm", - "path": "https://openenergy-platform.org/ontology/oeo/OEO_00000447" - } - ], - "valueReference": [ - { - "value": "onshore", - "name": "onshore wind farm", - "path": "https://openenergy-platform.org/ontology/oeo/OEO_00000311" - }, - { - "value": "offshore", - "name": "offshore wind farm", - "path": "https://openenergy-platform.org/ontology/oeo/OEO_00000308" - } - ] - }, - { - "name": "year", - "description": "Reference year", - "type": "integer", - "isAbout": [ - { - "name": "year", - "path": "https://openenergy-platform.org/ontology/oeo/UO_0000036" - } - ], - "valueReference": [ - {} - ] - }, - { - "name": "value", - "description": "Example value", - "type": "double precision", - "unit": "MW", - "isAbout": [ - { - "name": "quantity value", - "path": "https://openenergy-platform.org/ontology/oeo/OEO_00000350" - } - ], - "valueReference": [ - {} - ] - }, - { - "name": "geom", - "description": "Geometry", - "type": "geometry(Point, 4326)", - "isAbout": [ - { - "name": "spatial region", - "path": "https://openenergy-platform.org/ontology/oeo/BFO_0000006" - } - ], - "valueReference": [ - {} - ] - } - ], - "primaryKey": [ - "id" - ], - "foreignKeys": [ - { - "fields": [ - "year" - ], - "reference": { - "resource": "schema.table", - "fields": [ - "year" - ] - } - } - ] - }, - "dialect": { - "decimalSeparator": "." - } - } - ], - "@id": "https://databus.dbpedia.org/kurzum/mastr/bnetza-mastr/01.04.00", - "@context": "https://github.com/OpenEnergyPlatform/oemetadata/blob/master/metadata/latest/context.json", - "review": { - "path": "https://github.com/OpenEnergyPlatform/data-preprocessing/issues", - "badge": "Platinum" - }, - "metaMetadata": { - "metadataVersion": "OEP-1.5.2", - "metadataLicense": { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/" - } - }, - "_comment": { - "metadata": "Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/oemetadata)", - "dates": "Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - "units": "Use a space between numbers and units (100 m)", - "languages": "Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - "licenses": "License name must follow the SPDX License List (https://spdx.org/licenses/)", - "review": "Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/blob/master/data-review/manual/review_manual.md)", - "null": "If not applicable use: null", - "todo": "If a value is not yet available, use: todo" - } -} \ No newline at end of file diff --git a/tests/test_base.py b/tests/test_base.py new file mode 100644 index 0000000..c6faae6 --- /dev/null +++ b/tests/test_base.py @@ -0,0 +1,29 @@ +"""Tests for OMIs `base` package.""" + +import pytest + +from omi import base, validation + + +def deactivate_test_metadata_from_oep(): + """Test metadata from OEP.""" + metadata = base.get_metadata_from_oep_table("ind_steel_pellet_1") + validation.validate_metadata(metadata) + + +def test_metadata_from_oep_non_existing_table(): + """Test error for non existing table.""" + with pytest.raises( + base.MetadataError, + match="Could not retrieve metadata from OEP table 'model_draft.non_existing_table'.", + ): + base.get_metadata_from_oep_table("non_existing_table") + + +def deactivate_test_metadata_from_oep_empty(): + """Test error for empty metadata.""" + with pytest.raises( + base.MetadataError, + match="Metadata from 'model_draft.bnetza_eeg_anlagenstammdaten_wind_classification' is empty.", + ): + base.get_metadata_from_oep_table("bnetza_eeg_anlagenstammdaten_wind_classification") diff --git a/tests/test_cli/__init__.py b/tests/test_cli/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_cli/test_cli_translation.py b/tests/test_cli/test_cli_translation.py deleted file mode 100644 index 6ec50ae..0000000 --- a/tests/test_cli/test_cli_translation.py +++ /dev/null @@ -1,22 +0,0 @@ -import click -from click.testing import CliRunner -from omi.cli import translate -import json - - -def test_cli_translation(): - @click.command() - @click.argument("name") - def hello(name): - click.echo("Hello %s!" % name) - - runner = CliRunner() - result = runner.invoke( - translate, - ["-f", "oep-v1.3", "-t", "oep-v1.4", "-omit_nones", "True", "tests/data/metadata_v13.json"], - ) - with open("tests/data/metadata_v13_converted.json") as expected_file: - expected = json.loads(expected_file.read()) - print(result) - assert result.exit_code == 0 - assert json.loads(result.output) == expected diff --git a/tests/test_conversion.py b/tests/test_conversion.py new file mode 100644 index 0000000..c848bf3 --- /dev/null +++ b/tests/test_conversion.py @@ -0,0 +1,64 @@ +"""Tests for OMIs conversion module.""" + +import pytest + +import omi.base +from omi import base, conversion, validation + + +def test_conversion_from_oep_152_to_160(): + """Test conversion from OEP v1.5.2 -> v1.6.0.""" + metadata_schema_152 = omi.base.get_metadata_specification("OEP-1.5.2").example + converted_metadata_152 = conversion.convert_metadata(metadata_schema_152, "OEP-1.6.0") + assert base.get_metadata_version(converted_metadata_152) == "OEP-1.6.0" + validation.validate_metadata(converted_metadata_152) + + +def test_conversion_from_oep_160_to_200(): + """Test conversion from OEP v1.6.0 -> v2.0.0.""" + metadata_schema_160 = omi.base.get_metadata_specification("OEP-1.6.0").example + converted_metadata_160 = conversion.convert_metadata(metadata_schema_160, "OEMetadata-2.0.1") + assert base.get_metadata_version(converted_metadata_160) == "OEMetadata-2.0.1" + validation.validate_metadata(converted_metadata_160) + + +def test_conversion_chain(): + """Test conversion chain with conversion tree structure.""" + + def a_b_conversion(md: dict) -> dict: + md["metaMetadata"]["metadataVersion"] = "b" + md["value"] = md["value"] * 2 + return md + + def a_c_conversion(md: dict) -> dict: + md["metaMetadata"]["metadataVersion"] = "c" + md["value"] = md["value"] * 3 + return md + + def c_d_conversion(md: dict) -> dict: + md["metaMetadata"]["metadataVersion"] = "d" + md["value"] = md["value"] * 4 + return md + + def c_e_conversion(md: dict) -> dict: + md["metaMetadata"]["metadataVersion"] = "e" + md["value"] = md["value"] * 5 + return md + + conversion.METADATA_CONVERSIONS[("a", "b")] = a_b_conversion + conversion.METADATA_CONVERSIONS[("a", "c")] = a_c_conversion + conversion.METADATA_CONVERSIONS[("c", "d")] = c_d_conversion + conversion.METADATA_CONVERSIONS[("c", "e")] = c_e_conversion + + # Create dummy metadata in OEP format with version "a" + metadata = {"name": "a", "value": 10, "metaMetadata": {"metadataVersion": "a"}} + converted_metadata = conversion.convert_metadata(metadata, "e") + assert base.get_metadata_version(converted_metadata) == "e" + assert converted_metadata["value"] == 10 * 3 * 5 + + +def test_invalid_conversion(): + """Test if conversion error is raised for invalid conversion chain.""" + metadata = {"metaMetadata": {"metadataVersion": "OEP-1.5.2"}} + with pytest.raises(conversion.ConversionError, match="No conversion chain found from OEP-1.5.2 to OEP-1.5.0."): + conversion.convert_metadata(metadata, "OEP-1.5.0") diff --git a/tests/test_data/inspection/data.csv b/tests/test_data/inspection/data.csv new file mode 100644 index 0000000..2818778 --- /dev/null +++ b/tests/test_data/inspection/data.csv @@ -0,0 +1,3 @@ +string;integer;number;array string;array integer;array float;object;date;bool +gas;55;0.5;["helo", "none"];[1, 2, 3];[1.5, 1.3, 1.8];{"a": 300, "b": "hello"};2024-01-01;True +wind;18;1.8;["tut", "tut", "tut"];[3, 6, 3];[4.55, 44.7, 23.999];{"c": 2, "d": 4};2024-02-02;False diff --git a/tests/test_data/validation/data.csv b/tests/test_data/validation/data.csv new file mode 100644 index 0000000..ea631f2 --- /dev/null +++ b/tests/test_data/validation/data.csv @@ -0,0 +1,3 @@ +id;region;year;cost_var_e;bandwidth_type;source;method;comment;version +0;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 +1;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 diff --git a/tests/test_data/validation/hackathon_lignite_hh_invalid.csv b/tests/test_data/validation/hackathon_lignite_hh_invalid.csv new file mode 100644 index 0000000..d613ca8 --- /dev/null +++ b/tests/test_data/validation/hackathon_lignite_hh_invalid.csv @@ -0,0 +1,3 @@ +id;region;year;natural_domestic_limit;bandwidth_type;source;method;comment;version +0;DE;2024;100.0;should_be_json;{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 +1;DE;2024;100.0;should_be_json;{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 diff --git a/tests/test_data/validation/hackathon_lignite_hh_valid.csv b/tests/test_data/validation/hackathon_lignite_hh_valid.csv new file mode 100644 index 0000000..10915c2 --- /dev/null +++ b/tests/test_data/validation/hackathon_lignite_hh_valid.csv @@ -0,0 +1,3 @@ +id;region;year;natural_domestic_limit;bandwidth_type;source;method;comment;version +0;["DE"];2024;100.0;{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 +1;["DE"];2024;100.0;{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 diff --git a/tests/test_data/validation/invalid_data/duplicate_primary_keys.csv b/tests/test_data/validation/invalid_data/duplicate_primary_keys.csv new file mode 100644 index 0000000..5b25773 --- /dev/null +++ b/tests/test_data/validation/invalid_data/duplicate_primary_keys.csv @@ -0,0 +1,3 @@ +id;region;year;cost_var_e;bandwidth_type;source;method;comment;version +1;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 +1;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 diff --git a/tests/test_data/validation/invalid_data/extra_column.csv b/tests/test_data/validation/invalid_data/extra_column.csv new file mode 100644 index 0000000..fda814d --- /dev/null +++ b/tests/test_data/validation/invalid_data/extra_column.csv @@ -0,0 +1,3 @@ +id;region;year;cost_var_e;bandwidth_type;source;method;comment;version;added_column +0;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1;1 +0;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1;2 diff --git a/tests/test_data/validation/invalid_data/invalid_datatype.csv b/tests/test_data/validation/invalid_data/invalid_datatype.csv new file mode 100644 index 0000000..0a89385 --- /dev/null +++ b/tests/test_data/validation/invalid_data/invalid_datatype.csv @@ -0,0 +1,3 @@ +id;region;year;cost_var_e;bandwidth_type;source;method;comment;version +0;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};1;{"natural_domestic_limit": "exact"};{"test": "test"};v1 +0;["DE"];2024;100.0;{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"natural_domestic_limit": "exact"};{"test": "test"};v1 diff --git a/tests/test_data/validation/invalid_data/missing_column.csv b/tests/test_data/validation/invalid_data/missing_column.csv new file mode 100644 index 0000000..95895b8 --- /dev/null +++ b/tests/test_data/validation/invalid_data/missing_column.csv @@ -0,0 +1,3 @@ +id;region;year;cost_var_e;bandwidth_type;source;comment;version +0;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"test": "test"};v1 +0;["DE"];2024;[100.0];{"natural_domestic_limit": "point"};{"natural_domestic_limit": "file"};{"test": "test"};v1 diff --git a/tests/test_data/validation/invalid_metadata/additional_key.json b/tests/test_data/validation/invalid_metadata/additional_key.json new file mode 100644 index 0000000..ac304f2 --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/additional_key.json @@ -0,0 +1,41 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These Metadata add the key 'universe'.", + "universe": "milky way", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/duplicate_key.json b/tests/test_data/validation/invalid_metadata/duplicate_key.json new file mode 100644 index 0000000..32ae540 --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/duplicate_key.json @@ -0,0 +1,41 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These Metadata have two descrptions.", + "description": "These Metadata have two descrptions and they don't even match.", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/missing_fields.json b/tests/test_data/validation/invalid_metadata/missing_fields.json new file mode 100644 index 0000000..dbf583b --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/missing_fields.json @@ -0,0 +1,33 @@ +{ + "title": "title", + "description": "These Metadata are missing a license and an id.", + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/wrong_datatype.json b/tests/test_data/validation/invalid_metadata/wrong_datatype.json new file mode 100644 index 0000000..58db1a6 --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/wrong_datatype.json @@ -0,0 +1,41 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These Metadata use a wrong date format in publication date.", + "publicationDate": "First of June 2024", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/wrong_json_syntax.json b/tests/test_data/validation/invalid_metadata/wrong_json_syntax.json new file mode 100644 index 0000000..4402adc --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/wrong_json_syntax.json @@ -0,0 +1,40 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These Metadata have extra symbols, braking the structure: line 28 has double colons, extra quotes a semicolon and an extra curly bracket.", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description":: ""Example'' name";} + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/wrong_key.json b/tests/test_data/validation/invalid_metadata/wrong_key.json new file mode 100644 index 0000000..5322e2c --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/wrong_key.json @@ -0,0 +1,40 @@ +{ + "titel": "titel", + "id": "http://such.tld/name", + "description": "These Metadata misspell 'title' as 'titel'.", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/wrong_nesting.json b/tests/test_data/validation/invalid_metadata/wrong_nesting.json new file mode 100644 index 0000000..c25f9b0 --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/wrong_nesting.json @@ -0,0 +1,40 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These Metadata wrongly put the name of the first field object in a list.", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + ["name": "id"], + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/wrong_structure.json b/tests/test_data/validation/invalid_metadata/wrong_structure.json new file mode 100644 index 0000000..a3165f9 --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/wrong_structure.json @@ -0,0 +1,46 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These metadata use a list in spatial, when it should be a dictionary.", + "publicationDate": "First of June 2024", + "spatial": [ + "location": null, + "extent": "europe", + "resolution": "100 m" + ], + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text" + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/wrong_version.json b/tests/test_data/validation/invalid_metadata/wrong_version.json new file mode 100644 index 0000000..3461ba5 --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/wrong_version.json @@ -0,0 +1,47 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These metadata say they're v1.5.0 but 'isAbout' is only defined in version 1.5.2 or later.", + "publicationDate": "First of June 2024", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + { + "name": "name", + "description": "Example name", + "type": "text", + "isAbout": [ + { + "name": "written name", + "path": "https://openenergy-platform.org/ontology/oeo/IAO_0000590" + } + ] + } + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.5.0" + } +} diff --git a/tests/test_data/validation/invalid_metadata/wrongly_placed_null_value.json b/tests/test_data/validation/invalid_metadata/wrongly_placed_null_value.json new file mode 100644 index 0000000..9b6a81d --- /dev/null +++ b/tests/test_data/validation/invalid_metadata/wrongly_placed_null_value.json @@ -0,0 +1,36 @@ +{ + "title": "title", + "id": "http://such.tld/name", + "description": "These Metadata use a null value instead of a second object in fields.", + "licenses": [ + { + "name": "ODbL-1.0", + "title": "Open Data Commons Open Database License 1.0" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "very.name", + "path": "http://such.tld/name", + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "serial" + }, + null + ], + "primaryKey": [ + "id" + ] + } + } + ], + "metaMetadata": { + "metadataVersion": "OEP-1.6.0" + } +} diff --git a/tests/test_data/validation/metadata_for_data_csv.json b/tests/test_data/validation/metadata_for_data_csv.json new file mode 100644 index 0000000..5ae241d --- /dev/null +++ b/tests/test_data/validation/metadata_for_data_csv.json @@ -0,0 +1,214 @@ +{ + "name":"x2x_import_lng", + "title":"sedos_x2x_import_lng", + "id":null, + "description":"Techno-economic parameter for import of liquified natural gas (LNG).", + "subject":[ + { + "name":"import", + "path":"http://openenergy-platform.org/ontology/oeo/OEO_00020201" + }, + { + "name":"liquified natural gas", + "path":"http://openenergy-platform.org/ontology/oeo/oeo-physical/OEO_00010237" + } + ], + "language":[ + "en-GB" + ], + "keywords":[ + "SEDOS", + "AP5", + "X2X", + "oedatamodel-parameter", + "input_data" + ], + "publicationDate":"2024-04-08", + "context":{ + "homepage":"https://sedos-project.github.io/.github/", + "documentation":"https://sedos-project.github.io/.github/", + "sourceCode":"https://github.com/sedos-project", + "contact":"g.mueller@fz-juelich.de", + "grantNo":"03EI1040D", + "fundingAgency":"Bundesministerium für Wirtschaft und Klimaschutz (BMWK)", + "fundingAgencyLogo":"https://en.wikipedia.org/wiki/Federal_Ministry_for_Economic_Affairs_and_Climate_Action#/media/File:BMWi_Logo_2021.svg" + }, + "spatial":{ + "location":"germany", + "extent":null, + "resolution":null + }, + "temporal":{ + "referenceDate":null, + "timeseries":[ + { + "start":null, + "end":null, + "resolution":null, + "alignment":null, + "aggregationType":null + } + ] + }, + "sources":[ + { + "title":"TYNDP 2022. Scenario Building Guidelines.", + "description":null, + "path":"https://2022.entsos-tyndp-scenarios.eu/wp-content/uploads/2022/04/TYNDP_2022_Scenario_Building_Guidelines_Version_April_2022.pdf", + "licenses":[ + { + "instruction":null, + "attribution":"copyright. ENTSOG, ENTSO-E, 2022.", + "name":null, + "title":null, + "path":null + } + ] + }, + { + "title":"Economics of Gas Transportation by Pipeline and LNG", + "description":null, + "path":"https://link.springer.com/chapter/10.1007/978-3-030-86884-0_2", + "licenses":[ + { + "instruction":"You are free to share and adapt. You must give appropriate credit.", + "attribution":"copyright. Molnar, 2022.", + "name":"CC BY 4.0 DEED", + "title":"Attribution 4.0 International", + "path":"https://creativecommons.org/licenses/by/4.0/" + } + ] + } + ], + "licenses":[ + { + "instruction":"You are free: To Share, To Create, To Adapt", + "attribution":null, + "name":"CC0-1.0", + "title":"Creative Commons Zero v1.0 Universal", + "path":"https://creativecommons.org/publicdomain/zero/1.0/legalcode" + } + ], + "contributors":[ + { + "title":"Gian Müller, FZJ", + "email":"g.mueller@fz-juelich.de", + "object":"data and metadata", + "comment":"Data for import of liquified natural gas (LNG).", + "date":"2024-04-08" + } + ], + "resources":[ + { + "profile":"tabular-data-resource", + "name":"model_draft.x2x_import_lng", + "path":null, + "format":"PostgreSQL", + "encoding":"UTF-8", + "schema":{ + "primaryKey":[ + "id" + ], + "foreignKeys":[ ], + "fields":[ + { + "name":"id", + "description":"Unique identifier", + "type":"bigint", + "isAbout":[ ], + "valueReference":[ ], + "unit":null + }, + { + "name":"region", + "description":"Country or region", + "type":"text", + "isAbout":[ ], + "valueReference":[ ], + "unit":null + }, + { + "name":"year", + "description":"Year", + "type":"integer", + "isAbout":[ ], + "valueReference":[ ], + "unit":"a" + }, + { + "name":"cost_var_e", + "description":"Variable costs in cost per unit of a certain good.", + "type":"float array", + "isAbout":[ ], + "valueReference":[ ], + "unit":"€/MWh" + }, + { + "name":"bandwidth_type", + "description":"Bandwidth Type", + "type":"json", + "isAbout":[ ], + "valueReference":[ ], + "unit":null + }, + { + "name":"version", + "description":"Version", + "type":"text", + "isAbout":[ ], + "valueReference":[ ], + "unit":null + }, + { + "name":"method", + "description":"Method", + "type":"json", + "isAbout":[ ], + "valueReference":[ ], + "unit":null + }, + { + "name":"source", + "description":"Source", + "type":"json", + "isAbout":[ ], + "valueReference":[ ], + "unit":null + }, + { + "name":"comment", + "description":"Comment", + "type":"text", + "isAbout":[ ], + "valueReference":[ ], + "unit":null + } + ] + }, + "dialect":{ + "delimiter":";", + "decimalSeparator":"." + } + } + ], + "@id":null, + "@context":"https://raw.githubusercontent.com/OpenEnergyPlatform/oemetadata/develop/metadata/latest/context.json", + "metaMetadata":{ + "metadataVersion":"OEP-1.5.2", + "metadataLicense":{ + "name":"CC0-1.0", + "title":"Creative Commons Zero v1.0 Universal", + "path":"https://creativecommons.org/publicdomain/zero/1.0/" + } + }, + "_comment":{ + "metadata":"Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/oemetadata)", + "dates":"Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", + "units":"Use a space between numbers and units (100 m)", + "languages":"Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", + "licenses":"License name must follow the SPDX License List (https://spdx.org/licenses/)", + "review":"Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/blob/master/data-review/manual/review_manual.md)", + "null":"If not applicable use: null", + "todo":"If a value is not yet available, use: todo" + } +} diff --git a/tests/test_data/validation/metadata_oep_validation.json b/tests/test_data/validation/metadata_oep_validation.json new file mode 100644 index 0000000..5eb1c8e --- /dev/null +++ b/tests/test_data/validation/metadata_oep_validation.json @@ -0,0 +1,244 @@ +{ + "name": "x2x_p2gas_soec_1", + "title": "sedos_x2x_p2gas_soec_1", + "id": null, + "description": "Techno-economic parameter for SOEC hydrogen electrolyzers.", + "subject": [ + { + "name": "water electrolyser", + "path": "http://openenergy-platform.org/ontology/oeo/OEO_00010021" + } + ], + "language": [ + "en-GB" + ], + "keywords": [ + "SEDOS", + "AP5", + "X2X", + "oedatamodel-parameter", + "input_data" + ], + "publicationDate": "2024-04-08", + "context": { + "homepage": "https://sedos-project.github.io/.github/", + "documentation": "https://sedos-project.github.io/.github/", + "sourceCode": "https://github.com/sedos-project", + "contact": "g.mueller@fz-juelich.de", + "grantNo": "03EI1040D", + "fundingAgency": "Bundesministerium für Wirtschaft und Klimaschutz (BMWK)", + "fundingAgencyLogo": "https://en.wikipedia.org/wiki/Federal_Ministry_for_Economic_Affairs_and_Climate_Action#/media/File:BMWi_Logo_2021.svg" + }, + "spatial": { + "location": "global", + "extent": null, + "resolution": null + }, + "temporal": { + "referenceDate": null, + "timeseries": [ + { + "start": null, + "end": null, + "resolution": null, + "alignment": null, + "aggregationType": null + } + ] + }, + "sources": [ + { + "title": "Technology Data for Renewable Fuels", + "description": null, + "path": "https://ens.dk/sites/ens.dk/files/Analyser/technology_data_for_renewable_fuels.pdf", + "licenses": [ + { + "instruction": "You are free to: Share, Adapt. You must give appropriate credit.", + "attribution": "© Danish Energy Agency 2017.", + "name": "CC-BY-4.0 DEED", + "title": null, + "path": "https://creativecommons.org/licenses/by/4.0/" + } + ] + } + ], + "licenses": [ + { + "instruction": "You are free: To Share, To Create, To Adapt", + "attribution": null, + "name": "CC0-1.0", + "title": "Creative Commons Zero v1.0 Universal", + "path": "https://creativecommons.org/publicdomain/zero/1.0/legalcode" + } + ], + "contributors": [ + { + "title": "Gian Müller, FZJ", + "email": "g.mueller@fz-juelich.de", + "object": "data and metadata", + "comment": "Data for SOEC electrolyser process.", + "date": "2024-04-08" + } + ], + "resources": [ + { + "profile": "tabular-data-resource", + "name": "model_draft.x2x_p2gas_soec_1", + "path": null, + "format": "PostgreSQL", + "encoding": "UTF-8", + "schema": { + "primaryKey": [ + "id" + ], + "foreignKeys": [], + "fields": [ + { + "name": "id", + "description": "Unique identifier", + "type": "bigint", + "isAbout": [], + "valueReference": [], + "unit": null + }, + { + "name": "region", + "description": "Country or region", + "type": "text", + "isAbout": [], + "valueReference": [], + "unit": null + }, + { + "name": "year", + "description": "Year", + "type": "integer", + "isAbout": [], + "valueReference": [], + "unit": "a" + }, + { + "name": "conversion_factor_sec_elec", + "description": "Commodity conversion factor of electricity", + "type": "float array", + "isAbout": [], + "valueReference": [], + "unit": "MWh/MWh" + }, + { + "name": "conversion_factor_sec_heat_high", + "description": "Commodity conversion factor of high temperature heat", + "type": "float array", + "isAbout": [], + "valueReference": [], + "unit": "MWh/MWh" + }, + { + "name": "conversion_factor_sec_hydrogen_orig", + "description": "Commodity conversion factor of hydrogen", + "type": "float array", + "isAbout": [], + "valueReference": [], + "unit": "MWh/MWh" + }, + { + "name": "cost_inv_p", + "description": "Investment cost per capacity for SOEC electrolysis", + "type": "float array", + "isAbout": [], + "valueReference": [], + "unit": "EUR/MW" + }, + { + "name": "cost_fix_p", + "description": "Fixed operation and maintenance costs for SOEC electrolysis.", + "type": "float array", + "isAbout": [], + "valueReference": [], + "unit": "EUR/MW*a" + }, + { + "name": "lifetime", + "description": "Lifetime in operation.", + "type": "float array", + "isAbout": [], + "valueReference": [], + "unit": "a" + }, + { + "name": "wacc", + "description": "Percentage of costs for capital after taxes. Used to calculate annuity factor for investment costs.", + "type": "text", + "isAbout": [], + "valueReference": [], + "unit": "%" + }, + { + "name": "bandwidth_type", + "description": "Bandwidth Type", + "type": "json", + "isAbout": [], + "valueReference": [], + "unit": null + }, + { + "name": "version", + "description": "Version", + "type": "text", + "isAbout": [], + "valueReference": [], + "unit": null + }, + { + "name": "method", + "description": "Method", + "type": "json", + "isAbout": [], + "valueReference": [], + "unit": null + }, + { + "name": "source", + "description": "Source", + "type": "json", + "isAbout": [], + "valueReference": [], + "unit": null + }, + { + "name": "comment", + "description": "Comment", + "type": "text", + "isAbout": [], + "valueReference": [], + "unit": null + } + ] + }, + "dialect": { + "delimiter": ";", + "decimalSeparator": "." + } + } + ], + "@id": null, + "@context": "https://raw.githubusercontent.com/OpenEnergyPlatform/oemetadata/develop/metadata/latest/context.json", + "metaMetadata": { + "metadataVersion": "OEP-1.5.2", + "metadataLicense": { + "name": "CC0-1.0", + "title": "Creative Commons Zero v1.0 Universal", + "path": "https://creativecommons.org/publicdomain/zero/1.0/" + } + }, + "_comment": { + "metadata": "Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/oemetadata)", + "dates": "Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", + "units": "Use a space between numbers and units (100 m)", + "languages": "Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", + "licenses": "License name must follow the SPDX License List (https://spdx.org/licenses/)", + "review": "Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/blob/master/data-review/manual/review_manual.md)", + "null": "If not applicable use: null", + "todo": "If a value is not yet available, use: todo" + } +} diff --git a/examples/data/metadata_v15.json b/tests/test_data/validation/unsupported_oep_metadata_example.json similarity index 78% rename from examples/data/metadata_v15.json rename to tests/test_data/validation/unsupported_oep_metadata_example.json index 99b0952..e1731a1 100644 --- a/examples/data/metadata_v15.json +++ b/tests/test_data/validation/unsupported_oep_metadata_example.json @@ -30,7 +30,7 @@ "homepage": "https://reiner-lemoine-institut.de/lod-geoss/", "documentation": "https://openenergy-platform.org/tutorials/jupyter/OEMetadata/", "sourceCode": "https://github.com/OpenEnergyPlatform/oemetadata/tree/master", - "contact": "Ludee@email.de", + "contact": "https://github.com/Ludee", "grantNo": "03EI1005", "fundingAgency": "Bundesministerium für Wirtschaft und Klimaschutz", "fundingAgencyLogo": "https://commons.wikimedia.org/wiki/File:BMWi_Logo_2021.svg#/media/File:BMWi_Logo_2021.svg", @@ -83,7 +83,7 @@ { "name": "ODbL-1.0", "title": "Open Data Commons Open Database License 1.0", - "path": "https://opendatacommons.org/licenses/odbl/1.0/", + "path": "https://opendatacommons.org/licenses/odbl/1.0/index.html", "instruction": "You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", "attribution": "© OpenStreetMap contributors" } @@ -100,6 +100,111 @@ } ], "contributors": [ + { + "title": "Ludee", + "email": null, + "date": "2016-06-16", + "object": "metadata", + "comment": "Create metadata" + }, + { + "title": "Ludee", + "email": null, + "date": "2016-11-22", + "object": "metadata", + "comment": "Update metadata" + }, + { + "title": "Ludee", + "email": null, + "date": "2016-11-22", + "object": "metadata", + "comment": "Update header and license" + }, + { + "title": "Ludee", + "email": null, + "date": "2017-03-16", + "object": "metadata", + "comment": "Add license to source" + }, + { + "title": "Ludee", + "email": null, + "date": "2017-03-28", + "object": "metadata", + "comment": "Add copyright to source and license" + }, + { + "title": "Ludee", + "email": null, + "date": "2017-05-30", + "object": "metadata", + "comment": "Release metadata version 1.3" + }, + { + "title": "Ludee", + "email": null, + "date": "2017-06-26", + "object": "metadata", + "comment": "Move referenceDate into temporal and remove array" + }, + { + "title": "Ludee", + "email": null, + "date": "2018-07-19", + "object": "metadata", + "comment": "Start metadata version 1.4" + }, + { + "title": "Ludee", + "email": null, + "date": "2018-07-26", + "object": "data", + "comment": "Rename table and files" + }, + { + "title": "Ludee", + "email": null, + "date": "2018-10-18", + "object": "metadata", + "comment": "Add contribution object" + }, + { + "title": "christian-rli", + "email": null, + "date": "2018-10-18", + "object": "metadata", + "comment": "Add datapackage compatibility" + }, + { + "title": "Ludee", + "email": null, + "date": "2018-11-02", + "object": "metadata", + "comment": "Release metadata version 1.4" + }, + { + "title": "christian-rli", + "email": null, + "date": "2019-02-05", + "object": "metadata", + "comment": "Apply template structure to example" + }, + { + "title": "Ludee", + "email": null, + "date": "2019-03-22", + "object": "metadata", + "comment": "Hotfix foreignKeys" + }, + { + "title": "Ludee", + "email": null, + "date": "2019-07-09", + "object": "metadata", + "comment": "Release metadata version OEP-1.3.0" + }, { "title": "Ludee", "email": null, @@ -268,7 +373,7 @@ } ], "@id": "https://databus.dbpedia.org/kurzum/mastr/bnetza-mastr/01.04.00", - "@context": "https://github.com/OpenEnergyPlatform/oemetadata/blob/master/metadata/latest/context.json", + "@context": "https://raw.githubusercontent.com/OpenEnergyPlatform/oemetadata/develop/metadata/latest/context.json", "review": { "path": "https://github.com/OpenEnergyPlatform/data-preprocessing/issues", "badge": "Platinum" @@ -291,4 +396,4 @@ "null": "If not applicable use: null", "todo": "If a value is not yet available, use: todo" } -} \ No newline at end of file +} diff --git a/tests/test_data_validation.py b/tests/test_data_validation.py new file mode 100644 index 0000000..6772e47 --- /dev/null +++ b/tests/test_data_validation.py @@ -0,0 +1,112 @@ +"""Tests for validating data via OMI.""" + +import json +import pathlib + +import pandas as pd +import pytest +from frictionless import Report + +from omi import validation + + +def deactivate_test_data_validation_against_oep(): + """Test data validation with example file against OEP table.""" + valid_data_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "hackathon_lignite_hh_valid.csv" + valid_data = pd.read_csv(valid_data_file, delimiter=";") + validation.validate_data(valid_data, oep_table="hackathon_com_lignite_hh", oep_schema="model_draft") + + +def test_data_validation_against_metadata(): + """Test data validation with example file against metadata from file.""" + valid_data_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "data.csv" + valid_data = pd.read_csv(valid_data_file, delimiter=";") + metadata_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "metadata_for_data_csv.json" + with metadata_file.open("r") as f: + metadata = json.load(f) + validation.validate_data(valid_data, metadata=metadata) + + +def deactivate_test_data_validation_report(): + """Test data validation with example file.""" + valid_data_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "hackathon_lignite_hh_valid.csv" + valid_data = pd.read_csv(valid_data_file, delimiter=";") + report = validation.validate_data( + valid_data, + oep_table="hackathon_com_lignite_hh", + oep_schema="model_draft", + return_report=True, + ) + assert report is None + + +def test_data_validation_invalid(): + """Test invalid data validation with example file.""" + invalid_data_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "hackathon_lignite_hh_invalid.csv" + invalid_data = pd.read_csv(invalid_data_file, delimiter=";") + with pytest.raises(validation.ValidationError, match="Data validation failed."): + validation.validate_data(invalid_data, oep_table="hackathon_com_lignite_hh", oep_schema="model_draft") + + +def test_data_validation_invalid_report(): + """Test invalid data validation with example file.""" + invalid_data_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "hackathon_lignite_hh_invalid.csv" + invalid_data = pd.read_csv(invalid_data_file, delimiter=";") + report = validation.validate_data( + invalid_data, + oep_table="hackathon_com_lignite_hh", + oep_schema="model_draft", + return_report=True, + ) + assert isinstance(report, Report) + assert not report.valid + + +def test_invalid_data(): + """Test invalid data validation with example files.""" + metadata_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "metadata_for_data_csv.json" + with metadata_file.open("r") as f: + metadata = json.load(f) + + invalid_data_file = ( + pathlib.Path(__file__).parent / "test_data" / "validation" / "invalid_data" / "missing_column.csv" + ) + invalid_data = pd.read_csv(invalid_data_file, delimiter=";") + with pytest.raises(validation.ValidationError, match="Could not find column 'method' in data."): + validation.validate_data(invalid_data, metadata=metadata) + + invalid_data_file = pathlib.Path(__file__).parent / "test_data" / "validation" / "invalid_data" / "extra_column.csv" + invalid_data = pd.read_csv(invalid_data_file, delimiter=";") + with pytest.raises(validation.ValidationError, match="Could not find field 'added_column' in schema."): + validation.validate_data(invalid_data, metadata=metadata) + + invalid_data_file = ( + pathlib.Path(__file__).parent / "test_data" / "validation" / "invalid_data" / "invalid_datatype.csv" + ) + invalid_data = pd.read_csv(invalid_data_file, delimiter=";") + with pytest.raises(validation.ValidationError, match="type-error"): + validation.validate_data(invalid_data, metadata=metadata) + + invalid_data_file = ( + pathlib.Path(__file__).parent / "test_data" / "validation" / "invalid_data" / "duplicate_primary_keys.csv" + ) + invalid_data = pd.read_csv(invalid_data_file, delimiter=";") + with pytest.raises(validation.ValidationError, match="primary-key"): + validation.validate_data(invalid_data, metadata=metadata) + + +def test_invalid_arguments_to_validation_function(): + """Test different invalid function calls to validation function.""" + with pytest.raises(validation.ValidationError, match="Data must be given as pandas.DataFrame."): + validation.validate_data({}) + with pytest.raises( + validation.ValidationError, + match="You must either set metadata or OEP table to validate data against.", + ): + validation.validate_data(pd.DataFrame()) + with pytest.raises(validation.ValidationError, match="Cannot validate data against both metadata and OEP table."): + validation.validate_data(pd.DataFrame(), metadata={"a": "a"}, oep_table="a", oep_schema="a") + with pytest.raises(validation.ValidationError, match="Cannot validate data against both metadata and OEP table."): + validation.validate_data(pd.DataFrame(), metadata={"a": "a"}, oep_table="a") + with pytest.raises(validation.ValidationError, match="Cannot validate data against both metadata and OEP table."): + validation.validate_data(pd.DataFrame(), metadata={"a": "a"}, oep_schema="a") diff --git a/tests/test_dialects/__init__.py b/tests/test_dialects/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_dialects/base/__init__.py b/tests/test_dialects/base/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_dialects/base/parser.py b/tests/test_dialects/base/parser.py deleted file mode 100644 index d1c50a8..0000000 --- a/tests/test_dialects/base/parser.py +++ /dev/null @@ -1,62 +0,0 @@ -import datetime -import unittest - -from omi.structure import Compilable -from omi.structure import Field -from omi.oem_structures import oem_v15 - - -def _test_generic_parsing(parser, inp, expected, **kwargs): - if parser: - result = parser.parse_from_file(inp) - assert_compileable_equal(expected, result, **kwargs) - - -def assert_compileable_equal(expected, got, nulls=None, exclude=None): - exclude = exclude or [] - nulls = nulls or [None] - assert isinstance(expected, (Compilable, dict)), type(expected) - assert isinstance(got, (Compilable, dict)), (type(got), expected) - for key in set(expected.__dict__.keys()).union(set(got.__dict__.keys())): - if ( - key not in exclude - and isinstance(getattr(expected, key), Field) - or isinstance(getattr(expected, key), oem_v15.Field) - ): - l = getattr(expected, key) - r = getattr(got, key) - if isinstance(l, Compilable): - new_exclude = [] - if isinstance(l, Field): - new_exclude = ["resource"] - elif isinstance(l, oem_v15.Field): - new_exclude = ["resource"] - assert_compileable_equal(l, r, nulls=nulls, exclude=new_exclude) - elif isinstance(l, list) and isinstance(r, list): - assert len(l) == len( - r - ), "Lists do not match (Expected: {}; Got: {})".format(l, r) - for l0, r0 in zip(sorted(l), sorted(r)): - if isinstance(l0, Compilable): - if isinstance(l0, Field): - new_exclude = ["resource"] - elif isinstance(l, oem_v15.Field): - new_exclude = ["resource"] - else: - new_exclude = [] - assert_compileable_equal( - l0, r0, nulls=nulls, exclude=new_exclude - ) - else: - assert l0 == r0, "Expected: {}; Got: {}".format(l0, r0) - else: - if not (l is None and r in nulls): - assert ( - l == r - ), "Keys {} do not match (Expected:{}:{}; Got: {}:{})".format( - key, type(l), l, type(r), r - ) - - -def parse_date(s): - return datetime.datetime.strptime(s, "%Y-%M-%d") diff --git a/tests/test_dialects/internal_structures.py b/tests/test_dialects/internal_structures.py deleted file mode 100644 index 97d9f81..0000000 --- a/tests/test_dialects/internal_structures.py +++ /dev/null @@ -1,641 +0,0 @@ -import datetime - -from omi import structure as s -from omi.oem_structures import oem_v15 - -_source_year = s.Field( - name="year", description="Reference year", field_type="integer", unit=None -) - -_target_year = s.Field(name="year", description=None, field_type=None, unit=None) - -_target_resource = s.Resource( - name="schema.table", - schema=s.Schema(fields=[_target_year], foreign_keys=None, primary_key=None), - dialect=None, - encoding=None, - path=None, - profile=None, - resource_format=None, -) - -_target_year.resource = _target_resource - - -cc010 = s.License( - name="Creative Commons Zero v1.0 Universal", - identifier="CC0-1.0", - path="https://creativecommons.org/publicdomain/zero/1.0/legalcode", - other_references=None, - text=None, -) - -odbl10 = s.License( - identifier="ODbL-1.0", - name="Open Data Commons Open Database License 1.0", - path="https://opendatacommons.org/licenses/odbl/1.0/", - other_references=None, - text=None, -) - -odbl10_13 = s.License( - name=None, identifier="ODbL-1.0", path=None, other_references=None, text=None -) - -metadata_v_1_3 = s.OEPMetadata( - name=None, - title="Conceived Example Table Meant for Creating an Illustrative Metadata String thereof", - identifier=None, - description="An imaginary table that provides many features, offering a suitable source for metadata template entries", - languages=["eng"], - keywords=None, - publication_date=None, - context=None, - spatial=s.Spatial(location=None, extent="Berlin", resolution="1 m"), - temporal=s.Temporal( - reference_date=datetime.datetime(2018, 11, 13), - start=None, - end=None, - resolution=None, - ts_orientation=None, - ), - sources=[ - s.Source( - title="Technical review and evaluation of Issue", - description="Study financed by Organisation describes Issue. The study is authored by Jon Doe and Erika Mustermann", - path="https://doi.org/1.1/j.d.2000.01.001", - licenses=[s.TermsOfUse(attribution="Publisher")], - ), - s.Source( - title="Metastudy on Issue", - description="Study financed by State Actor evaluates Issue in regions. The study is authored by Jane Doe and Otto Normal", - path="https://doi.org/2.2/j.d.2022.02.022", - licenses=[s.TermsOfUse(attribution="Publisher2")], - ), - ], - terms_of_use=[ - s.TermsOfUse( - lic=odbl10, - instruction="You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - attribution="Institute", - ) - ], - contributions=[ - s.Contribution( - contributor=s.Person( - name="Person McHuman", email="person.mchuman@good-institute.net" - ), - date=datetime.datetime(2011, 1, 11, 0, 0, 0), - obj=None, - comment="Prepared the dataset", - ), - s.Contribution( - contributor=s.Person( - name="Indivia Mensch", email="indivia.mensch@gute-organisation.org" - ), - date=datetime.datetime(2012, 2, 12, 0, 0, 0), - obj=None, - comment="Fixed Metadata String and date format ", - ), - ], - resources=[ - s.Resource( - name="example.datatable", - resource_format="PostgreSQL", - schema=s.Schema( - fields=[ - s.Field( - name="id", - description="unambiguous unique numer", - unit=None, - field_type=None, - ), - s.Field( - name="component_id", - description="Identifying numer of component. May repeat due to several occurences of the same component.", - unit=None, - field_type=None, - ), - s.Field( - name="measurement", - description="Measured by Instrument", - unit="kWh", - field_type=None, - ), - s.Field( - name="reference", - description="Bibtex String that references the information source.", - unit=None, - field_type=None, - ), - ], - primary_key=None, - foreign_keys=None, - ), - path=None, - profile=None, - encoding=None, - dialect=None, - ) - ], - review=None, - comment=None, -) - -metadata_v_1_4 = s.OEPMetadata( - name="oep_metadata_table_example_v14", - title="Good example title", - identifier="http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14", - description="example metadata for example data", - languages=["en-GB", "en-US", "de-DE", "fr-FR"], - keywords=["example", "template", "test"], - publication_date=datetime.datetime(2018, 6, 12, 0, 0), - context=s.Context( - homepage="https://reiner-lemoine-institut.de/szenariendb/", - documentation="https://github.com/OpenEnergyPlatform/organisation/wiki/metadata", - source_code="https://github.com/OpenEnergyPlatform/examples/tree/master/metadata", - contact="https://github.com/Ludee", - grant_number="03ET4057", - funding_agency=s.Agency( - name="Bundesministerium für Wirtschaft und Energie", - logo="https://www.innovation-beratung-foerderung.de/INNO/Redaktion/DE/Bilder/Titelbilder/titel_foerderlogo_bmwi.jpg?__blob=poster&v=2", - ), - publisher=s.Agency( - logo="https://reiner-lemoine-institut.de//wp-content/uploads/2015/09/rlilogo.png" - ), - ), - spatial=s.Spatial(location=None, extent="europe", resolution="100 m"), - temporal=s.Temporal( - reference_date=datetime.datetime(2016, 1, 1, 0, 0), - start=datetime.datetime( - 2017, 1, 1, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 3600)) - ), - end=datetime.datetime( - 2017, 12, 31, 23, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 3600)) - ), - resolution="1 h", - ts_orientation=s.TimestampOrientation.left, - aggregation="sum", - ), - sources=[ - s.Source( - title="OpenEnergyPlatform Metadata Example", - description="Metadata description", - path="https://github.com/OpenEnergyPlatform", - licenses=[ - s.TermsOfUse( - lic=cc010, - instruction="You are free: To Share, To Create, To Adapt", - attribution="© Reiner Lemoine Institut", - ) - ], - ), - s.Source( - title="OpenStreetMap", - description="A collaborative project to create a free editable map of the world", - path="https://www.openstreetmap.org/", - licenses=[ - s.TermsOfUse( - lic=odbl10, - instruction="You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - attribution="© OpenStreetMap contributors", - ) - ], - ), - ], - terms_of_use=[ - s.TermsOfUse( - lic=odbl10, - instruction="You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - attribution="© Reiner Lemoine Institut © OpenStreetMap contributors", - ) - ], - contributions=[ - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2016, 6, 16), - obj="metadata", - comment="Create metadata", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2016, 11, 22), - obj="metadata", - comment="Update metadata", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2016, 11, 22), - obj="metadata", - comment="Update header and license", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2017, 3, 16), - obj="metadata", - comment="Add license to source", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2017, 3, 28), - obj="metadata", - comment="Add copyright to source and license", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2017, 5, 30), - obj="metadata", - comment="Release metadata version 1.3", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2017, 6, 26), - obj="metadata", - comment="Move referenceDate into temporal and remove array", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2018, 7, 19), - obj="metadata", - comment="Start metadata version 1.4", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2018, 7, 26), - obj="data", - comment="Rename table and files", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2018, 10, 18), - obj="metadata", - comment="Add contribution object", - ), - s.Contribution( - contributor=s.Person(name="christian-rli", email=None), - date=datetime.datetime(2018, 10, 18), - obj="metadata", - comment="Add datapackage compatibility", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2018, 11, 2), - obj="metadata", - comment="Release metadata version 1.4", - ), - s.Contribution( - contributor=s.Person(name="christian-rli", email=None), - date=datetime.datetime(2019, 2, 5), - obj="metadata", - comment="Apply template structure to example", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2019, 3, 22), - obj="metadata", - comment="Hotfix foreignKeys", - ), - s.Contribution( - contributor=s.Person(name="Ludee", email=None), - date=datetime.datetime(2019, 7, 9), - obj="metadata", - comment="Release metadata version OEP-1.3.0", - ), - ], - resources=[ - s.Resource( - name="model_draft.oep_metadata_table_example_v14", - path="http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v14", - profile="tabular-data-resource", - resource_format="PostgreSQL", - encoding="UTF-8", - schema=s.Schema( - fields=[ - s.Field( - name="id", - description="Unique identifier", - field_type="serial", - unit=None, - ), - _source_year, - s.Field( - name="value", - description="Example value", - field_type="double precision", - unit="MW", - ), - s.Field( - name="geom", - description="Geometry", - field_type="geometry(Point, 4326)", - unit=None, - ), - ], - primary_key=["id"], - foreign_keys=[ - s.ForeignKey( - references=[ - s.Reference(source=_source_year, target=_target_year) - ] - ) - ], - ), - dialect=s.Dialect(delimiter=None, decimal_separator="."), - ) - ], - review=s.Review( - path="https://github.com/OpenEnergyPlatform/data-preprocessing/wiki", - badge="platin", - ), - comment=s.MetaComment( - metadata_info="Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/organisation/wiki/metadata)", - dates="Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - units="Use a space between numbers and units (100 m)", - languages="Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - licenses="License name must follow the SPDX License List (https://spdx.org/licenses/)", - review="Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/wiki)", - none="If not applicable use (null)", - ), -) - -############################################### oem v151 ######################################################### -cc010_v15 = oem_v15.License( - name="CC0-1.0", - title="Creative Commons Zero v1.0 Universal", - path="https://creativecommons.org/publicdomain/zero/1.0/legalcode", -) - -odbl10_v15 = oem_v15.License( - name="ODbL-1.0", - title="Open Data Commons Open Database License 1.0", - path="https://opendatacommons.org/licenses/odbl/1.0/", -) - - -metadata_v_1_5 = oem_v15.OEPMetadata( - name="oep_metadata_table_example_v151", - title="Example title for metadata example - Version 1.5.1", - identifier="http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v151", - description="This is an metadata example for example data. There is a corresponding table on the OEP for each metadata version.", - languages=["en-GB", "en-US", "de-DE", "fr-FR"], - subject=[ - oem_v15.Subject( - name="energy", - path="https://openenergy-platform.org/ontology/oeo/OEO_00000150", - ), - oem_v15.Subject( - name="test dataset", - path="https://openenergy-platform.org/ontology/oeo/OEO_00000408", - ), - ], - keywords=["energy", "example", "template", "test"], - publication_date=datetime.datetime(2022, 2, 15, 0, 0), - context=oem_v15.Context( - homepage="https://reiner-lemoine-institut.de/lod-geoss/", - documentation="https://openenergy-platform.org/tutorials/jupyter/OEMetadata/", - source_code="https://github.com/OpenEnergyPlatform/oemetadata/tree/master", - contact="https://github.com/Ludee", - grant_number="03EI1005", - funding_agency=oem_v15.Agency( - name="Bundesministerium für Wirtschaft und Klimaschutz", - logo="https://commons.wikimedia.org/wiki/File:BMWi_Logo_2021.svg#/media/File:BMWi_Logo_2021.svg", - ), - publisher=oem_v15.Agency( - logo="https://reiner-lemoine-institut.de//wp-content/uploads/2015/09/rlilogo.png" - ), - ), - spatial=oem_v15.Spatial(location=None, extent="europe", resolution="100 m"), - temporal=oem_v15.Temporal( - reference_date=datetime.datetime(2016, 1, 1, 0, 0), - timeseries_collection=[ - oem_v15.Timeseries( - start=datetime.datetime( - 2017, - 1, - 1, - 0, - 0, - tzinfo=datetime.timezone(datetime.timedelta(0, 3600)), - ), - end=datetime.datetime( - 2017, - 12, - 31, - 23, - 0, - tzinfo=datetime.timezone(datetime.timedelta(0, 3600)), - ), - resolution="1 h", - ts_orientation=oem_v15.TimestampOrientation.left, - aggregation="sum", - ), - oem_v15.Timeseries( - start=datetime.datetime( - 2018, - 1, - 1, - 0, - 0, - tzinfo=datetime.timezone(datetime.timedelta(0, 3600)), - ), - end=datetime.datetime( - 2019, - 6, - 1, - 23, - 0, - tzinfo=datetime.timezone(datetime.timedelta(0, 3600)), - ), - resolution="15 min", - ts_orientation=oem_v15.TimestampOrientation.right, - aggregation="sum", - ), - ], - ), - sources=[ - oem_v15.Source( - title="OpenEnergyPlatform Metadata Example", - description="Metadata description", - path="https://github.com/OpenEnergyPlatform", - licenses=[ - oem_v15.TermsOfUse( - lic=cc010_v15, - instruction="You are free: To Share, To Create, To Adapt", - attribution="© Reiner Lemoine Institut", - ) - ], - ), - oem_v15.Source( - title="OpenStreetMap", - description="A collaborative project to create a free editable map of the world", - path="https://www.openstreetmap.org/", - licenses=[ - oem_v15.TermsOfUse( - lic=odbl10_v15, - instruction="You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - attribution="© OpenStreetMap contributors", - ) - ], - ), - ], - terms_of_use=[ - oem_v15.TermsOfUse( - lic=odbl10_v15, - instruction="You are free: To Share, To Create, To Adapt; As long as you: Attribute, Share-Alike, Keep open!", - attribution="© Reiner Lemoine Institut © OpenStreetMap contributors", - ) - ], - contributions=[ - oem_v15.Contribution( - contributor=oem_v15.Person(name="Ludee", email=None), - date=datetime.datetime(2021, 11, 15), - obj="metadata", - comment="Release metadata version OEP-1.5.0", - ), - oem_v15.Contribution( - contributor=oem_v15.Person(name="Ludee", email=None), - date=datetime.datetime(2022, 2, 15), - obj="metadata", - comment="Release metadata version OEP-1.5.1", - ), - ], - resources=[ - oem_v15.Resource( - name="model_draft.oep_metadata_table_example_v151", - path="http://openenergyplatform.org/dataedit/view/model_draft/oep_metadata_table_example_v151", - profile="tabular-data-resource", - resource_format="PostgreSQL", - encoding="UTF-8", - schema=oem_v15.Schema( - fields=[ - oem_v15.Field( - name="id", - description="Unique identifier", - field_type="serial", - unit=None, - isAbout=[oem_v15.IsAbout(name=None, path=None)], - valueReference=[ - oem_v15.ValueReference(value=None, name=None, path=None) - ], - ), - oem_v15.Field( - name="name", - description="Example name", - field_type="text", - unit=None, - isAbout=[ - oem_v15.IsAbout( - name="written name", - path="https://openenergy-platform.org/ontology/oeo/IAO_0000590", - ) - ], - valueReference=[ - oem_v15.ValueReference(value=None, name=None, path=None) - ], - ), - oem_v15.Field( - name="type", - description="Type of wind farm", - field_type="text", - unit=None, - isAbout=[ - oem_v15.IsAbout( - name="wind farm", - path="https://openenergy-platform.org/ontology/oeo/OEO_00000447", - ) - ], - valueReference=[ - oem_v15.ValueReference( - value="onshore", - name="onshore wind farm", - path="https://openenergy-platform.org/ontology/oeo/OEO_00000311", - ), - oem_v15.ValueReference( - value="offshore", - name="offshore wind farm", - path="https://openenergy-platform.org/ontology/oeo/OEO_00000308", - ), - ], - ), - oem_v15.Field( - name="year", - description="Reference year", - field_type="integer", - unit=None, - isAbout=[ - oem_v15.IsAbout( - name="year", - path="https://openenergy-platform.org/ontology/oeo/UO_0000036", - ) - ], - valueReference=[ - oem_v15.ValueReference(value=None, name=None, path=None) - ], - ), - oem_v15.Field( - name="value", - description="Example value", - field_type="double precision", - unit="MW", - isAbout=[ - oem_v15.IsAbout( - name="quantity value", - path="https://openenergy-platform.org/ontology/oeo/OEO_00000350", - ) - ], - valueReference=[ - oem_v15.ValueReference(value=None, name=None, path=None) - ], - ), - oem_v15.Field( - name="geom", - description="Geometry", - field_type="geometry(Point, 4326)", - unit=None, - isAbout=[ - oem_v15.IsAbout( - name="spatial region", - path="https://openenergy-platform.org/ontology/oeo/BFO_0000006", - ) - ], - valueReference=[ - oem_v15.ValueReference(value=None, name=None, path=None) - ], - ), - ], - primary_key=["id"], - foreign_keys=[ - oem_v15.ForeignKey( - references=[ - oem_v15.Reference(source=_source_year, target=_target_year) - ] - ) - ], - ), - dialect=oem_v15.Dialect(delimiter=None, decimal_separator="."), - ) - ], - databus_identifier="https://databus.dbpedia.org/kurzum/mastr/bnetza-mastr/01.04.00", - databus_context="https://github.com/OpenEnergyPlatform/oemetadata/blob/master/metadata/latest/context.json", - review=oem_v15.Review( - path="https://github.com/OpenEnergyPlatform/data-preprocessing/issues", - badge="Platinum", - ), - comment=oem_v15.MetaComment( - metadata_info="Metadata documentation and explanation (https://github.com/OpenEnergyPlatform/oemetadata)", - dates="Dates and time must follow the ISO8601 including time zone (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss±hh)", - units="Use a space between numbers and units (100 m)", - languages="Languages must follow the IETF (BCP47) format (en-GB, en-US, de-DE)", - licenses="License name must follow the SPDX License List (https://spdx.org/licenses/)", - review="Following the OEP Data Review (https://github.com/OpenEnergyPlatform/data-preprocessing/blob/master/data-review/manual/review_manual.md)", - null="If not applicable use: null", - todo="If a value is not yet available, use: todo", - ), -) - - -metadata_v_1_3_minimal = s.OEPMetadata() - -metadata_v_1_4_minimal = s.OEPMetadata(identifier="id") - -metadata_v_1_5_minimal = oem_v15.OEPMetadata(identifier="id") diff --git a/tests/test_dialects/test_oep/__init__.py b/tests/test_dialects/test_oep/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_dialects/test_oep/deactivate-test_roundtrip.py b/tests/test_dialects/test_oep/deactivate-test_roundtrip.py deleted file mode 100644 index 3e1189d..0000000 --- a/tests/test_dialects/test_oep/deactivate-test_roundtrip.py +++ /dev/null @@ -1,59 +0,0 @@ -import json -from itertools import combinations, product - -from omi.dialects.oep.compiler import JSONCompiler -from omi.dialects.oep.parser import JSONParser_1_4 -from omi.dialects.rdf.compiler import RDFCompiler -from omi.dialects.rdf.parser import RDFParser - -from .test_compiler import assert_equal - - -def test_roundtrip(): - with open("tests/data/metadata_v14.json", "r") as _input_file: - input_string = _input_file.read() - assert_roundtrip(json.loads(input_string), input_string) - - -def assert_roundtrip(expected_json, input_string): - json_compiler = JSONCompiler() - json_parser = JSONParser_1_4() - rdf_compiler = RDFCompiler() - rdf_p = RDFParser() - # Step 1: Parse JSON to internal structure - internal_metadata = json_parser.parse_from_string(input_string) - # Step 2: Translate to rdf - _ = rdf_compiler.visit(internal_metadata) - # Step 3: Parse rdf string - internal_metadata2 = rdf_p.parse(rdf_compiler.graph) - # Step 4: Translate to JSON - result_json = json_compiler.visit(internal_metadata2) - # Final step: Compare - assert_equal(expected_json, result_json, disregard_ordering=True) - - -def __mask(jsn, keep): - if isinstance(jsn, dict): - return [dict(zip(keys, items)) - for keys in combinations(jsn.keys(),2) - for items in product(*(__mask(jsn[field], keep) - if field not in keep else [jsn[field]] - for field in keys)) - if keys and all(k not in jsn.keys() or k in keys for k in keep) ] - if isinstance(jsn, list): - if jsn: - return [[possibility] + jsn[1:] for possibility in __mask(jsn[0], keep)] - else: - return [[]] - else: - return [jsn] - - -def test_roundtrip_with_missing_fields(): - json_compiler = JSONCompiler() - json_parser = JSONParser_1_4() - with open("tests/data/metadata_v14.json", "r") as _input_file: - input_string = _input_file.read() - for expected_json in __mask(json.loads(input_string), keep=["id", "metaMetadata"]): - assert_equal(json_compiler.visit(json_parser.parse(expected_json)), expected_json) - diff --git a/tests/test_dialects/test_oep/test_compiler.py b/tests/test_dialects/test_oep/test_compiler.py deleted file mode 100644 index 13eaaa4..0000000 --- a/tests/test_dialects/test_oep/test_compiler.py +++ /dev/null @@ -1,84 +0,0 @@ -import json - -from omi.dialects.oep.compiler import JSONCompiler, JSONCompilerOEM15 - -from ..internal_structures import metadata_v_1_4, metadata_v_1_5 - - -def test_compiler_v1_5(): - compiler = JSONCompilerOEM15() - # omit none values as expected result also does not include None´s - compiler.OMIT_NONE_FIELDS = True - with open("tests/data/metadata_v15.json", "r", encoding="utf-8") as _input_file: - expected_result = json.load(_input_file) - result = compiler.visit(metadata_v_1_5) - assert_equal(expected_result, result) - - -def test_compiler_v1_4(): - compiler = JSONCompiler() - # omit none values as expected result also does not include None´s - compiler.OMIT_NONE_FIELDS = True - with open("tests/data/metadata_v14.json", "r", encoding="utf-8") as _input_file: - expected_result = json.load(_input_file) - result = compiler.visit(metadata_v_1_4) - assert_equal(expected_result, result) - - -def assert_equal(first, second, nulls=frozenset(["none"]), **kwargs): - if isinstance(first, dict): - assert_dict_equal(first, second, **kwargs) - elif isinstance(first, list): - assert_list_equal(first, second, **kwargs) - else: - if first in nulls and second is None: - return - assert first == second - - -def assert_dict_equal(first, second, **kwargs): - assert_list_equal(list(first.keys()), list(second.keys()), disregard_ordering=True) - for key in first.keys(): - if key not in second: - raise Exception('Key "{}" missing in {}'.format(key, second)) - assert_equal(first[key], second[key], **kwargs) - - -def assert_list_equal(first, second, disregard_ordering=False, **kwargs): - assert len(first) == len(second), "Length mismatch ({}!={}) for {} and {}".format( - len(first), len(second), first, second - ) - - if disregard_ordering: - remaining = list(second) - for expected in first: - to_remove = None - for i, result in enumerate(remaining): - try: - assert_equal( - expected, - result, - disregard_ordering=disregard_ordering, - **kwargs - ) - except: - pass - else: - to_remove = i - if to_remove is not None: - del remaining[to_remove] - else: - raise AssertionError( - "Element not found: {} in {}".format(expected, second) - ) - if remaining: - raise AssertionError( - "Elements not found: {} in {}".format(remaining, first) - ) - else: - for i, (l, r) in enumerate(zip(first, second)): - try: - assert_equal(l, r, **kwargs) - except: - print("Mismatch in element {}: {}!={}".format(i, l, r)) - raise diff --git a/tests/test_dialects/test_oep/test_parser.py b/tests/test_dialects/test_oep/test_parser.py deleted file mode 100644 index 443b995..0000000 --- a/tests/test_dialects/test_oep/test_parser.py +++ /dev/null @@ -1,67 +0,0 @@ -from email import parser -import unittest -from omi.dialects.oep.parser import JSONParser_1_3 -from omi.dialects.oep.parser import JSONParser_1_4 -from omi.dialects.oep.parser import JSONParser_1_5 - -from ..base.parser import _test_generic_parsing -from ..internal_structures import metadata_v_1_3 -from ..internal_structures import metadata_v_1_3_minimal -from ..internal_structures import metadata_v_1_4 -from ..internal_structures import metadata_v_1_4_minimal -from ..internal_structures import metadata_v_1_5 -from ..internal_structures import metadata_v_1_5_minimal -from omi.dialects.base.parser import ParserException - -from metadata.latest.schema import OEMETADATA_LATEST_SCHEMA - -import json - - -class ParserTest(unittest.TestCase): - def test_parser_v1_3(self): - parser = JSONParser_1_3() - _input_file = "tests/data/metadata_v13.json" - expected_result = metadata_v_1_3 - _test_generic_parsing(parser, _input_file, expected_result, nulls=["none", ""]) - - def test_parser_v1_4(self): - parser = JSONParser_1_4() - _input_file = "tests/data/metadata_v14.json" - expected_result = metadata_v_1_4 - _test_generic_parsing(parser, _input_file, expected_result) - - def test_parser_v1_4_Resource(self): - parser = JSONParser_1_4() - _input_file = "tests/data/metadata_v14_withoutresource.json" - expected_result = metadata_v_1_4 - with self.assertRaises(ParserException): - _test_generic_parsing(parser, _input_file, expected_result) - - def test_parser_v1_3_minimal(self): - parser = JSONParser_1_3() - _input_file = "tests/data/metadata_v13_minimal.json" - expected_result = metadata_v_1_3_minimal - _test_generic_parsing(parser, _input_file, expected_result) - - def test_parser_v1_4_minimal(self): - parser = JSONParser_1_4() - _input_file = "tests/data/metadata_v14_minimal.json" - expected_result = metadata_v_1_4_minimal - _test_generic_parsing(parser, _input_file, expected_result) - - def test_parser_v1_5(self): - parser = JSONParser_1_5() - _input_file = "tests/data/metadata_v15.json" - expected_result = metadata_v_1_5 - _test_generic_parsing(parser, _input_file, expected_result) - - def test_parser_v1_5_is_valid(self): - parser = JSONParser_1_5() - _input_file = "tests/data/metadata_v15.json" - - with open(_input_file, "r", encoding="utf-8") as f: - jsn = json.load(f) - - # file = parser.parse_from_file(_input_file) - parser.validate(jsn) diff --git a/tests/test_dialects/test_oep/test_regression/__init__.py b/tests/test_dialects/test_oep/test_regression/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py b/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py deleted file mode 100644 index f701b2e..0000000 --- a/tests/test_dialects/test_oep/test_regression/test_issue86_datetime.py +++ /dev/null @@ -1,105 +0,0 @@ -import json -from unittest import SkipTest -from unittest import TestCase - -from omi.dialects.oep import OEP_V_1_3_Dialect -from omi.dialects.oep import OEP_V_1_4_Dialect -from omi.dialects.oep import OEP_V_1_5_Dialect -from omi.dialects.oep.compiler import compile_date_or_none -from omi.dialects.oep.parser import ParserException -from omi.dialects.oep.parser import parse_date_or_none - -# in the metadata, for some values we return the date,not the full datetime - - -class TestIssue86Datetime(TestCase): - - BAD_VALUES = [True, {}, "", "not a date", "200", "2020-30-40", "2020-01-01 WTF"] - OK_VALUES = { - None: None, - 2020: 2020, - "2020": "2020", - "2020-12": "2020-12", - "2020-12-02": "2020-12-02", - "2020-12-2": "2020-12-02", - "2020-10-01T10:12:13": "2020-10-01T10:12:13", - "2020-10-01 10:12": "2020-10-01T10:12:00", - "2020-10-01T10:12:13+0200": "2020-10-01T10:12:13+02:00", - } - - def roundtrip_value(self, value): - value = parse_date_or_none(value) - value = compile_date_or_none(value) - return value - - def test_datetime_roundtrip(self): - for bad_value in self.BAD_VALUES: - self.assertRaises(ParserException, self.roundtrip_value, bad_value) - for ok_value, exp_value in self.OK_VALUES.items(): - self.assertEqual(self.roundtrip_value(ok_value), exp_value) - - -class TestIssue86Metadata(TestIssue86Datetime): - """test roundtrip in OEP_V_1_5_Dialect""" - - dialect = None - OK_VALUES = { - None: (None, None), - 2020: (2020, 2020), - "2020": ("2020", "2020"), - "2020-12": ("2020-12", "2020-12"), - "2020-12-02": ("2020-12-02", "2020-12-02"), - "2020-12-2": ("2020-12-02", "2020-12-02"), - "2020-10-01T10:12:13": ("2020-10-01T10:12:13", "2020-10-01"), - "2020-10-01 10:12": ("2020-10-01T10:12:00", "2020-10-01"), - "2020-10-01T10:12:13+0200": ("2020-10-01T10:12:13+02:00", "2020-10-01"), - } - - def test_datetime_roundtrip(self): - # only actually run tests in subclasses - if self.dialect: - return super().test_datetime_roundtrip() - - def roundtrip_value(self, value): - metadata_in = {"id": "test"} - self.set_date_datetime_values(metadata_in, value) - metadata_str = json.dumps(metadata_in) - metadata_obj = self.dialect.parse(metadata_str) - metadata_out = self.dialect.compile(metadata_obj) - return self.get_date_datetime_values(metadata_out) - - def set_date_datetime_values(self, metadata, value): - raise NotImplementedError() - - def get_date_datetime_values(self, metadata): - raise NotImplementedError() - - -class TestIssue86Datetime_V_1_5(TestIssue86Metadata): - """test roundtrip in OEP_V_1_5_Dialect""" - - dialect = OEP_V_1_5_Dialect() - - def set_date_datetime_values(self, metadata, value): - metadata["publicationDate"] = value - metadata["temporal"] = {"timeseries": [{"start": value}]} - - def get_date_datetime_values(self, metadata): - v_datetime = metadata["temporal"]["timeseries"][0].get("start") - v_date = metadata.get("publicationDate") - return (v_datetime, v_date) - - -class TestIssue86Datetime_V_1_4(TestIssue86Metadata): - """test roundtrip in OEP_V_1_4_Dialect""" - - dialect = OEP_V_1_4_Dialect() - - def set_date_datetime_values(self, metadata, value): - metadata["publicationDate"] = value - metadata["temporal"] = {"timeseries": {"start": value}} - - def get_date_datetime_values(self, metadata): - v_datetime = metadata["temporal"]["timeseries"].get("start") - v_date = metadata.get("publicationDate") - return (v_datetime, v_date) diff --git a/tests/test_dialects/test_oep/test_translation.py b/tests/test_dialects/test_oep/test_translation.py deleted file mode 100644 index 1448ebd..0000000 --- a/tests/test_dialects/test_oep/test_translation.py +++ /dev/null @@ -1,30 +0,0 @@ -import json -from collections import OrderedDict - -from omi.dialects.oep.compiler import JSONCompiler -from omi.dialects.oep.parser import JSONParser_1_3 - -from .test_compiler import assert_equal - - -def test_translation_1_3_to_1_4(): - parser = JSONParser_1_3() - compiler = JSONCompiler() - # omit none values as expected result also does not include None´s - compiler.OMIT_NONE_FIELDS = True - with open("tests/data/metadata_v13_minimal.json", "r") as _input_file: - input_string = _input_file.read() - # Step 1: Parse JSON to internal structure - internal_metadata = parser.parse_from_string(input_string) - # Step 2: Translate to version 1_4 - result_json = compiler.visit(internal_metadata) - - expected_json = OrderedDict(json.loads('''{ - "metaMetadata": { - "metadataVersion": "OEP-1.4.0", - "metadataLicense": { - "name": "CC0-1.0", - "title": "Creative Commons Zero v1.0 Universal", - "path": "https://creativecommons.org/publicdomain/zero/1.0/"}}}''')) - - assert_equal(expected_json, result_json) diff --git a/tests/test_dialects/test_rdf/__init__.py b/tests/test_dialects/test_rdf/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_dialects/test_rdf/deactivate-test_compiler.py b/tests/test_dialects/test_rdf/deactivate-test_compiler.py deleted file mode 100644 index fd262f5..0000000 --- a/tests/test_dialects/test_rdf/deactivate-test_compiler.py +++ /dev/null @@ -1,26 +0,0 @@ -from rdflib import BNode -from rdflib import Graph -from rdflib.compare import _squashed_graphs_triples -from rdflib.compare import graph_diff -from rdflib.compare import isomorphic -from rdflib.compare import similar -from rdflib.compare import to_isomorphic - -from omi.dialects.rdf.compiler import RDFCompiler - -from ..internal_structures import metadata_v_1_4 -from omi.dialects.rdf.namespace import OEO -from rdflib.namespace import DCTERMS - - -def test_compiler_v1_4(): - compiler = RDFCompiler() - with open("tests/data/metadata_v14.ttl", "r", encoding="utf-8") as _input_file: - expected_graph = Graph() - expected_graph.parse(data=_input_file.read(), format="ttl") - _ = compiler.visit(metadata_v_1_4) - expected = to_isomorphic(expected_graph) - got = to_isomorphic(compiler.graph) - for (t1, t2) in _squashed_graphs_triples(expected, got): - assert t1 == t2 - assert isomorphic(expected, got) diff --git a/tests/test_dialects/test_rdf/deactivate-test_parser.py b/tests/test_dialects/test_rdf/deactivate-test_parser.py deleted file mode 100644 index 67cc489..0000000 --- a/tests/test_dialects/test_rdf/deactivate-test_parser.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- - -from omi.dialects.rdf.parser import RDFParser - -from ..base.parser import _test_generic_parsing -from ..internal_structures import metadata_v_1_4 - - -def test_parser_rdf(): - parser = RDFParser() - _input_file = "tests/data/metadata_v14.ttl" - expected_result = metadata_v_1_4 - _test_generic_parsing(parser, _input_file, expected_result) diff --git a/tests/test_dialects/test_rdf/deactivate-test_roundtrip.py b/tests/test_dialects/test_rdf/deactivate-test_roundtrip.py deleted file mode 100644 index 699e625..0000000 --- a/tests/test_dialects/test_rdf/deactivate-test_roundtrip.py +++ /dev/null @@ -1,33 +0,0 @@ -from rdflib import Graph -from rdflib.compare import _squashed_graphs_triples -from rdflib.compare import isomorphic - -from omi.dialects.oep.compiler import JSONCompiler -from omi.dialects.oep.parser import JSONParser_1_4 -from omi.dialects.oep.renderer import JSONRenderer -from omi.dialects.rdf.compiler import RDFCompiler -from omi.dialects.rdf.parser import RDFParser - - -def test_roundtrip(): - json_compiler = JSONCompiler() - json_parser = JSONParser_1_4() - json_renderer = JSONRenderer() - rdf_compiler = RDFCompiler() - rdf_p = RDFParser() - with open("tests/data/metadata_v14.ttl", "r") as _input_file: - input_string = _input_file.read() - expected_graph = Graph() - expected_graph.parse(data=input_string, format="ttl") - # Step 1: Parse Turtle to internal structure - internal_metadata = rdf_p.parse_from_string(input_string) - # Step 2: Translate to json string - json_metadata = json_renderer.render(json_compiler.visit(internal_metadata)) - # Step 3: Parse json string - internal_metadata2 = json_parser.parse_from_string(json_metadata) - # Step 4: Translate to Turtle - _ = rdf_compiler.visit(internal_metadata2) - # Final step: Compare - for (t1, t2) in _squashed_graphs_triples(expected_graph, rdf_compiler.graph): - assert t1 == t2 - assert isomorphic(expected_graph, rdf_compiler.graph) diff --git a/tests/test_inspection.py b/tests/test_inspection.py new file mode 100644 index 0000000..8cf504b --- /dev/null +++ b/tests/test_inspection.py @@ -0,0 +1,36 @@ +"""Tests for `inspection` module of OMI.""" + +import pathlib + +from omi import inspection + +CSV_DATA_FILE = pathlib.Path(__file__).parent / "test_data" / "inspection" / "data.csv" + + +def test_inspection(): + """Test inspection of test data file and check resulting metadata.""" + with CSV_DATA_FILE.open("r") as f: + metadata = inspection.infer_metadata(f, "OEP") + + assert len(metadata["resources"]) == 1 + assert len(metadata["resources"][0]["schema"]["fields"]) == 9 + + assert metadata["resources"][0]["schema"]["fields"][0]["name"] == "string" + assert metadata["resources"][0]["schema"]["fields"][1]["name"] == "integer" + assert metadata["resources"][0]["schema"]["fields"][2]["name"] == "number" + assert metadata["resources"][0]["schema"]["fields"][3]["name"] == "array string" + assert metadata["resources"][0]["schema"]["fields"][4]["name"] == "array integer" + assert metadata["resources"][0]["schema"]["fields"][5]["name"] == "array float" + assert metadata["resources"][0]["schema"]["fields"][6]["name"] == "object" + assert metadata["resources"][0]["schema"]["fields"][7]["name"] == "date" + assert metadata["resources"][0]["schema"]["fields"][8]["name"] == "bool" + + assert metadata["resources"][0]["schema"]["fields"][0]["type"] == "string" + assert metadata["resources"][0]["schema"]["fields"][1]["type"] == "integer" + assert metadata["resources"][0]["schema"]["fields"][2]["type"] == "float" + assert metadata["resources"][0]["schema"]["fields"][3]["type"] == "array string" + assert metadata["resources"][0]["schema"]["fields"][4]["type"] == "array integer" + assert metadata["resources"][0]["schema"]["fields"][5]["type"] == "array float" + assert metadata["resources"][0]["schema"]["fields"][6]["type"] == "object" + assert metadata["resources"][0]["schema"]["fields"][7]["type"] == "date" + assert metadata["resources"][0]["schema"]["fields"][8]["type"] == "boolean" diff --git a/tests/test_metadata_validation.py b/tests/test_metadata_validation.py new file mode 100644 index 0000000..a5aba38 --- /dev/null +++ b/tests/test_metadata_validation.py @@ -0,0 +1,164 @@ +"""Tests for validation module of OMI.""" + +import json +import pathlib +import re + +import pytest + +from omi import base, license, validation + +TEST_VALIDATION_DATA_PATH = pathlib.Path(__file__).parent / "test_data" / "validation" +INVALID_METADAT_PATH = TEST_VALIDATION_DATA_PATH / "invalid_metadata" + +UNSUPPORTED_OEP_METADATA_EXAMPLE_FILE = TEST_VALIDATION_DATA_PATH / "unsupported_oep_metadata_example.json" + + +def test_validation_of_oep_metadata(): + """Test successful validation of OEP metadata.""" + versions = ("OEP-1.5.2", "OEP-1.6.0") + for version in versions: + metadata_schema = base.get_metadata_specification(version) + validation.validate_metadata(metadata_schema.example) + + +def test_invalid_oep_metadata(): + """Test if validation error is raised for different invalid OEP metadata.""" + with (INVALID_METADAT_PATH / "additional_key.json").open("r") as f: + invalid_oep_metadata = json.load(f) + # `re.escape` must be used, otherwise quotes around 'universe' are not detected correctly + with pytest.raises( + validation.ValidationError, + match=re.escape("Additional properties are not allowed ('universe' was unexpected)"), + ): + validation.validate_metadata(invalid_oep_metadata) + + with (INVALID_METADAT_PATH / "missing_fields.json").open("r") as f: + invalid_oep_metadata = json.load(f) + with pytest.raises( + license.LicenseError, + match=r"No license information available in the metadata for resource: \d+\.?", + ): + validation.validate_metadata(invalid_oep_metadata) + + with (INVALID_METADAT_PATH / "wrongly_placed_null_value.json").open("r") as f: + invalid_oep_metadata = json.load(f) + with pytest.raises(validation.ValidationError, match="None is not of type 'object'"): + validation.validate_metadata(invalid_oep_metadata) + + +def test_invalid_oep_metadata_caused_by_invalid_json(): + """Test if validation error is raised for invalid OEP metadata due to invalid JSOn syntax.""" + with (INVALID_METADAT_PATH / "duplicate_key.json").open("r") as f: + invalid_metadata_string = f.read() + with pytest.raises(validation.ValidationError, match="Duplicate keys in metadata: 'description'"): + validation.validate_metadata(invalid_metadata_string) + + with (INVALID_METADAT_PATH / "wrong_json_syntax.json").open("r") as f: + invalid_metadata_string = f.read() + with pytest.raises(validation.ValidationError, match="Failed to decode JSON: Expecting value"): + validation.validate_metadata(invalid_metadata_string) + + with (INVALID_METADAT_PATH / "wrong_nesting.json").open("r") as f: + invalid_metadata_string = f.read() + with pytest.raises( + validation.ValidationError, + match="Failed to decode JSON: Expecting property name enclosed in double quotes", + ): + validation.validate_metadata(invalid_metadata_string) + + with (INVALID_METADAT_PATH / "wrong_structure.json").open("r") as f: + invalid_metadata_string = f.read() + with pytest.raises(validation.ValidationError, match="Failed to decode JSON: Expecting ',' delimiter"): + validation.validate_metadata(invalid_metadata_string) + + +def test_unsupported_oep_metadata_version(): + """Test if validation error is raised for unsupported OEP metadata version.""" + with UNSUPPORTED_OEP_METADATA_EXAMPLE_FILE.open("r") as f: + unsupported_oep_metadata = json.load(f) + with pytest.raises( + base.MetadataError, + match="Metadata format for metadata version OEP-1.5.1 could not be found.", + ): + validation.validate_metadata(unsupported_oep_metadata) + + +def test_metadata_schema_for_oep_version(): + """Test schema, template and example for OEP metadata.""" + version = "OEP-1.5.2" + schema = base.get_metadata_specification(version) + assert schema.schema["description"] == "Open Energy Plaftorm (OEP) metadata schema v1.5.2" + assert schema.template["name"] is None + assert schema.example["name"] == "oep_metadata_table_example_v152" + + +def test_metadata_schema_not_found(): + """Test failing schema for invalid metadata version.""" + with pytest.raises( + base.MetadataError, + match="Metadata format for metadata version OEP-1.5.0 could not be found.", + ): + base.get_metadata_specification("OEP-1.5.0") + + +def test_metadata_against_oep_table(): + """Test OEP table definition against OEP metadata.""" + table = "x2x_p2gas_soec_1" + with (TEST_VALIDATION_DATA_PATH / "metadata_oep_validation.json").open("r") as f: + metadata = json.load(f) + validation.validate_oep_table_against_metadata(oep_table=table, oep_schema="model_draft", metadata=metadata) + + +def test_metadata_against_oep_table_using_metadata_from_oep(): + """Test OEP table definition against OEP metadata, where metadata is taken from OEP.""" + table = "x2x_p2gas_soec_1" + with pytest.raises(validation.ValidationError, match="None is not of type 'object'"): + validation.validate_oep_table_against_metadata(oep_table=table, oep_schema="model_draft") + + +def test_metadata_against_oep_table_invalid_name(): + """Test different naming convention violation for OEP metadata.""" + table = "x2x_p2gas_soec_1" + with (TEST_VALIDATION_DATA_PATH / "metadata_oep_validation.json").open("r") as f: + metadata = json.load(f) + metadata["resources"][0]["name"] = "invalid" + with pytest.raises( + validation.ValidationError, + match=f"Name 'invalid' of metadata resource does not fit to oep table name. " + f"It should be one of '{table}', or 'model_draft.{table}'.", + ): + validation.validate_oep_table_against_metadata(oep_table=table, oep_schema="model_draft", metadata=metadata) + del metadata["resources"][0]["name"] + with pytest.raises(validation.ValidationError, match="Metadata resource has no name."): + validation.validate_oep_table_against_metadata(oep_table=table, oep_schema="model_draft", metadata=metadata) + + +def test_metadata_against_oep_table_with_missing_fields(): + """Test error raised for missing fields.""" + table = "x2x_p2gas_soec_1" + with (TEST_VALIDATION_DATA_PATH / "metadata_oep_validation.json").open("r") as f: + metadata = json.load(f) + metadata["resources"][0]["schema"]["fields"].append({"name": "added_field", "type": "string"}) + with pytest.raises(validation.ValidationError, match="Field 'added_field' not defined in OEP table"): + validation.validate_oep_table_against_metadata(oep_table=table, oep_schema="model_draft", metadata=metadata) + metadata["resources"][0]["schema"]["fields"].pop() + metadata["resources"][0]["schema"]["fields"].pop() + with pytest.raises( + validation.ValidationError, + match=f"Field 'comment' from OEP table 'model_draft.{table}' is missing in metadata schema.", + ): + validation.validate_oep_table_against_metadata(oep_table=table, oep_schema="model_draft", metadata=metadata) + + +def test_metadata_against_oep_table_with_incompatible_field_types(): + """Test error raised for incompatible field types.""" + table = "x2x_p2gas_soec_1" + with (TEST_VALIDATION_DATA_PATH / "metadata_oep_validation.json").open("r") as f: + metadata = json.load(f) + metadata["resources"][0]["schema"]["fields"][0]["type"] = "string" + with pytest.raises( + validation.ValidationError, + match="Field type 'bigint' from OEP table field 'id' differs from type 'string' defined in metadata schema.", + ): + validation.validate_oep_table_against_metadata(oep_table=table, oep_schema="model_draft", metadata=metadata) diff --git a/tox.ini b/tox.ini index 1bda854..4b495f3 100644 --- a/tox.ini +++ b/tox.ini @@ -36,16 +36,12 @@ commands = [testenv:check] deps = - docutils - check-manifest + poetry flake8 - readme-renderer - pygments isort skip_install = true commands = - python setup.py check --strict --metadata --restructuredtext - check-manifest {toxinidir} + poetry check --lock isort --verbose --check-only --diff src [testenv:spell] @@ -59,14 +55,6 @@ deps = sphinxcontrib-spelling pyenchant -[testenv:docs] -deps = - -r{toxinidir}/docs/requirements.txt -commands = - sphinx-build {posargs:-E} -b doctest docs dist/docs - sphinx-build {posargs:-E} -b html docs dist/docs -; sphinx-build -b linkcheck docs dist/docs - [testenv:codecov] deps = codecov