diff --git a/.cruft.json b/.cruft.json new file mode 100644 index 0000000..dc11afe --- /dev/null +++ b/.cruft.json @@ -0,0 +1,27 @@ +{ + "template": "https://github.com/linkml/linkml-project-cookiecutter", + "commit": "b2da87eb7835bfec748a76823d098cac85e8363a", + "checkout": null, + "context": { + "cookiecutter": { + "project_name": "linkml-tutorial-2024", + "__project_slug": "linkml_tutorial_2024", + "github_org": "my-org", + "__source_path": "src/linkml_tutorial_2024/schema/linkml_tutorial_2024.yaml", + "project_description": "This is the project description.", + "full_name": "My Name", + "email": "my-name@my-org.org", + "__author": "My Name ", + "license": "Apache Software License 2.0", + "main_schema_class": "Person", + "create_python_classes": "Yes", + "use_schemasheets": "No", + "google_sheet_id": "1wVoaiFg47aT9YWNeRfTZ8tYHN8s8PAuDx5i2HUcDpvQ", + "google_sheet_tabs": "personinfo enums", + "__google_sheet_module": "personinfo_enums", + "github_token_for_pypi_deployment": "PYPI_PASSWORD", + "_template": "https://github.com/linkml/linkml-project-cookiecutter" + } + }, + "directory": null +} diff --git a/.env.public b/.env.public new file mode 100644 index 0000000..b05edbc --- /dev/null +++ b/.env.public @@ -0,0 +1,27 @@ +# This file is public in git. No sensitive info allowed. + +###### schema definition variables, used by makefile + +LINKML_SCHEMA_NAME="linkml_tutorial_2024" +LINKML_SCHEMA_AUTHOR="My Name " +LINKML_SCHEMA_DESCRIPTION="This is the project description." +LINKML_SCHEMA_SOURCE_PATH="src/linkml_tutorial_2024/schema/linkml_tutorial_2024.yaml" +LINKML_SCHEMA_GOOGLE_SHEET_ID="1wVoaiFg47aT9YWNeRfTZ8tYHN8s8PAuDx5i2HUcDpvQ" +LINKML_SCHEMA_GOOGLE_SHEET_TABS="personinfo enums" + +###### linkml generator variables, used by makefile + +## gen-project configuration file +LINKML_GENERATORS_CONFIG_YAML= --config-file config.yaml + +## pass args if gendoc ignores config.yaml (i.e. --no-mergeimports) +LINKML_GENERATORS_DOC_ARGS= + +## pass args to workaround genowl rdfs config bug (linkml#1453) +## (i.e. --no-type-objects --no-metaclasses --metadata-profile rdfs) +LINKML_GENERATORS_OWL_ARGS= + +## pass args to trigger experimental java/typescript generation +LINKML_GENERATORS_JAVA_ARGS= +LINKML_GENERATORS_TYPESCRIPT_ARGS= + diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml new file mode 100644 index 0000000..37e95be --- /dev/null +++ b/.github/workflows/deploy-docs.yaml @@ -0,0 +1,40 @@ +--- +name: Auto-deployment of linkml_tutorial_2024 Documentation +on: + push: + branches: [main] + +jobs: + build-docs: + runs-on: ubuntu-latest + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + permissions: + contents: write # to let mkdocs write the new docs + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # otherwise, you will failed to push refs to dest repo + + - name: Set up Python. + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Install Poetry. + run: pipx install poetry + + - name: Install dependencies. + run: poetry install -E docs + + - name: Build documentation. + run: | + mkdir -p docs + touch docs/.nojekyll + make gendoc + ([ ! -f docs/about.md ] && cp src/docs/about.md docs/) || true + make mkd-gh-deploy diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml new file mode 100644 index 0000000..32593af --- /dev/null +++ b/.github/workflows/main.yaml @@ -0,0 +1,36 @@ +# Built from: +# https://docs.github.com/en/actions/guides/building-and-testing-python +--- +name: Build and test linkml_tutorial_2024 + +on: [pull_request] + +jobs: + test: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10"] + + steps: + + - name: Check out repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + run: pipx install poetry + + - name: Install dependencies + run: poetry install --no-interaction --no-root + + - name: Install project + run: poetry install --no-interaction + + - name: Run test suite + run: make test diff --git a/.github/workflows/pypi-publish.yaml b/.github/workflows/pypi-publish.yaml new file mode 100644 index 0000000..22d5a69 --- /dev/null +++ b/.github/workflows/pypi-publish.yaml @@ -0,0 +1,36 @@ +--- +name: Publish Python Package + +on: + release: + types: [created] + +jobs: + build-n-publish: + name: Build and publish Python ๐Ÿ distributions ๐Ÿ“ฆ to PyPI + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Install Poetry + run: | + pipx install poetry + poetry self add "poetry-dynamic-versioning[plugin]" + + # - name: Install dependencies + # run: poetry install --no-interaction + + - name: Build source and wheel archives + run: poetry build + + - name: Publish distribution ๐Ÿ“ฆ to PyPI + uses: pypa/gh-action-pypi-publish@v1.2.2 + with: + user: __token__ + password: ${{ secrets.PYPI_PASSWORD }} diff --git a/.github/workflows/test_pages_build.yaml b/.github/workflows/test_pages_build.yaml new file mode 100644 index 0000000..bc6723b --- /dev/null +++ b/.github/workflows/test_pages_build.yaml @@ -0,0 +1,44 @@ +name: Preview linkml_tutorial_2024 documentation build + +on: + pull_request: + types: + - opened + - reopened + - synchronize + +concurrency: preview-${{ github.ref }} + +jobs: + run: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python 3 + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Install Poetry + run: pipx install poetry + + - name: Install dependencies + run: poetry install -E docs + + - name: Build documentation + run: | + mkdir -p site + touch site/.nojekyll + make gendoc + ([ ! -f docs/about.md ] && cp src/docs/about.md docs/) || true + poetry run mkdocs build -d site + + - name: Deploy preview + uses: rossjrw/pr-preview-action@v1 + with: + source-dir: site/ + preview-branch: gh-pages diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e110be5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,133 @@ +/docs/ +/project/docs/ +/tmp/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..2b301c6 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, +body size, disability, ethnicity, gender identity and expression, level of +experience, nationality, personal appearance, race, religion, or sexual +identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an +appointed representative at an online or offline event. Representation of a +project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by [contacting the project team](contact.md). All complaints will be +reviewed and investigated and will result in a response that is deemed +necessary and appropriate to the circumstances. The project team is obligated +to maintain confidentiality with regard to the reporter of an incident. Further +details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This code of conduct has been derived from the excellent code of conduct of the +[ATOM project](https://github.com/atom/atom/blob/master/CODE_OF_CONDUCT.md) +which in turn is adapted from the [Contributor Covenant][homepage], version +1.4, available at [https://contributor-covenant.org/version/1/4][version] + +[homepage]: https://contributor-covenant.org +[version]: https://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..fb88cef --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,121 @@ +# Contributing to linkml-tutorial-2024 + +:+1: First of all: Thank you for taking the time to contribute! + +The following is a set of guidelines for contributing to +linkml-tutorial-2024. These guidelines are not strict rules. +Use your best judgment, and feel free to propose changes to this document +in a pull request. + +## Table Of Contents + +* [Code of Conduct](#code-of-conduct) +* [Guidelines for Contributions and Requests](#contributions) + * [Reporting issues and making requests](#reporting-issues) + * [Questions and Discussion](#questions-and-discussion) + * [Adding new elements yourself](#adding-elements) +* [Best Practices](#best-practices) + * [How to write a great issue](#great-issues) + * [How to create a great pull/merge request](#great-pulls) + + + +## Code of Conduct + +The linkml-tutorial-2024 team strives to create a +welcoming environment for editors, users and other contributors. +Please carefully read our [Code of Conduct](CODE_OF_CONDUCT.md). + + + +## Guidelines for Contributions and Requests + + + +### Reporting problems and suggesting changes to with the data model + +Please use our [Issue Tracker][issues] for any of the following: + +- Reporting problems +- Requesting new schema elements + + + +### Questions and Discussions + +Please use our [Discussions forum][discussions] to ask general questions or contribute to discussions. + + + +### Adding new elements yourself + +Please submit a [Pull Request][pulls] to submit a new term for consideration. + + + +## Best Practices + + + +### GitHub Best Practice + +- Creating and curating issues + - Read ["About Issues"][[about-issues]] + - Issues should be focused and actionable + - Complex issues should be broken down into simpler issues where possible +- Pull Requests + - Read ["About Pull Requests"][about-pulls] + - Read [GitHub Pull Requests: 10 Tips to Know](https://blog.mergify.com/github-pull-requests-10-tips-to-know/) + - Pull Requests (PRs) should be atomic and aim to close a single issue + - Long running PRs should be avoided where possible + - PRs should reference issues following standard conventions (e.g. โ€œfixes #123โ€) + - Schema developers should always be working on a single issue at any one time + - Never work on the main branch, always work on an issue/feature branch + - Core developers can work on branches off origin rather than forks + - Always create a PR on a branch to maximize transparency of what you are doing + - PRs should be reviewed and merged in a timely fashion by the linkml-tutorial-2024 technical leads + - PRs that do not pass GitHub actions should never be merged + - In the case of git conflicts, the contributor should try and resolve the conflict + - If a PR fails a GitHub action check, the contributor should try and resolve the issue in a timely fashion + +### Understanding LinkML + +Core developers should read the material on the [LinkML site](https://linkml.io/linkml), in particular: + +- [Overview](https://linkml.io/linkml/intro/overview.html) +- [Tutorial](https://linkml.io/linkml/intro/tutorial.html) +- [Schemas](https://linkml.io/linkml/schemas/index.html) +- [FAQ](https://linkml.io/linkml/faq/index.html) + +### Modeling Best Practice + +- Follow Naming conventions + - Standard LinkML naming conventions should be followed (UpperCamelCase for classes and enums, snake_case for slots) + - Know how to use the LinkML linter to check style and conventions + - The names for classes should be nouns or noun-phrases: Person, GenomeAnnotation, Address, Sample + - Spell out abbreviations and short forms, except where this goes against convention (e.g. do not spell out DNA) + - Elements that are imported from outside (e.g. schema.org) need not follow the same naming conventions + - Multivalued slots should be named as plurals +- Document model elements + - All model elements should have documentation (descriptions) and other textual annotations (e.g. comments, notes) + - Textual annotations on classes, slots and enumerations should be written with minimal jargon, clear grammar and no misspellings +- Include examples and counter-examples (intentionally invalid examples) + - Rationale: these serve as documentation and unit tests + - These will be used by the automated test suite + - All elements of the nmdc-schema must be illustrated with valid and invalid data examples in src/data. New schema elements will not be merged into the main branch until examples are provided + - Invalid example data files should be invalid for one single reason, which should be reflected in the filename. It should be possible to render the invalid example files valid by addressing that single fault. +- Use enums for categorical values + - Rationale: Open-ended string ranges encourage multiple values to represent the same entity, like โ€œwaterโ€, โ€œH2Oโ€ and โ€œHOHโ€ + - Any slot whose values could be constrained to a finite set should use an Enum + - Non-categorical values, e.g. descriptive fields like `name` or `description` fall outside of this. +- Reuse + - Existing scheme elements should be reused where appropriate, rather than making duplicative elements + - More specific classes can be created by refinining classes using inheritance (`is_a`) + +[about-branches]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches +[about-issues]: https://docs.github.com/en/issues/tracking-your-work-with-issues/about-issues +[about-pulls]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests +[issues]: https://github.com/my-org/linkml-tutorial-2024/issues/ +[pulls]: https://github.com/my-org/linkml-tutorial-2024/pulls/ + +We recommend also reading [GitHub Pull Requests: 10 Tips to Know](https://blog.mergify.com/github-pull-requests-10-tips-to-know/) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..427417b --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ecc0788 --- /dev/null +++ b/Makefile @@ -0,0 +1,225 @@ +MAKEFLAGS += --warn-undefined-variables +SHELL := bash +.SHELLFLAGS := -eu -o pipefail -c +.DEFAULT_GOAL := help +.DELETE_ON_ERROR: +.SUFFIXES: +.SECONDARY: + +# environment variables +.EXPORT_ALL_VARIABLES: +ifdef LINKML_ENVIRONMENT_FILENAME +include ${LINKML_ENVIRONMENT_FILENAME} +else +include .env.public +endif + +RUN = poetry run +SCHEMA_NAME = $(LINKML_SCHEMA_NAME) +SOURCE_SCHEMA_PATH = $(LINKML_SCHEMA_SOURCE_PATH) +SOURCE_SCHEMA_DIR = $(dir $(SOURCE_SCHEMA_PATH)) +SRC = src +DEST = project +PYMODEL = $(SRC)/$(SCHEMA_NAME)/datamodel +DOCDIR = docs +EXAMPLEDIR = examples +SHEET_MODULE = personinfo_enums +SHEET_ID = $(LINKML_SCHEMA_GOOGLE_SHEET_ID) +SHEET_TABS = $(LINKML_SCHEMA_GOOGLE_SHEET_TABS) +SHEET_MODULE_PATH = $(SOURCE_SCHEMA_DIR)/$(SHEET_MODULE).yaml + +CONFIG_YAML = +ifdef LINKML_GENERATORS_CONFIG_YAML +CONFIG_YAML = ${LINKML_GENERATORS_CONFIG_YAML} +endif + +GEN_DOC_ARGS = +ifdef LINKML_GENERATORS_DOC_ARGS +GEN_DOC_ARGS = ${LINKML_GENERATORS_DOC_ARGS} +endif + +GEN_OWL_ARGS = +ifdef LINKML_GENERATORS_OWL_ARGS +GEN_OWL_ARGS = ${LINKML_GENERATORS_OWL_ARGS} +endif + +GEN_JAVA_ARGS = +ifdef LINKML_GENERATORS_JAVA_ARGS +GEN_JAVA_ARGS = ${LINKML_GENERATORS_JAVA_ARGS} +endif + +GEN_TS_ARGS = +ifdef LINKML_GENERATORS_TYPESCRIPT_ARGS +GEN_TS_ARGS = ${LINKML_GENERATORS_TYPESCRIPT_ARGS} +endif + + +# basename of a YAML file in model/ +.PHONY: all clean setup gen-project gen-examples gendoc git-init-add git-init git-add git-commit git-status + +# note: "help" MUST be the first target in the file, +# when the user types "make" they should get help info +help: status + @echo "" + @echo "make setup -- initial setup (run this first)" + @echo "make site -- makes site locally" + @echo "make install -- install dependencies" + @echo "make test -- runs tests" + @echo "make lint -- perform linting" + @echo "make testdoc -- builds docs and runs local test server" + @echo "make deploy -- deploys site" + @echo "make update -- updates linkml version" + @echo "make help -- show this help" + @echo "" + +status: check-config + @echo "Project: $(SCHEMA_NAME)" + @echo "Source: $(SOURCE_SCHEMA_PATH)" + +# generate products and add everything to github +setup: check-config git-init install gen-project gen-examples gendoc git-add git-commit + +# install any dependencies required for building +install: + poetry install +.PHONY: install + +# --- +# Project Synchronization +# --- +# +# check we are up to date +check: cruft-check +cruft-check: + cruft check +cruft-diff: + cruft diff + +update: update-template update-linkml +update-template: + cruft update + +# todo: consider pinning to template +update-linkml: + poetry add -D linkml@latest + +# EXPERIMENTAL +create-data-harmonizer: + npm init data-harmonizer $(SOURCE_SCHEMA_PATH) + +all: site +site: gen-project gendoc +%.yaml: gen-project +deploy: all mkd-gh-deploy + +compile-sheets: + $(RUN) sheets2linkml --gsheet-id $(SHEET_ID) $(SHEET_TABS) > $(SHEET_MODULE_PATH).tmp && mv $(SHEET_MODULE_PATH).tmp $(SHEET_MODULE_PATH) + +# In future this will be done by conversion +gen-examples: + cp src/data/examples/* $(EXAMPLEDIR) + +# generates all project files + +gen-project: $(PYMODEL) + $(RUN) gen-project ${CONFIG_YAML} -d $(DEST) $(SOURCE_SCHEMA_PATH) && mv $(DEST)/*.py $(PYMODEL) + + +# non-empty arg triggers owl (workaround https://github.com/linkml/linkml/issues/1453) +ifneq ($(strip ${GEN_OWL_ARGS}),) + mkdir -p ${DEST}/owl || true + $(RUN) gen-owl ${GEN_OWL_ARGS} $(SOURCE_SCHEMA_PATH) >${DEST}/owl/${SCHEMA_NAME}.owl.ttl +endif +# non-empty arg triggers java +ifneq ($(strip ${GEN_JAVA_ARGS}),) + $(RUN) gen-java ${GEN_JAVA_ARGS} --output-directory ${DEST}/java/ $(SOURCE_SCHEMA_PATH) +endif +# non-empty arg triggers typescript +ifneq ($(strip ${GEN_TS_ARGS}),) + mkdir -p ${DEST}/typescript || true + $(RUN) gen-typescript ${GEN_TS_ARGS} $(SOURCE_SCHEMA_PATH) >${DEST}/typescript/${SCHEMA_NAME}.ts +endif + +test: test-schema test-python test-examples + +test-schema: + $(RUN) gen-project ${CONFIG_YAML} -d tmp $(SOURCE_SCHEMA_PATH) + +test-python: + $(RUN) python -m unittest discover + +lint: + $(RUN) linkml-lint $(SOURCE_SCHEMA_PATH) + +check-config: +ifndef LINKML_SCHEMA_NAME + $(error **Project not configured**:\n\n - See '.env.public'\n\n) +else + $(info Ok) +endif + +convert-examples-to-%: + $(patsubst %, $(RUN) linkml-convert % -s $(SOURCE_SCHEMA_PATH) -C Person, $(shell ${SHELL} find src/data/examples -name "*.yaml")) + +examples/%.yaml: src/data/examples/%.yaml + $(RUN) linkml-convert -s $(SOURCE_SCHEMA_PATH) -C Person $< -o $@ +examples/%.json: src/data/examples/%.yaml + $(RUN) linkml-convert -s $(SOURCE_SCHEMA_PATH) -C Person $< -o $@ +examples/%.ttl: src/data/examples/%.yaml + $(RUN) linkml-convert -P EXAMPLE=http://example.org/ -s $(SOURCE_SCHEMA_PATH) -C Person $< -o $@ + +test-examples: examples/output + +examples/output: src/linkml_tutorial_2024/schema/linkml_tutorial_2024.yaml + mkdir -p $@ + $(RUN) linkml-run-examples \ + --output-formats json \ + --output-formats yaml \ + --counter-example-input-directory src/data/examples/invalid \ + --input-directory src/data/examples/valid \ + --output-directory $@ \ + --schema $< > $@/README.md + +# Test documentation locally +serve: mkd-serve + +# Python datamodel +$(PYMODEL): + mkdir -p $@ + + +$(DOCDIR): + mkdir -p $@ + +gendoc: $(DOCDIR) + cp -rf $(SRC)/docs/* $(DOCDIR) ; \ + $(RUN) gen-doc ${GEN_DOC_ARGS} -d $(DOCDIR) $(SOURCE_SCHEMA_PATH) + +testdoc: gendoc serve + +MKDOCS = $(RUN) mkdocs +mkd-%: + $(MKDOCS) $* + +git-init-add: git-init git-add git-commit git-status +git-init: + git init +git-add: .cruft.json + git add . +git-commit: + git commit -m 'chore: make setup was run' -a +git-status: + git status + +# only necessary if setting up via cookiecutter +.cruft.json: + echo "creating a stub for .cruft.json. IMPORTANT: setup via cruft not cookiecutter recommended!" ; \ + touch $@ + +clean: + rm -rf $(DEST) + rm -rf tmp + rm -fr docs/* + rm -fr $(PYMODEL)/* + +include project.Makefile diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6d72e0 --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# linkml-tutorial-2024 + +This is the project description. + +## Website + +[https://my-org.github.io/linkml-tutorial-2024](https://my-org.github.io/linkml-tutorial-2024) + +## Repository Structure + +* [examples/](examples/) - example data +* [project/](project/) - project files (do not edit these) +* [src/](src/) - source files (edit these) + * [linkml_tutorial_2024](src/linkml_tutorial_2024) + * [schema](src/linkml_tutorial_2024/schema) -- LinkML schema + (edit this) + * [datamodel](src/linkml_tutorial_2024/datamodel) -- generated + Python datamodel +* [tests/](tests/) - Python tests + +## Developer Documentation + +
+Use the `make` command to generate project artefacts: + +* `make all`: make everything +* `make deploy`: deploys site +
+ +## Credits + +This project was made with +[linkml-project-cookiecutter](https://github.com/linkml/linkml-project-cookiecutter). diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..56da66d --- /dev/null +++ b/config.yaml @@ -0,0 +1,41 @@ +# Configuration of generators (defaults illustrated) +--- +generator_args: + excel: + mergeimports: true + owl: + mergeimports: true + metaclasses: true + type_objects: true + # throws 'Cannot handle metadata profile: rdfs' + # metadata_profile: rdfs + markdown: + mergeimports: true + graphql: + mergeimports: true + java: + mergeimports: true + metadata: true + jsonld: + mergeimports: true + jsonschema: + mergeimports: true + jsonldcontext: + mergeimports: true + python: + mergeimports: true + prefixmap: + mergeimports: true + proto: + mergeimports: true + shacl: + mergeimports: true + shex: + mergeimports: true + sqlddl: + mergeimports: true + typescript: + mergeimports: true + metadata: true + +... diff --git a/examples/Person-001.yaml b/examples/Person-001.yaml new file mode 100644 index 0000000..617ff08 --- /dev/null +++ b/examples/Person-001.yaml @@ -0,0 +1,7 @@ +# Example data object +--- +entries: + - id: example:Person001 + name: foo bar + primary_email: foo.bar@example.com + age_in_years: 33 diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..41ff69a --- /dev/null +++ b/examples/README.md @@ -0,0 +1,5 @@ +# Examples of use of linkml_tutorial_2024 + +This folder contains example data conforming to linkml_tutorial_2024 + +The source for these is in [src/data](../src/data/examples) diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..889dbd2 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,27 @@ +--- +site_name: "linkml-tutorial-2024" +theme: + name: material + # palette: + # scheme: slate + # primary: cyan + features: + - content.tabs.link +plugins: + - search + - mermaid2 + - mermaid2: + version: 10.9.0 +nav: + # - Home: home.md + - Index: index.md + - About: about.md +site_url: https://my-org.github.io/linkml-tutorial-2024 +repo_url: https://github.com/my-org/linkml-tutorial-2024 + +# Uncomment this block to enable use of Google Analytics. +# Replace the property value with your own ID. +# extra: +# analytics: +# provider: google +# property: G-XXXXXXXXXX diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..a768249 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1717 @@ +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "antlr4-python3-runtime" +version = "4.9.3" +description = "ANTLR 4.9.3 runtime for Python 3.7" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "arrow" +version = "1.3.0" +description = "Better dates & times for Python" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + +[package.extras] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (>=1.0.0,<2.0.0)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (>=3.0.0,<4.0.0)"] + +[[package]] +name = "attrs" +version = "23.2.0" +description = "Classes Without Boilerplate" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +cov = ["attrs", "coverage[toml] (>=5.3)"] +dev = ["attrs", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs", "zope-interface"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs", "cloudpickle", "hypothesis", "pympler", "pytest-xdist", "pytest (>=4.3.0)"] + +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +category = "dev" +optional = false +python-versions = ">=3.6.0" + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "bioregistry" +version = "0.11.10" +description = "Integrated registry of biological databases and nomenclatures" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +click = "*" +curies = ">=0.7.0" +more-click = ">=0.1.2" +pydantic = "*" +pystow = ">=0.1.13" +requests = "*" +tqdm = "*" + +[package.extras] +align = ["pyyaml", "beautifulsoup4", "tabulate", "defusedxml", "class-resolver", "fairsharing-client (>=0.1.0)", "pandas"] +charts = ["matplotlib", "matplotlib-venn", "seaborn", "pandas", "jinja2"] +docs = ["sphinx (<7.3)", "sphinx-rtd-theme", "sphinx-click", "sphinx-automodapi", "autodoc-pydantic"] +export = ["pyyaml", "rdflib", "rdflib-jsonld", "ndex2"] +gha = ["more-itertools"] +health = ["click-default-group", "pandas", "tabulate", "pyyaml", "jinja2"] +tests = ["coverage", "pytest", "more-itertools", "httpx"] +web = ["pyyaml", "rdflib", "rdflib-jsonld", "rdflib-endpoint", "flask (<2.2.4)", "werkzeug (<2.3.0)", "fastapi", "uvicorn", "bootstrap-flask (<=2.0.0)", "markdown", "curies"] + +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "certifi" +version = "2024.7.4" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "cfgraph" +version = "0.2.1" +description = "rdflib collections flattening graph" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +rdflib = ">=0.4.2" + +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "main" +optional = false +python-versions = ">=3.7.0" + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" + +[[package]] +name = "curies" +version = "0.7.9" +description = "Idiomatic conversion between URIs and compact URIs (CURIEs)." +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +pydantic = "*" +pytrie = "*" +requests = "*" + +[package.extras] +docs = ["sphinx", "sphinx-rtd-theme", "sphinx-automodapi"] +fastapi = ["fastapi", "python-multipart", "httpx", "defusedxml", "uvicorn"] +flask = ["flask", "defusedxml"] +pandas = ["pandas"] +rdflib = ["rdflib"] +tests = ["pytest", "coverage"] + +[[package]] +name = "daff" +version = "1.3.46" +description = "Diff and patch tables" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["tox", "pytest", "pytest-cov", "bump2version (<1)", "sphinx (<2)"] + +[[package]] +name = "editorconfig" +version = "0.12.4" +description = "EditorConfig File Locator and Interpreter for Python" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "et-xmlfile" +version = "1.1.0" +description = "An implementation of lxml.xmlfile for the standard library" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "exceptiongroup" +version = "1.2.1" +description = "Backport of PEP 654 (exception groups)" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "fqdn" +version = "1.5.1" +description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" + +[[package]] +name = "ghp-import" +version = "2.1.0" +description = "Copy your docs directly to the gh-pages branch." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +python-dateutil = ">=2.8.1" + +[package.extras] +dev = ["twine", "markdown", "flake8", "wheel"] + +[[package]] +name = "google" +version = "3.0.0" +description = "Python bindings to the Google search engine." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +beautifulsoup4 = "*" + +[[package]] +name = "google-api-core" +version = "2.19.1" +description = "Google API client core library" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +google-auth = ">=2.14.1,<3.0.dev0" +googleapis-common-protos = ">=1.56.2,<2.0.dev0" +proto-plus = ">=1.22.3,<2.0.0dev" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" +requests = ">=2.18.0,<3.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.49.1,<2.0.dev0)"] +grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] + +[[package]] +name = "google-api-python-client" +version = "2.136.0" +description = "Google API Client Library for Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.0 || >2.3.0,<3.0.0.dev0" +google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" +google-auth-httplib2 = ">=0.2.0,<1.0.0" +httplib2 = ">=0.19.0,<1.dev0" +uritemplate = ">=3.0.1,<5" + +[[package]] +name = "google-auth" +version = "2.31.0" +description = "Google Authentication Library" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +cachetools = ">=2.0.0,<6.0" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] +enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] +pyopenssl = ["pyopenssl (>=20.0.0)", "cryptography (>=38.0.3)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] + +[[package]] +name = "google-auth-httplib2" +version = "0.2.0" +description = "Google Authentication Library: httplib2 transport" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +google-auth = "*" +httplib2 = ">=0.19.0" + +[[package]] +name = "google-auth-oauthlib" +version = "1.2.0" +description = "Google Authentication Library" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +google-auth = ">=2.15.0" +requests-oauthlib = ">=0.7.0" + +[package.extras] +tool = ["click (>=6.0.0)"] + +[[package]] +name = "googleapis-common-protos" +version = "1.63.2" +description = "Common protobufs used in Google APIs" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +protobuf = ">=3.20.2,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] + +[[package]] +name = "graphviz" +version = "0.20.3" +description = "Simple Python interface for Graphviz" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.extras] +dev = ["tox (>=3)", "flake8", "pep8-naming", "wheel", "twine"] +docs = ["sphinx (>=5,<7)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"] +test = ["pytest (>=7,<8.1)", "pytest-mock (>=3)", "pytest-cov", "coverage"] + +[[package]] +name = "greenlet" +version = "3.0.3" +description = "Lightweight in-process concurrent programming" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +docs = ["sphinx", "furo"] +test = ["objgraph", "psutil"] + +[[package]] +name = "gspread" +version = "6.1.2" +description = "Google Spreadsheets Python API" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +google-auth = ">=1.12.0" +google-auth-oauthlib = ">=0.4.1" + +[[package]] +name = "gspread-formatting" +version = "1.2.0" +description = "Complete Google Sheets formatting support for gspread worksheets" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +gspread = ">=3.0.0" + +[[package]] +name = "hbreader" +version = "0.9.1" +description = "Honey Badger reader - a generic file/url/string open and read tool" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "httplib2" +version = "0.22.0" +description = "A comprehensive HTTP client library." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "importlib-metadata" +version = "8.0.0" +description = "Read metadata from Python packages" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +doc = ["sphinx (>=3.5)", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"] +perf = ["ipython"] +test = ["pytest (>=6,<8.1.0 || >=8.2.0)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-mypy", "pytest-enabler (>=2.2)", "pytest-ruff (>=0.2.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "jaraco.test (>=5.4)", "importlib-resources (>=1.3)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "isodate" +version = "0.6.1" +description = "An ISO 8601 date/time/duration parser and formatter" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + +[[package]] +name = "isoduration" +version = "20.11.0" +description = "Operations with ISO 8601 durations" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +arrow = ">=0.15.0" + +[[package]] +name = "jinja2" +version = "3.1.4" +description = "A very fast and expressive template engine." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jsbeautifier" +version = "1.15.1" +description = "JavaScript unobfuscator and beautifier." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +editorconfig = ">=0.12.2" +six = ">=1.13.0" + +[[package]] +name = "json-flattener" +version = "0.1.9" +description = "Python library for denormalizing nested dicts or json objects to tables and back" +category = "main" +optional = false +python-versions = ">=3.7.0" + +[package.dependencies] +click = "*" +pyyaml = "*" + +[[package]] +name = "jsonasobj" +version = "2.0.1" +description = "JSON as python objects" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +hbreader = "*" + +[[package]] +name = "jsonasobj2" +version = "1.0.4" +description = "JSON as python objects - version 2" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +hbreader = "*" + +[[package]] +name = "jsonpatch" +version = "1.33" +description = "Apply JSON-Patches (RFC 6902)" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" + +[package.dependencies] +jsonpointer = ">=1.9" + +[[package]] +name = "jsonpath-ng" +version = "1.6.1" +description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +ply = "*" + +[[package]] +name = "jsonpointer" +version = "3.0.0" +description = "Identify specific nodes in a JSON document (RFC 6901)" +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "jsonschema" +version = "4.23.0" +description = "An implementation of JSON Schema validation for Python" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +attrs = ">=22.2.0" +fqdn = {version = "*", optional = true, markers = "extra == \"format\""} +idna = {version = "*", optional = true, markers = "extra == \"format\""} +isoduration = {version = "*", optional = true, markers = "extra == \"format\""} +jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format\""} +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format\""} +rfc3987 = {version = "*", optional = true, markers = "extra == \"format\""} +rpds-py = ">=0.7.1" +uri-template = {version = "*", optional = true, markers = "extra == \"format\""} +webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format\""} + +[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 (>=24.6.0)"] + +[[package]] +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "linkml" +version = "1.8.1" +description = "Linked Open Data Modeling Language" +category = "dev" +optional = false +python-versions = "<4.0.0,>=3.8.1" + +[package.dependencies] +antlr4-python3-runtime = ">=4.9.0,<4.10" +click = ">=7.0" +graphviz = ">=0.10.1" +hbreader = "*" +isodate = ">=0.6.0" +jinja2 = ">=3.1.0" +jsonasobj2 = ">=1.0.3,<2.0.0" +jsonschema = {version = ">=4.0.0", extras = ["format"]} +linkml-dataops = "*" +linkml-runtime = "1.8.0" +openpyxl = "*" +parse = "*" +prefixcommons = ">=0.1.7" +prefixmaps = ">=0.2.2" +pydantic = ">=1.0.0,<3.0.0" +pyjsg = ">=0.11.6" +pyshex = ">=0.7.20" +pyshexc = ">=0.8.3" +python-dateutil = "*" +pyyaml = "*" +rdflib = ">=6.0.0" +requests = ">=2.22" +sqlalchemy = ">=1.4.31" +watchdog = ">=0.9.0" + +[package.extras] +black = ["black (>=24.0.0)"] +tests = ["black (>=24.0.0)", "pyshacl (>=0.25.0,<0.26.0)"] +shacl = ["pyshacl (>=0.25.0,<0.26.0)"] + +[[package]] +name = "linkml-dataops" +version = "0.1.0" +description = "LinkML Data Operations API" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +jinja2 = "*" +jsonpatch = "*" +jsonpath-ng = "*" +linkml-runtime = ">=1.1.6" +"ruamel.yaml" = "*" + +[[package]] +name = "linkml-runtime" +version = "1.8.0" +description = "Runtime environment for LinkML, the Linked open data modeling language" +category = "main" +optional = false +python-versions = "<4.0,>=3.8" + +[package.dependencies] +click = "*" +curies = ">=0.5.4" +deprecated = "*" +hbreader = "*" +json-flattener = ">=0.1.9" +jsonasobj2 = ">=1.0.4,<2.dev0" +jsonschema = ">=3.2.0" +prefixcommons = ">=0.1.12" +prefixmaps = ">=0.1.4" +pydantic = ">=1.10.2,<3.0.0" +pyyaml = "*" +rdflib = ">=6.0.0" +requests = "*" + +[[package]] +name = "markdown" +version = "3.6" +description = "Python implementation of John Gruber's Markdown." +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["mkdocs (>=1.5)", "mkdocs-nature (>=0.6)", "mdx-gh-links (>=0.2)", "mkdocstrings", "mkdocs-gen-files", "mkdocs-section-index", "mkdocs-literate-nav"] +testing = ["coverage", "pyyaml"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +category = "dev" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "mergedeep" +version = "1.3.4" +description = "A deep merge function for ๐Ÿ." +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "mkdocs" +version = "1.6.0" +description = "Project documentation with Markdown." +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +ghp-import = ">=1.0" +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} +jinja2 = ">=2.11.1" +markdown = ">=3.3.6" +markupsafe = ">=2.0.1" +mergedeep = ">=1.3.4" +mkdocs-get-deps = ">=0.2.0" +packaging = ">=20.5" +pathspec = ">=0.11.1" +pyyaml = ">=5.1" +pyyaml-env-tag = ">=0.1" +watchdog = ">=2.0" + +[package.extras] +i18n = ["babel (>=2.9.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml-env-tag (==0.1)", "pyyaml (==5.1)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +mergedeep = ">=1.3.4" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" + +[[package]] +name = "mkdocs-material" +version = "8.5.11" +description = "Documentation that simply works" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +jinja2 = ">=3.0.2" +markdown = ">=3.2" +mkdocs = ">=1.4.0" +mkdocs-material-extensions = ">=1.1" +pygments = ">=2.12" +pymdown-extensions = ">=9.4" +requests = ">=2.26" + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +description = "Extension pack for Python Markdown and MkDocs Material." +category = "dev" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "mkdocs-mermaid2-plugin" +version = "1.1.1" +description = "A MkDocs plugin for including mermaid graphs in markdown sources" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +beautifulsoup4 = ">=4.6.3" +jsbeautifier = "*" +mkdocs = ">=1.0.4" +pymdown-extensions = ">=8.0" +requests = "*" + +[package.extras] +test = ["mkdocs-material"] + +[[package]] +name = "more-click" +version = "0.1.2" +description = "More click." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +click = "*" + +[package.extras] +tests = ["coverage", "pytest"] + +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + +[[package]] +name = "ontodev-cogs" +version = "0.3.3" +description = "COGS Operates Google Sheets" +category = "dev" +optional = false +python-versions = ">=3.6, <4" + +[package.dependencies] +daff = "*" +google = "*" +google-api-python-client = "*" +gspread = "*" +gspread-formatting = "*" +requests = "*" +tabulate = "*" +termcolor = "*" + +[[package]] +name = "openpyxl" +version = "3.1.5" +description = "A Python library to read/write Excel 2010 xlsx/xlsm files" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +et-xmlfile = "*" + +[[package]] +name = "packaging" +version = "24.1" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "parse" +version = "1.20.2" +description = "parse() is the opposite of format()" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "platformdirs" +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx (>=7.2.6)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest (>=7.4.3)"] +type = ["mypy (>=1.8)"] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "ply" +version = "3.11" +description = "Python Lex & Yacc" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "prefixcommons" +version = "0.1.12" +description = "A python API for working with ID prefixes" +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + +[package.dependencies] +click = ">=8.1.3,<9.0.0" +pytest-logging = ">=2015.11.4,<2016.0.0" +PyYAML = ">=6.0,<7.0" +requests = ">=2.28.1,<3.0.0" + +[[package]] +name = "prefixmaps" +version = "0.2.4" +description = "A python library for retrieving semantic prefix maps" +category = "main" +optional = false +python-versions = "<4.0,>=3.8" + +[package.dependencies] +curies = ">=0.5.3" +pyyaml = ">=5.3.1" + +[[package]] +name = "proto-plus" +version = "1.24.0" +description = "Beautiful, Pythonic protocol buffers." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +protobuf = ">=3.19.0,<6.0.0dev" + +[package.extras] +testing = ["google-api-core (>=1.31.5)"] + +[[package]] +name = "protobuf" +version = "5.27.2" +description = "" +category = "dev" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "pyasn1" +version = "0.6.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +category = "dev" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "pyasn1-modules" +version = "0.4.0" +description = "A collection of ASN.1-based protocols modules" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.7.0" + +[[package]] +name = "pydantic" +version = "2.8.2" +description = "Data validation using Python type hints" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.20.1" +typing-extensions = [ + {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, + {version = ">=4.6.1", markers = "python_version < \"3.13\""}, +] + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.20.1" +description = "Core functionality for Pydantic validation and serialization" +category = "main" +optional = false +python-versions = ">=3.8" + +[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." +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyjsg" +version = "0.11.10" +description = "Python JSON Schema Grammar interpreter" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +antlr4-python3-runtime = ">=4.9.3,<4.10.0" +jsonasobj = ">=1.2.1" + +[[package]] +name = "pymdown-extensions" +version = "10.8.1" +description = "Extension pack for Python Markdown." +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +markdown = ">=3.6" +pyyaml = "*" + +[package.extras] +extra = ["pygments (>=2.12)"] + +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" +optional = false +python-versions = ">=3.6.8" + +[package.extras] +diagrams = ["railroad-diagrams", "jinja2"] + +[[package]] +name = "pyshex" +version = "0.8.1" +description = "Python ShEx Implementation" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +cfgraph = ">=0.2.1" +chardet = "*" +pyshexc = "0.9.1" +rdflib-shim = "*" +requests = ">=2.22.0" +shexjsg = ">=0.8.2" +sparqlslurper = ">=0.5.1" +sparqlwrapper = ">=1.8.5" +urllib3 = "*" + +[[package]] +name = "pyshexc" +version = "0.9.1" +description = "PyShExC - Python ShEx compiler" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +antlr4-python3-runtime = ">=4.9.3,<4.10.0" +chardet = "*" +jsonasobj = ">=1.2.1" +pyjsg = ">=0.11.10" +rdflib-shim = "*" +shexjsg = ">=0.8.1" + +[[package]] +name = "pystow" +version = "0.5.4" +description = "Easily pick a place to store data for your python package." +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +click = "*" +requests = "*" +tqdm = "*" + +[package.extras] +aws = ["boto3"] +docs = ["sphinx", "sphinx-rtd-theme", "sphinx-click", "sphinx-autodoc-typehints", "sphinx-automodapi"] +pandas = ["pandas"] +rdf = ["rdflib"] +tests = ["coverage", "pytest", "requests-file"] +xml = ["lxml"] + +[[package]] +name = "pytest" +version = "8.2.2" +description = "pytest: simple powerful testing with Python" +category = "main" +optional = false +python-versions = ">=3.8" + +[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 = "pytest-logging" +version = "2015.11.4" +description = "Configures logging and allows tweaking the log level with a py.test flag" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pytest = ">=2.8.1" + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytrie" +version = "0.4.0" +description = "A pure Python implementation of the trie data structure." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +sortedcontainers = "*" + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +description = "A custom YAML tag for referencing environment variables in YAML files. " +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pyyaml = "*" + +[[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." +category = "main" +optional = false +python-versions = ">=3.8.1,<4.0.0" + +[package.dependencies] +isodate = ">=0.6.0,<0.7.0" +pyparsing = ">=2.1.0,<4" + +[package.extras] +berkeleydb = ["berkeleydb (>=18.1.0,<19.0.0)"] +networkx = ["networkx (>=2.0.0,<3.0.0)"] +html = ["html5lib (>=1.0,<2.0)"] +lxml = ["lxml (>=4.3.0,<5.0.0)"] + +[[package]] +name = "rdflib-jsonld" +version = "0.6.1" +description = "rdflib extension adding JSON-LD parser and serializer" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +rdflib = ">=5.0.0" + +[[package]] +name = "rdflib-shim" +version = "1.0.3" +description = "Shim for rdflib 5 and 6 incompatibilities" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +rdflib = ">=5.0.0" +rdflib-jsonld = "0.6.1" + +[[package]] +name = "referencing" +version = "0.35.1" +description = "JSON Referencing + Python" +category = "main" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +category = "main" +optional = false +python-versions = ">=3.8" + +[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 = "requests-oauthlib" +version = "2.0.0" +description = "OAuthlib authentication support for Requests." +category = "dev" +optional = false +python-versions = ">=3.4" + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +description = "A pure python RFC3339 validator" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + +[package.dependencies] +six = "*" + +[[package]] +name = "rfc3987" +version = "1.3.8" +description = "Parsing and validation of URIs (RFC 3986) and IRIs (RFC 3987)" +category = "dev" +optional = false +python-versions = "*" + +[[package]] +name = "rpds-py" +version = "0.19.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +category = "dev" +optional = false +python-versions = ">=3.6,<4" + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "ruamel.yaml" +version = "0.18.6" +description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""} + +[package.extras] +docs = ["ryd", "mercurial (>5.7)"] +jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] + +[[package]] +name = "ruamel.yaml.clib" +version = "0.2.8" +description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "schemasheets" +version = "0.1.24" +description = "Package to author schemas using spreadsheets" +category = "dev" +optional = false +python-versions = ">=3.9,<4.0" + +[package.dependencies] +bioregistry = ">0.5.0" +Jinja2 = ">=3.0.3" +linkml = ">=1.5.0" +linkml-runtime = ">=1.5.0" +ontodev-cogs = ">=0.3.3,<0.4.0" + +[[package]] +name = "shexjsg" +version = "0.8.2" +description = "ShExJSG - Astract Syntax Tree for the ShEx 2.0 language" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +pyjsg = ">=0.11.10" + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +category = "dev" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "sparqlslurper" +version = "0.5.1" +description = "SPARQL Slurper for rdflib" +category = "dev" +optional = false +python-versions = ">=3.7.4" + +[package.dependencies] +rdflib = ">=5.0.0" +rdflib-shim = "*" +sparqlwrapper = ">=1.8.2" + +[[package]] +name = "sparqlwrapper" +version = "2.0.0" +description = "SPARQL Endpoint interface to Python" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +rdflib = ">=6.1.1" + +[package.extras] +dev = ["setuptools (>=3.7.1)", "mypy (>=0.931)", "pandas (>=1.3.5)", "pandas-stubs (>=1.2.0.48)"] +docs = ["sphinx (<5)", "sphinx-rtd-theme"] +keepalive = ["keepalive (>=0.5)"] +pandas = ["pandas (>=1.3.5)"] + +[[package]] +name = "sqlalchemy" +version = "2.0.31" +description = "Database Abstraction Library" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} +typing-extensions = ">=4.6.0" + +[package.extras] +asyncio = ["greenlet (!=0.4.17)"] +mypy = ["mypy (>=0.910)"] +mssql = ["pyodbc"] +mssql-pymssql = ["pymssql"] +mssql-pyodbc = ["pyodbc"] +mysql = ["mysqlclient (>=1.4.0)"] +mysql-connector = ["mysql-connector-python"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] +oracle = ["cx_oracle (>=8)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] +postgresql-psycopg2binary = ["psycopg2-binary"] +postgresql-psycopg2cffi = ["psycopg2cffi"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] +aiomysql = ["greenlet (!=0.4.17)", "aiomysql (>=0.2.0)"] +aioodbc = ["greenlet (!=0.4.17)", "aioodbc"] +asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)"] +aiosqlite = ["greenlet (!=0.4.17)", "aiosqlite", "typing_extensions (!=3.10.0.1)"] +sqlcipher = ["sqlcipher3-binary"] + +[[package]] +name = "tabulate" +version = "0.9.0" +description = "Pretty-print tabular data" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +widechars = ["wcwidth"] + +[[package]] +name = "termcolor" +version = "2.4.0" +description = "ANSI color formatting for output in terminal" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.extras] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "main" +optional = false +python-versions = ">=3.7" + +[[package]] +name = "tqdm" +version = "4.66.4" +description = "Fast, Extensible Progress Meter" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20240316" +description = "Typing stubs for python-dateutil" +category = "dev" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "typing-extensions" +version = "4.12.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" +optional = false +python-versions = ">=3.8" + +[[package]] +name = "uri-template" +version = "1.3.0" +description = "RFC 6570 URI Template Processor" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +dev = ["types-pyyaml", "mypy", "flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "pep8-naming"] + +[[package]] +name = "uritemplate" +version = "4.1.1" +description = "Implementation of RFC 6570 URI Templates" +category = "dev" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "urllib3" +version = "2.2.2" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=3.8" + +[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 = "watchdog" +version = "4.0.1" +description = "Filesystem events monitoring" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + +[[package]] +name = "webcolors" +version = "24.6.0" +description = "A library for working with the color formats defined by HTML and CSS." +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.extras] +docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] +tests = ["coverage"] + +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +category = "main" +optional = false +python-versions = ">=3.6" + +[[package]] +name = "zipp" +version = "3.19.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.extras] +doc = ["sphinx (>=3.5)", "jaraco.packaging (>=9.3)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"] +test = ["pytest (>=6,<8.1.0 || >=8.2.0)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-mypy", "pytest-enabler (>=2.2)", "pytest-ruff (>=0.2.1)", "jaraco.itertools", "jaraco.functools", "more-itertools", "big-o", "pytest-ignore-flaky", "jaraco.test", "importlib-resources"] + +[extras] +docs = [] + +[metadata] +lock-version = "1.1" +python-versions = "^3.9" +content-hash = "81d3ac12af995549849efe0f958f92e7d52bf30f96791b6f84e539b533901b08" + +[metadata.files] +annotated-types = [] +antlr4-python3-runtime = [] +arrow = [] +attrs = [] +beautifulsoup4 = [] +bioregistry = [] +cachetools = [] +certifi = [] +cfgraph = [] +chardet = [] +charset-normalizer = [] +click = [] +colorama = [] +curies = [] +daff = [] +deprecated = [] +editorconfig = [] +et-xmlfile = [] +exceptiongroup = [] +fqdn = [] +ghp-import = [] +google = [] +google-api-core = [] +google-api-python-client = [] +google-auth = [] +google-auth-httplib2 = [] +google-auth-oauthlib = [] +googleapis-common-protos = [] +graphviz = [] +greenlet = [] +gspread = [] +gspread-formatting = [] +hbreader = [] +httplib2 = [] +idna = [] +importlib-metadata = [] +iniconfig = [] +isodate = [] +isoduration = [] +jinja2 = [] +jsbeautifier = [] +json-flattener = [] +jsonasobj = [] +jsonasobj2 = [] +jsonpatch = [] +jsonpath-ng = [] +jsonpointer = [] +jsonschema = [] +jsonschema-specifications = [] +linkml = [] +linkml-dataops = [] +linkml-runtime = [] +markdown = [] +markupsafe = [] +mergedeep = [] +mkdocs = [] +mkdocs-get-deps = [] +mkdocs-material = [] +mkdocs-material-extensions = [] +mkdocs-mermaid2-plugin = [] +more-click = [] +oauthlib = [] +ontodev-cogs = [] +openpyxl = [] +packaging = [] +parse = [] +pathspec = [] +platformdirs = [] +pluggy = [] +ply = [] +prefixcommons = [] +prefixmaps = [] +proto-plus = [] +protobuf = [] +pyasn1 = [] +pyasn1-modules = [] +pydantic = [] +pydantic-core = [] +pygments = [] +pyjsg = [] +pymdown-extensions = [] +pyparsing = [] +pyshex = [] +pyshexc = [] +pystow = [] +pytest = [] +pytest-logging = [] +python-dateutil = [] +pytrie = [] +pyyaml = [] +pyyaml-env-tag = [] +rdflib = [] +rdflib-jsonld = [] +rdflib-shim = [] +referencing = [] +requests = [] +requests-oauthlib = [] +rfc3339-validator = [] +rfc3987 = [] +rpds-py = [] +rsa = [] +"ruamel.yaml" = [] +"ruamel.yaml.clib" = [] +schemasheets = [] +shexjsg = [] +six = [] +sortedcontainers = [] +soupsieve = [] +sparqlslurper = [] +sparqlwrapper = [] +sqlalchemy = [] +tabulate = [] +termcolor = [] +tomli = [] +tqdm = [] +types-python-dateutil = [] +typing-extensions = [] +uri-template = [] +uritemplate = [] +urllib3 = [] +watchdog = [] +webcolors = [] +wrapt = [] +zipp = [] diff --git a/project.Makefile b/project.Makefile new file mode 100644 index 0000000..0dd0fa0 --- /dev/null +++ b/project.Makefile @@ -0,0 +1 @@ +## Add your own custom Makefile targets here diff --git a/project/excel/linkml_tutorial_2024.xlsx b/project/excel/linkml_tutorial_2024.xlsx new file mode 100644 index 0000000..e2f52ca Binary files /dev/null and b/project/excel/linkml_tutorial_2024.xlsx differ diff --git a/project/graphql/linkml_tutorial_2024.graphql b/project/graphql/linkml_tutorial_2024.graphql new file mode 100644 index 0000000..819dd17 --- /dev/null +++ b/project/graphql/linkml_tutorial_2024.graphql @@ -0,0 +1,24 @@ +# metamodel_version: 1.7.0 +type NamedThing + { + id: Uriorcurie! + name: String + description: String + } + +type Person + { + id: Uriorcurie! + name: String + description: String + primaryEmail: String + birthDate: Date + ageInYears: Integer + vitalStatus: PersonStatus + } + +type PersonCollection + { + entries: [Person] + } + diff --git a/project/jsonld/linkml_tutorial_2024.context.jsonld b/project/jsonld/linkml_tutorial_2024.context.jsonld new file mode 100644 index 0000000..6dc3dbe --- /dev/null +++ b/project/jsonld/linkml_tutorial_2024.context.jsonld @@ -0,0 +1,60 @@ +{ + "comments": { + "description": "Auto generated by LinkML jsonld context generator", + "generation_date": "2024-07-08T14:51:23", + "source": "linkml_tutorial_2024.yaml" + }, + "@context": { + "PATO": { + "@id": "http://purl.obolibrary.org/obo/PATO_", + "@prefix": true + }, + "biolink": "https://w3id.org/biolink/", + "example": "https://example.org/", + "linkml": "https://w3id.org/linkml/", + "linkml_tutorial_2024": "https://w3id.org/my-org/linkml-tutorial-2024/", + "schema": "http://schema.org/", + "skos": "http://www.w3.org/2004/02/skos/core#", + "@vocab": "https://w3id.org/my-org/linkml-tutorial-2024/", + "age_in_years": { + "@type": "xsd:integer", + "@id": "age_in_years" + }, + "birth_date": { + "@type": "xsd:date", + "@id": "schema:birthDate" + }, + "description": { + "@id": "schema:description" + }, + "id": "@id", + "name": { + "@id": "schema:name" + }, + "entries": { + "@type": "@id", + "@id": "entries" + }, + "primary_email": { + "@id": "schema:email" + }, + "vital_status": { + "@context": { + "@vocab": "@null", + "text": "skos:notation", + "description": "skos:prefLabel", + "meaning": "@id" + }, + "@id": "vital_status" + }, + "NamedThing": { + "@id": "schema:Thing" + }, + "Person": { + "@id": "Person" + }, + "PersonCollection": { + "@id": "PersonCollection" + } + } +} diff --git a/project/jsonld/linkml_tutorial_2024.jsonld b/project/jsonld/linkml_tutorial_2024.jsonld new file mode 100644 index 0000000..3172969 --- /dev/null +++ b/project/jsonld/linkml_tutorial_2024.jsonld @@ -0,0 +1,596 @@ +{ + "name": "linkml-tutorial-2024", + "description": "This is the project description.", + "title": "linkml-tutorial-2024", + "see_also": [ + "https://my-org.github.io/linkml-tutorial-2024" + ], + "id": "https://w3id.org/my-org/linkml-tutorial-2024", + "imports": [ + "linkml:types" + ], + "license": "Apache Software License 2.0", + "prefixes": [ + { + "prefix_prefix": "linkml_tutorial_2024", + "prefix_reference": "https://w3id.org/my-org/linkml-tutorial-2024/" + }, + { + "prefix_prefix": "linkml", + "prefix_reference": "https://w3id.org/linkml/" + }, + { + "prefix_prefix": "biolink", + "prefix_reference": "https://w3id.org/biolink/" + }, + { + "prefix_prefix": "schema", + "prefix_reference": "http://schema.org/" + }, + { + "prefix_prefix": "PATO", + "prefix_reference": "http://purl.obolibrary.org/obo/PATO_" + }, + { + "prefix_prefix": "example", + "prefix_reference": "https://example.org/" + } + ], + "default_prefix": "linkml_tutorial_2024", + "default_range": "string", + "types": [ + { + "name": "string", + "definition_uri": "https://w3id.org/linkml/String", + "description": "A character string", + "notes": [ + "In RDF serializations, a slot with range of string is treated as a literal or type xsd:string. If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"string\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "exact_mappings": [ + "schema:Text" + ], + "base": "str", + "uri": "http://www.w3.org/2001/XMLSchema#string", + "@type": "TypeDefinition" + }, + { + "name": "integer", + "definition_uri": "https://w3id.org/linkml/Integer", + "description": "An integer", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"integer\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "exact_mappings": [ + "schema:Integer" + ], + "base": "int", + "uri": "http://www.w3.org/2001/XMLSchema#integer", + "@type": "TypeDefinition" + }, + { + "name": "boolean", + "definition_uri": "https://w3id.org/linkml/Boolean", + "description": "A binary (true or false) value", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"boolean\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "exact_mappings": [ + "schema:Boolean" + ], + "base": "Bool", + "uri": "http://www.w3.org/2001/XMLSchema#boolean", + "repr": "bool", + "@type": "TypeDefinition" + }, + { + "name": "float", + "definition_uri": "https://w3id.org/linkml/Float", + "description": "A real number that conforms to the xsd:float specification", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"float\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "exact_mappings": [ + "schema:Float" + ], + "base": "float", + "uri": "http://www.w3.org/2001/XMLSchema#float", + "@type": "TypeDefinition" + }, + { + "name": "double", + "definition_uri": "https://w3id.org/linkml/Double", + "description": "A real number that conforms to the xsd:double specification", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"double\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "close_mappings": [ + "schema:Float" + ], + "base": "float", + "uri": "http://www.w3.org/2001/XMLSchema#double", + "@type": "TypeDefinition" + }, + { + "name": "decimal", + "definition_uri": "https://w3id.org/linkml/Decimal", + "description": "A real number with arbitrary precision that conforms to the xsd:decimal specification", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"decimal\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "broad_mappings": [ + "schema:Number" + ], + "base": "Decimal", + "uri": "http://www.w3.org/2001/XMLSchema#decimal", + "@type": "TypeDefinition" + }, + { + "name": "time", + "definition_uri": "https://w3id.org/linkml/Time", + "description": "A time object represents a (local) time of day, independent of any particular day", + "notes": [ + "URI is dateTime because OWL reasoners do not work with straight date or time", + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"time\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "exact_mappings": [ + "schema:Time" + ], + "base": "XSDTime", + "uri": "http://www.w3.org/2001/XMLSchema#time", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "date", + "definition_uri": "https://w3id.org/linkml/Date", + "description": "a date (year, month and day) in an idealized calendar", + "notes": [ + "URI is dateTime because OWL reasoners don't work with straight date or time", + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"date\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "exact_mappings": [ + "schema:Date" + ], + "base": "XSDDate", + "uri": "http://www.w3.org/2001/XMLSchema#date", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "datetime", + "definition_uri": "https://w3id.org/linkml/Datetime", + "description": "The combination of a date and time", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"datetime\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "exact_mappings": [ + "schema:DateTime" + ], + "base": "XSDDateTime", + "uri": "http://www.w3.org/2001/XMLSchema#dateTime", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "date_or_datetime", + "definition_uri": "https://w3id.org/linkml/DateOrDatetime", + "description": "Either a date or a datetime", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"date_or_datetime\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "str", + "uri": "https://w3id.org/linkml/DateOrDatetime", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "uriorcurie", + "definition_uri": "https://w3id.org/linkml/Uriorcurie", + "description": "a URI or a CURIE", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"uriorcurie\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "URIorCURIE", + "uri": "http://www.w3.org/2001/XMLSchema#anyURI", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "curie", + "definition_uri": "https://w3id.org/linkml/Curie", + "conforms_to": "https://www.w3.org/TR/curie/", + "description": "a compact URI", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"curie\"." + ], + "comments": [ + "in RDF serializations this MUST be expanded to a URI", + "in non-RDF serializations MAY be serialized as the compact representation" + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "Curie", + "uri": "http://www.w3.org/2001/XMLSchema#string", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "uri", + "definition_uri": "https://w3id.org/linkml/Uri", + "conforms_to": "https://www.ietf.org/rfc/rfc3987.txt", + "description": "a complete URI", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"uri\"." + ], + "comments": [ + "in RDF serializations a slot with range of uri is treated as a literal or type xsd:anyURI unless it is an identifier or a reference to an identifier, in which case it is translated directly to a node" + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "close_mappings": [ + "schema:URL" + ], + "base": "URI", + "uri": "http://www.w3.org/2001/XMLSchema#anyURI", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "ncname", + "definition_uri": "https://w3id.org/linkml/Ncname", + "description": "Prefix part of CURIE", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"ncname\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "NCName", + "uri": "http://www.w3.org/2001/XMLSchema#string", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "objectidentifier", + "definition_uri": "https://w3id.org/linkml/Objectidentifier", + "description": "A URI or CURIE that represents an object in the model.", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"objectidentifier\"." + ], + "comments": [ + "Used for inheritance and type checking" + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "ElementIdentifier", + "uri": "http://www.w3.org/ns/shex#iri", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "nodeidentifier", + "definition_uri": "https://w3id.org/linkml/Nodeidentifier", + "description": "A URI, CURIE or BNODE that represents a node in a model.", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"nodeidentifier\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "NodeIdentifier", + "uri": "http://www.w3.org/ns/shex#nonLiteral", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "jsonpointer", + "definition_uri": "https://w3id.org/linkml/Jsonpointer", + "conforms_to": "https://datatracker.ietf.org/doc/html/rfc6901", + "description": "A string encoding a JSON Pointer. The value of the string MUST conform to JSON Point syntax and SHOULD dereference to a valid object within the current instance document when encoded in tree form.", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"jsonpointer\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "str", + "uri": "http://www.w3.org/2001/XMLSchema#string", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "jsonpath", + "definition_uri": "https://w3id.org/linkml/Jsonpath", + "conforms_to": "https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html", + "description": "A string encoding a JSON Path. The value of the string MUST conform to JSON Point syntax and SHOULD dereference to zero or more valid objects within the current instance document when encoded in tree form.", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"jsonpath\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "str", + "uri": "http://www.w3.org/2001/XMLSchema#string", + "repr": "str", + "@type": "TypeDefinition" + }, + { + "name": "sparqlpath", + "definition_uri": "https://w3id.org/linkml/Sparqlpath", + "conforms_to": "https://www.w3.org/TR/sparql11-query/#propertypaths", + "description": "A string encoding a SPARQL Property Path. The value of the string MUST conform to SPARQL syntax and SHOULD dereference to zero or more valid objects within the current instance document when encoded as RDF.", + "notes": [ + "If you are authoring schemas in LinkML YAML, the type is referenced with the lower case \"sparqlpath\"." + ], + "from_schema": "https://w3id.org/linkml/types", + "imported_from": "linkml:types", + "base": "str", + "uri": "http://www.w3.org/2001/XMLSchema#string", + "repr": "str", + "@type": "TypeDefinition" + } + ], + "enums": [ + { + "name": "PersonStatus", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/PersonStatus", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "permissible_values": [ + { + "text": "ALIVE", + "description": "the person is living", + "meaning": "PATO:0001421" + }, + { + "text": "DEAD", + "description": "the person is deceased", + "meaning": "PATO:0001422" + }, + { + "text": "UNKNOWN", + "description": "the vital status is not known", + "todos": [ + "map this to an ontology" + ] + } + ] + } + ], + "slots": [ + { + "name": "id", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/id", + "description": "A unique identifier for a thing", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "mappings": [ + "http://schema.org/identifier" + ], + "slot_uri": "http://schema.org/identifier", + "identifier": true, + "owner": "NamedThing", + "domain_of": [ + "NamedThing" + ], + "range": "uriorcurie", + "required": true, + "@type": "SlotDefinition" + }, + { + "name": "name", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/name", + "description": "A human-readable name for a thing", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "mappings": [ + "http://schema.org/name" + ], + "slot_uri": "http://schema.org/name", + "owner": "NamedThing", + "domain_of": [ + "NamedThing" + ], + "range": "string", + "@type": "SlotDefinition" + }, + { + "name": "description", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/description", + "description": "A human-readable description for a thing", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "mappings": [ + "http://schema.org/description" + ], + "slot_uri": "http://schema.org/description", + "owner": "NamedThing", + "domain_of": [ + "NamedThing" + ], + "range": "string", + "@type": "SlotDefinition" + }, + { + "name": "primary_email", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/primary_email", + "description": "The main email address of a person", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "mappings": [ + "http://schema.org/email" + ], + "slot_uri": "http://schema.org/email", + "owner": "Person", + "domain_of": [ + "Person" + ], + "range": "string", + "@type": "SlotDefinition" + }, + { + "name": "birth_date", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/birth_date", + "description": "Date on which a person is born", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "mappings": [ + "http://schema.org/birthDate" + ], + "slot_uri": "http://schema.org/birthDate", + "owner": "Person", + "domain_of": [ + "Person" + ], + "range": "date", + "@type": "SlotDefinition" + }, + { + "name": "age_in_years", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/age_in_years", + "description": "Number of years since birth", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "slot_uri": "https://w3id.org/my-org/linkml-tutorial-2024/age_in_years", + "owner": "Person", + "domain_of": [ + "Person" + ], + "range": "integer", + "@type": "SlotDefinition" + }, + { + "name": "vital_status", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/vital_status", + "description": "living or dead status", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "slot_uri": "https://w3id.org/my-org/linkml-tutorial-2024/vital_status", + "owner": "Person", + "domain_of": [ + "Person" + ], + "range": "PersonStatus", + "@type": "SlotDefinition" + }, + { + "name": "personCollection__entries", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "slot_uri": "https://w3id.org/my-org/linkml-tutorial-2024/entries", + "alias": "entries", + "owner": "PersonCollection", + "domain_of": [ + "PersonCollection" + ], + "range": "Person", + "multivalued": true, + "inlined": true, + "@type": "SlotDefinition" + }, + { + "name": "Person_primary_email", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/primary_email", + "description": "The main email address of a person", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "mappings": [ + "http://schema.org/email" + ], + "is_a": "primary_email", + "domain": "Person", + "slot_uri": "http://schema.org/email", + "alias": "primary_email", + "owner": "Person", + "domain_of": [ + "Person" + ], + "is_usage_slot": true, + "usage_slot_name": "primary_email", + "range": "string", + "pattern": "^\\S+@[\\S+\\.]+\\S+", + "@type": "SlotDefinition" + } + ], + "classes": [ + { + "name": "NamedThing", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/NamedThing", + "description": "A generic grouping for any identifiable entity", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "mappings": [ + "schema:Thing" + ], + "slots": [ + "id", + "name", + "description" + ], + "slot_usage": {}, + "class_uri": "http://schema.org/Thing", + "@type": "ClassDefinition" + }, + { + "name": "Person", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/Person", + "description": "Represents a Person", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "is_a": "NamedThing", + "slots": [ + "id", + "name", + "description", + "Person_primary_email", + "birth_date", + "age_in_years", + "vital_status" + ], + "slot_usage": {}, + "class_uri": "https://w3id.org/my-org/linkml-tutorial-2024/Person", + "@type": "ClassDefinition" + }, + { + "name": "PersonCollection", + "definition_uri": "https://w3id.org/my-org/linkml-tutorial-2024/PersonCollection", + "description": "A holder for Person objects", + "from_schema": "https://w3id.org/my-org/linkml-tutorial-2024", + "slots": [ + "personCollection__entries" + ], + "slot_usage": {}, + "attributes": [ + { + "name": "entries", + "range": "Person", + "multivalued": true, + "inlined": true, + "@type": "SlotDefinition" + } + ], + "class_uri": "https://w3id.org/my-org/linkml-tutorial-2024/PersonCollection", + "tree_root": true, + "@type": "ClassDefinition" + } + ], + "metamodel_version": "1.7.0", + "source_file": "linkml_tutorial_2024.yaml", + "source_file_date": "2024-07-08T14:49:59", + "source_file_size": 2256, + "generation_date": "2024-07-08T14:51:23", + "@type": "SchemaDefinition", + "@context": [ + "project/jsonld/linkml_tutorial_2024.context.jsonld", + "https://w3id.org/linkml/types.context.jsonld", + { + "@base": "https://w3id.org/my-org/linkml-tutorial-2024/" + } + ] +} diff --git a/project/jsonschema/linkml_tutorial_2024.schema.json b/project/jsonschema/linkml_tutorial_2024.schema.json new file mode 100644 index 0000000..8a3ea15 --- /dev/null +++ b/project/jsonschema/linkml_tutorial_2024.schema.json @@ -0,0 +1,161 @@ +{ + "$defs": { + "NamedThing": { + "additionalProperties": false, + "description": "A generic grouping for any identifiable entity", + "properties": { + "description": { + "description": "A human-readable description for a thing", + "type": "string" + }, + "id": { + "description": "A unique identifier for a thing", + "type": "string" + }, + "name": { + "description": "A human-readable name for a thing", + "type": "string" + } + }, + "required": [ + "id" + ], + "title": "NamedThing", + "type": "object" + }, + "Person": { + "additionalProperties": false, + "description": "Represents a Person", + "properties": { + "age_in_years": { + "description": "Number of years since birth", + "type": "integer" + }, + "birth_date": { + "description": "Date on which a person is born", + "format": "date", + "type": "string" + }, + "description": { + "description": "A human-readable description for a thing", + "type": "string" + }, + "id": { + "description": "A unique identifier for a thing", + "type": "string" + }, + "name": { + "description": "A human-readable name for a thing", + "type": "string" + }, + "primary_email": { + "description": "The main email address of a person", + "pattern": "^\\S+@[\\S+\\.]+\\S+", + "type": "string" + }, + "vital_status": { + "$ref": "#/$defs/PersonStatus", + "description": "living or dead status" + } + }, + "required": [ + "id" + ], + "title": "Person", + "type": "object" + }, + "PersonCollection": { + "additionalProperties": false, + "description": "A holder for Person objects", + "properties": { + "entries": { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/$defs/Person__identifier_optional" + }, + { + "type": "null" + } + ] + }, + "type": "object" + } + }, + "title": "PersonCollection", + "type": "object" + }, + "PersonStatus": { + "description": "", + "enum": [ + "ALIVE", + "DEAD", + "UNKNOWN" + ], + "title": "PersonStatus", + "type": "string" + }, + "Person__identifier_optional": { + "additionalProperties": false, + "description": "Represents a Person", + "properties": { + "age_in_years": { + "description": "Number of years since birth", + "type": "integer" + }, + "birth_date": { + "description": "Date on which a person is born", + "format": "date", + "type": "string" + }, + "description": { + "description": "A human-readable description for a thing", + "type": "string" + }, + "id": { + "description": "A unique identifier for a thing", + "type": "string" + }, + "name": { + "description": "A human-readable name for a thing", + "type": "string" + }, + "primary_email": { + "description": "The main email address of a person", + "pattern": "^\\S+@[\\S+\\.]+\\S+", + "type": "string" + }, + "vital_status": { + "$ref": "#/$defs/PersonStatus", + "description": "living or dead status" + } + }, + "required": [], + "title": "Person", + "type": "object" + } + }, + "$id": "https://w3id.org/my-org/linkml-tutorial-2024", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "additionalProperties": true, + "description": "A holder for Person objects", + "metamodel_version": "1.7.0", + "properties": { + "entries": { + "additionalProperties": { + "anyOf": [ + { + "$ref": "#/$defs/Person__identifier_optional" + }, + { + "type": "null" + } + ] + }, + "type": "object" + } + }, + "title": "linkml-tutorial-2024", + "type": "object", + "version": null +} \ No newline at end of file diff --git a/project/owl/linkml_tutorial_2024.owl.ttl b/project/owl/linkml_tutorial_2024.owl.ttl new file mode 100644 index 0000000..ff1605c --- /dev/null +++ b/project/owl/linkml_tutorial_2024.owl.ttl @@ -0,0 +1,182 @@ +@prefix PATO: . +@prefix dcterms: . +@prefix linkml: . +@prefix linkml_tutorial_2024: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix schema1: . +@prefix skos: . +@prefix xsd: . + +linkml_tutorial_2024:PersonCollection a owl:Class, + linkml:ClassDefinition ; + rdfs:label "PersonCollection" ; + rdfs:subClassOf [ a owl:Restriction ; + owl:minCardinality 0 ; + owl:onProperty linkml_tutorial_2024:entries ], + [ a owl:Restriction ; + owl:allValuesFrom linkml_tutorial_2024:Person ; + owl:onProperty linkml_tutorial_2024:entries ] ; + skos:definition "A holder for Person objects" ; + skos:inScheme . + +linkml_tutorial_2024:NamedThing a owl:Class, + linkml:ClassDefinition ; + rdfs:label "NamedThing" ; + rdfs:subClassOf [ a owl:Restriction ; + owl:allValuesFrom linkml:String ; + owl:onProperty linkml_tutorial_2024:description ], + [ a owl:Restriction ; + owl:minCardinality 0 ; + owl:onProperty linkml_tutorial_2024:name ], + [ a owl:Restriction ; + owl:minCardinality 1 ; + owl:onProperty linkml_tutorial_2024:id ], + [ a owl:Restriction ; + owl:minCardinality 0 ; + owl:onProperty linkml_tutorial_2024:description ], + [ a owl:Restriction ; + owl:allValuesFrom linkml:Uriorcurie ; + owl:onProperty linkml_tutorial_2024:id ], + [ a owl:Restriction ; + owl:maxCardinality 1 ; + owl:onProperty linkml_tutorial_2024:description ], + [ a owl:Restriction ; + owl:maxCardinality 1 ; + owl:onProperty linkml_tutorial_2024:id ], + [ a owl:Restriction ; + owl:maxCardinality 1 ; + owl:onProperty linkml_tutorial_2024:name ], + [ a owl:Restriction ; + owl:allValuesFrom linkml:String ; + owl:onProperty linkml_tutorial_2024:name ] ; + skos:definition "A generic grouping for any identifiable entity" ; + skos:exactMatch schema1:Thing ; + skos:inScheme . + +linkml_tutorial_2024:Person a owl:Class, + linkml:ClassDefinition ; + rdfs:label "Person" ; + rdfs:subClassOf [ a owl:Restriction ; + owl:minCardinality 0 ; + owl:onProperty linkml_tutorial_2024:vital_status ], + [ a owl:Restriction ; + owl:minCardinality 0 ; + owl:onProperty linkml_tutorial_2024:age_in_years ], + [ a owl:Restriction ; + owl:minCardinality 0 ; + owl:onProperty linkml_tutorial_2024:primary_email ], + [ a owl:Restriction ; + owl:allValuesFrom linkml_tutorial_2024:PersonStatus ; + owl:onProperty linkml_tutorial_2024:vital_status ], + [ a owl:Restriction ; + owl:maxCardinality 1 ; + owl:onProperty linkml_tutorial_2024:age_in_years ], + [ a owl:Restriction ; + owl:maxCardinality 1 ; + owl:onProperty linkml_tutorial_2024:birth_date ], + [ a owl:Restriction ; + owl:allValuesFrom linkml:Integer ; + owl:onProperty linkml_tutorial_2024:age_in_years ], + [ a owl:Restriction ; + owl:allValuesFrom linkml:Date ; + owl:onProperty linkml_tutorial_2024:birth_date ], + [ a owl:Restriction ; + owl:maxCardinality 1 ; + owl:onProperty linkml_tutorial_2024:primary_email ], + [ a owl:Restriction ; + owl:minCardinality 0 ; + owl:onProperty linkml_tutorial_2024:birth_date ], + [ a owl:Restriction ; + owl:maxCardinality 1 ; + owl:onProperty linkml_tutorial_2024:vital_status ], + [ a owl:Restriction ; + owl:allValuesFrom [ a rdfs:Datatype ; + owl:onDatatype xsd:string ; + owl:withRestrictions ( [ xsd:pattern "^\\S+@[\\S+\\.]+\\S+" ] ) ] ; + owl:onProperty linkml_tutorial_2024:primary_email ], + linkml_tutorial_2024:NamedThing ; + skos:definition "Represents a Person" ; + skos:inScheme . + +PATO:0001421 a owl:Class, + linkml_tutorial_2024:PersonStatus ; + rdfs:label "ALIVE" ; + rdfs:subClassOf linkml_tutorial_2024:PersonStatus . + +PATO:0001422 a owl:Class, + linkml_tutorial_2024:PersonStatus ; + rdfs:label "DEAD" ; + rdfs:subClassOf linkml_tutorial_2024:PersonStatus . + + a owl:Class, + linkml_tutorial_2024:PersonStatus ; + rdfs:label "UNKNOWN" ; + rdfs:subClassOf linkml_tutorial_2024:PersonStatus . + +linkml_tutorial_2024:entries a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "entries" ; + skos:inScheme . + +linkml_tutorial_2024:age_in_years a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "age_in_years" ; + rdfs:range linkml:Integer ; + skos:definition "Number of years since birth" ; + skos:inScheme . + +linkml_tutorial_2024:birth_date a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "birth_date" ; + rdfs:range linkml:Date ; + skos:definition "Date on which a person is born" ; + skos:inScheme . + +linkml_tutorial_2024:description a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "description" ; + skos:definition "A human-readable description for a thing" ; + skos:inScheme . + +linkml_tutorial_2024:id a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "id" ; + rdfs:range linkml:Uriorcurie ; + skos:definition "A unique identifier for a thing" ; + skos:inScheme . + +linkml_tutorial_2024:name a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "name" ; + skos:definition "A human-readable name for a thing" ; + skos:inScheme . + +linkml_tutorial_2024:primary_email a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "primary_email" ; + skos:definition "The main email address of a person" ; + skos:inScheme . + +linkml_tutorial_2024:vital_status a owl:ObjectProperty, + linkml:SlotDefinition ; + rdfs:label "vital_status" ; + rdfs:range linkml_tutorial_2024:PersonStatus ; + skos:definition "living or dead status" ; + skos:inScheme . + +linkml_tutorial_2024:PersonStatus a owl:Class, + linkml:EnumDefinition ; + owl:unionOf ( PATO:0001421 PATO:0001422 ) ; + linkml:permissible_values PATO:0001421, + PATO:0001422, + . + + a owl:Ontology ; + rdfs:label "linkml-tutorial-2024" ; + dcterms:license "Apache Software License 2.0" ; + dcterms:title "linkml-tutorial-2024" ; + rdfs:seeAlso ; + skos:definition "This is the project description." . + diff --git a/project/prefixmap/linkml_tutorial_2024.yaml b/project/prefixmap/linkml_tutorial_2024.yaml new file mode 100644 index 0000000..8830e6c --- /dev/null +++ b/project/prefixmap/linkml_tutorial_2024.yaml @@ -0,0 +1,11 @@ +{ + "PATO": "http://purl.obolibrary.org/obo/PATO_", + "biolink": "https://w3id.org/biolink/", + "example": "https://example.org/", + "linkml": "https://w3id.org/linkml/", + "linkml_tutorial_2024": "https://w3id.org/my-org/linkml-tutorial-2024/", + "schema": "http://schema.org/", + "NamedThing": { + "@id": "schema:Thing" + } +} \ No newline at end of file diff --git a/project/protobuf/linkml_tutorial_2024.proto b/project/protobuf/linkml_tutorial_2024.proto new file mode 100644 index 0000000..b33b0d5 --- /dev/null +++ b/project/protobuf/linkml_tutorial_2024.proto @@ -0,0 +1,26 @@ + syntax="proto3"; + package +// metamodel_version: 1.7.0 +// A generic grouping for any identifiable entity +message NamedThing + { + uriorcurie id = 0 + string name = 0 + string description = 0 + } +// Represents a Person +message Person + { + uriorcurie id = 0 + string name = 0 + string description = 0 + string primaryEmail = 0 + date birthDate = 0 + integer ageInYears = 0 + personStatus vitalStatus = 0 + } +// A holder for Person objects +message PersonCollection + { + repeated person entries = 0 + } diff --git a/project/shacl/linkml_tutorial_2024.shacl.ttl b/project/shacl/linkml_tutorial_2024.shacl.ttl new file mode 100644 index 0000000..6a7070a --- /dev/null +++ b/project/shacl/linkml_tutorial_2024.shacl.ttl @@ -0,0 +1,90 @@ +@prefix PATO: . +@prefix linkml_tutorial_2024: . +@prefix rdf: . +@prefix schema1: . +@prefix sh: . +@prefix xsd: . + +schema1:Thing a sh:NodeShape ; + sh:closed true ; + sh:description "A generic grouping for any identifiable entity" ; + sh:ignoredProperties ( rdf:type ) ; + sh:property [ sh:datatype xsd:anyURI ; + sh:description "A unique identifier for a thing" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 0 ; + sh:path schema1:identifier ], + [ sh:datatype xsd:string ; + sh:description "A human-readable description for a thing" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 2 ; + sh:path schema1:description ], + [ sh:datatype xsd:string ; + sh:description "A human-readable name for a thing" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 1 ; + sh:path schema1:name ] ; + sh:targetClass schema1:Thing . + +linkml_tutorial_2024:PersonCollection a sh:NodeShape ; + sh:closed true ; + sh:description "A holder for Person objects" ; + sh:ignoredProperties ( rdf:type ) ; + sh:property [ sh:class linkml_tutorial_2024:Person ; + sh:nodeKind sh:IRI ; + sh:order 0 ; + sh:path linkml_tutorial_2024:entries ] ; + sh:targetClass linkml_tutorial_2024:PersonCollection . + +linkml_tutorial_2024:Person a sh:NodeShape ; + sh:closed true ; + sh:description "Represents a Person" ; + sh:ignoredProperties ( rdf:type ) ; + sh:property [ sh:datatype xsd:string ; + sh:description "A human-readable description for a thing" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 6 ; + sh:path schema1:description ], + [ sh:datatype xsd:integer ; + sh:description "Number of years since birth" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 2 ; + sh:path linkml_tutorial_2024:age_in_years ], + [ sh:datatype xsd:string ; + sh:description "A human-readable name for a thing" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 5 ; + sh:path schema1:name ], + [ sh:datatype xsd:date ; + sh:description "Date on which a person is born" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 1 ; + sh:path schema1:birthDate ], + [ sh:datatype xsd:string ; + sh:description "The main email address of a person" ; + sh:maxCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 0 ; + sh:path schema1:email ; + sh:pattern "^\\S+@[\\S+\\.]+\\S+" ], + [ sh:datatype xsd:anyURI ; + sh:description "A unique identifier for a thing" ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:nodeKind sh:Literal ; + sh:order 4 ; + sh:path schema1:identifier ], + [ sh:description "living or dead status" ; + sh:in ( PATO:0001421 PATO:0001422 "UNKNOWN" ) ; + sh:maxCount 1 ; + sh:order 3 ; + sh:path linkml_tutorial_2024:vital_status ] ; + sh:targetClass linkml_tutorial_2024:Person . + diff --git a/project/shex/linkml_tutorial_2024.shex b/project/shex/linkml_tutorial_2024.shex new file mode 100644 index 0000000..70d4c3d --- /dev/null +++ b/project/shex/linkml_tutorial_2024.shex @@ -0,0 +1,75 @@ +# metamodel_version: 1.7.0 +BASE +PREFIX rdf: +PREFIX xsd: +PREFIX linkml: +PREFIX schema1: + + +linkml:String xsd:string + +linkml:Integer xsd:integer + +linkml:Boolean xsd:boolean + +linkml:Float xsd:float + +linkml:Double xsd:double + +linkml:Decimal xsd:decimal + +linkml:Time xsd:time + +linkml:Date xsd:date + +linkml:Datetime xsd:dateTime + +linkml:DateOrDatetime linkml:DateOrDatetime + +linkml:Uriorcurie IRI + +linkml:Curie xsd:string + +linkml:Uri IRI + +linkml:Ncname xsd:string + +linkml:Objectidentifier IRI + +linkml:Nodeidentifier NONLITERAL + +linkml:Jsonpointer xsd:string + +linkml:Jsonpath xsd:string + +linkml:Sparqlpath xsd:string + + ( + CLOSED { + ( $ ( schema1:name @linkml:String ? ; + schema1:description @linkml:String ? + ) ; + rdf:type [ schema1:Thing ] + ) + } OR @ +) + + CLOSED { + ( $ ( & ; + rdf:type [ schema1:Thing ] ? ; + schema1:email @linkml:String ? ; + schema1:birthDate @linkml:Date ? ; + @linkml:Integer ? ; + [ + ] ? + ) ; + rdf:type [ ] + ) +} + + CLOSED { + ( $ @ * ; + rdf:type [ ] ? + ) +} + diff --git a/project/sqlschema/linkml_tutorial_2024.sql b/project/sqlschema/linkml_tutorial_2024.sql new file mode 100644 index 0000000..39f254f --- /dev/null +++ b/project/sqlschema/linkml_tutorial_2024.sql @@ -0,0 +1,38 @@ +-- # Class: "NamedThing" Description: "A generic grouping for any identifiable entity" +-- * Slot: id Description: A unique identifier for a thing +-- * Slot: name Description: A human-readable name for a thing +-- * Slot: description Description: A human-readable description for a thing +-- # Class: "Person" Description: "Represents a Person" +-- * Slot: primary_email Description: The main email address of a person +-- * Slot: birth_date Description: Date on which a person is born +-- * Slot: age_in_years Description: Number of years since birth +-- * Slot: vital_status Description: living or dead status +-- * Slot: id Description: A unique identifier for a thing +-- * Slot: name Description: A human-readable name for a thing +-- * Slot: description Description: A human-readable description for a thing +-- * Slot: PersonCollection_id Description: Autocreated FK slot +-- # Class: "PersonCollection" Description: "A holder for Person objects" +-- * Slot: id Description: + +CREATE TABLE "NamedThing" ( + id TEXT NOT NULL, + name TEXT, + description TEXT, + PRIMARY KEY (id) +); +CREATE TABLE "PersonCollection" ( + id INTEGER NOT NULL, + PRIMARY KEY (id) +); +CREATE TABLE "Person" ( + primary_email TEXT, + birth_date DATE, + age_in_years INTEGER, + vital_status VARCHAR(7), + id TEXT NOT NULL, + name TEXT, + description TEXT, + "PersonCollection_id" INTEGER, + PRIMARY KEY (id), + FOREIGN KEY("PersonCollection_id") REFERENCES "PersonCollection" (id) +); \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d452ca9 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,30 @@ +[tool.poetry] +name = "linkml_tutorial_2024" +version = "0.1.0" +description = "This is the project description." +authors = ["My Name "] +license = "Apache Software License 2.0" +readme = "README.md" +include = ["README.md", "src/linkml_tutorial_2024/schema", "project"] + +[tool.poetry.dependencies] +python = "^3.9" +linkml-runtime = "^1.1.24" + +[tool.poetry-dynamic-versioning] +enable = true +vcs = "git" +style = "pep440" + +[tool.poetry.dev-dependencies] +linkml = "^1.3.5" +mkdocs-material = "^8.2.8" +mkdocs-mermaid2-plugin = "^1.1.1" +schemasheets = "^0.1.14" + +[build-system] +requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning"] +build-backend = "poetry_dynamic_versioning.backend" + +[tool.poetry.extras] +docs = ["linkml", "mkdocs-material"] diff --git a/src/data/examples/Person-001.yaml b/src/data/examples/Person-001.yaml new file mode 100644 index 0000000..617ff08 --- /dev/null +++ b/src/data/examples/Person-001.yaml @@ -0,0 +1,7 @@ +# Example data object +--- +entries: + - id: example:Person001 + name: foo bar + primary_email: foo.bar@example.com + age_in_years: 33 diff --git a/src/docs/about.md b/src/docs/about.md new file mode 100644 index 0000000..0f975cf --- /dev/null +++ b/src/docs/about.md @@ -0,0 +1,3 @@ +# linkml-tutorial-2024 + +This is the project description. diff --git a/src/linkml_tutorial_2024/_version.py b/src/linkml_tutorial_2024/_version.py new file mode 100644 index 0000000..7edc9ee --- /dev/null +++ b/src/linkml_tutorial_2024/_version.py @@ -0,0 +1,7 @@ +from importlib.metadata import version, PackageNotFoundError + +try: + __version__ = version(__name__) +except PackageNotFoundError: + # package not installed + __version__ = "0.0.0" diff --git a/src/linkml_tutorial_2024/datamodel/__init__.py b/src/linkml_tutorial_2024/datamodel/__init__.py new file mode 100644 index 0000000..5e424ec --- /dev/null +++ b/src/linkml_tutorial_2024/datamodel/__init__.py @@ -0,0 +1,7 @@ +from pathlib import Path +from .linkml_tutorial_2024 import * + +THIS_PATH = Path(__file__).parent + +SCHEMA_DIRECTORY = THIS_PATH.parent / "schema" +MAIN_SCHEMA_PATH = SCHEMA_DIRECTORY / "linkml_tutorial_2024.yaml" diff --git a/src/linkml_tutorial_2024/datamodel/linkml_tutorial_2024.py b/src/linkml_tutorial_2024/datamodel/linkml_tutorial_2024.py new file mode 100644 index 0000000..3d27313 --- /dev/null +++ b/src/linkml_tutorial_2024/datamodel/linkml_tutorial_2024.py @@ -0,0 +1,194 @@ +# Auto generated from linkml_tutorial_2024.yaml by pythongen.py version: 0.0.1 +# Generation date: 2024-07-08T14:51:23 +# Schema: linkml-tutorial-2024 +# +# id: https://w3id.org/my-org/linkml-tutorial-2024 +# description: This is the project description. +# license: Apache Software License 2.0 + +import dataclasses +import re +from jsonasobj2 import JsonObj, as_dict +from typing import Optional, List, Union, Dict, ClassVar, Any +from dataclasses import dataclass +from datetime import date, datetime +from linkml_runtime.linkml_model.meta import EnumDefinition, PermissibleValue, PvFormulaOptions + +from linkml_runtime.utils.slot import Slot +from linkml_runtime.utils.metamodelcore import empty_list, empty_dict, bnode +from linkml_runtime.utils.yamlutils import YAMLRoot, extended_str, extended_float, extended_int +from linkml_runtime.utils.dataclass_extensions_376 import dataclasses_init_fn_with_kwargs +from linkml_runtime.utils.formatutils import camelcase, underscore, sfx +from linkml_runtime.utils.enumerations import EnumDefinitionImpl +from rdflib import Namespace, URIRef +from linkml_runtime.utils.curienamespace import CurieNamespace +from linkml_runtime.linkml_model.types import Date, Integer, String, Uriorcurie +from linkml_runtime.utils.metamodelcore import URIorCURIE, XSDDate + +metamodel_version = "1.7.0" +version = None + +# Overwrite dataclasses _init_fn to add **kwargs in __init__ +dataclasses._init_fn = dataclasses_init_fn_with_kwargs + +# Namespaces +PATO = CurieNamespace('PATO', 'http://purl.obolibrary.org/obo/PATO_') +BIOLINK = CurieNamespace('biolink', 'https://w3id.org/biolink/') +EXAMPLE = CurieNamespace('example', 'https://example.org/') +LINKML = CurieNamespace('linkml', 'https://w3id.org/linkml/') +LINKML_TUTORIAL_2024 = CurieNamespace('linkml_tutorial_2024', 'https://w3id.org/my-org/linkml-tutorial-2024/') +SCHEMA = CurieNamespace('schema', 'http://schema.org/') +DEFAULT_ = LINKML_TUTORIAL_2024 + + +# Types + +# Class references +class NamedThingId(URIorCURIE): + pass + + +class PersonId(NamedThingId): + pass + + +@dataclass +class NamedThing(YAMLRoot): + """ + A generic grouping for any identifiable entity + """ + _inherited_slots: ClassVar[List[str]] = [] + + class_class_uri: ClassVar[URIRef] = SCHEMA["Thing"] + class_class_curie: ClassVar[str] = "schema:Thing" + class_name: ClassVar[str] = "NamedThing" + class_model_uri: ClassVar[URIRef] = LINKML_TUTORIAL_2024.NamedThing + + id: Union[str, NamedThingId] = None + name: Optional[str] = None + description: Optional[str] = None + + def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]): + if self._is_empty(self.id): + self.MissingRequiredField("id") + if not isinstance(self.id, NamedThingId): + self.id = NamedThingId(self.id) + + if self.name is not None and not isinstance(self.name, str): + self.name = str(self.name) + + if self.description is not None and not isinstance(self.description, str): + self.description = str(self.description) + + super().__post_init__(**kwargs) + + +@dataclass +class Person(NamedThing): + """ + Represents a Person + """ + _inherited_slots: ClassVar[List[str]] = [] + + class_class_uri: ClassVar[URIRef] = LINKML_TUTORIAL_2024["Person"] + class_class_curie: ClassVar[str] = "linkml_tutorial_2024:Person" + class_name: ClassVar[str] = "Person" + class_model_uri: ClassVar[URIRef] = LINKML_TUTORIAL_2024.Person + + id: Union[str, PersonId] = None + primary_email: Optional[str] = None + birth_date: Optional[Union[str, XSDDate]] = None + age_in_years: Optional[int] = None + vital_status: Optional[Union[str, "PersonStatus"]] = None + + def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]): + if self._is_empty(self.id): + self.MissingRequiredField("id") + if not isinstance(self.id, PersonId): + self.id = PersonId(self.id) + + if self.primary_email is not None and not isinstance(self.primary_email, str): + self.primary_email = str(self.primary_email) + + if self.birth_date is not None and not isinstance(self.birth_date, XSDDate): + self.birth_date = XSDDate(self.birth_date) + + if self.age_in_years is not None and not isinstance(self.age_in_years, int): + self.age_in_years = int(self.age_in_years) + + if self.vital_status is not None and not isinstance(self.vital_status, PersonStatus): + self.vital_status = PersonStatus(self.vital_status) + + super().__post_init__(**kwargs) + + +@dataclass +class PersonCollection(YAMLRoot): + """ + A holder for Person objects + """ + _inherited_slots: ClassVar[List[str]] = [] + + class_class_uri: ClassVar[URIRef] = LINKML_TUTORIAL_2024["PersonCollection"] + class_class_curie: ClassVar[str] = "linkml_tutorial_2024:PersonCollection" + class_name: ClassVar[str] = "PersonCollection" + class_model_uri: ClassVar[URIRef] = LINKML_TUTORIAL_2024.PersonCollection + + entries: Optional[Union[Dict[Union[str, PersonId], Union[dict, Person]], List[Union[dict, Person]]]] = empty_dict() + + def __post_init__(self, *_: List[str], **kwargs: Dict[str, Any]): + self._normalize_inlined_as_dict(slot_name="entries", slot_type=Person, key_name="id", keyed=True) + + super().__post_init__(**kwargs) + + +# Enumerations +class PersonStatus(EnumDefinitionImpl): + + ALIVE = PermissibleValue( + text="ALIVE", + description="the person is living", + meaning=PATO["0001421"]) + DEAD = PermissibleValue( + text="DEAD", + description="the person is deceased", + meaning=PATO["0001422"]) + UNKNOWN = PermissibleValue( + text="UNKNOWN", + description="the vital status is not known") + + _defn = EnumDefinition( + name="PersonStatus", + ) + +# Slots +class slots: + pass + +slots.id = Slot(uri=SCHEMA.identifier, name="id", curie=SCHEMA.curie('identifier'), + model_uri=LINKML_TUTORIAL_2024.id, domain=None, range=URIRef) + +slots.name = Slot(uri=SCHEMA.name, name="name", curie=SCHEMA.curie('name'), + model_uri=LINKML_TUTORIAL_2024.name, domain=None, range=Optional[str]) + +slots.description = Slot(uri=SCHEMA.description, name="description", curie=SCHEMA.curie('description'), + model_uri=LINKML_TUTORIAL_2024.description, domain=None, range=Optional[str]) + +slots.primary_email = Slot(uri=SCHEMA.email, name="primary_email", curie=SCHEMA.curie('email'), + model_uri=LINKML_TUTORIAL_2024.primary_email, domain=None, range=Optional[str]) + +slots.birth_date = Slot(uri=SCHEMA.birthDate, name="birth_date", curie=SCHEMA.curie('birthDate'), + model_uri=LINKML_TUTORIAL_2024.birth_date, domain=None, range=Optional[Union[str, XSDDate]]) + +slots.age_in_years = Slot(uri=LINKML_TUTORIAL_2024.age_in_years, name="age_in_years", curie=LINKML_TUTORIAL_2024.curie('age_in_years'), + model_uri=LINKML_TUTORIAL_2024.age_in_years, domain=None, range=Optional[int]) + +slots.vital_status = Slot(uri=LINKML_TUTORIAL_2024.vital_status, name="vital_status", curie=LINKML_TUTORIAL_2024.curie('vital_status'), + model_uri=LINKML_TUTORIAL_2024.vital_status, domain=None, range=Optional[Union[str, "PersonStatus"]]) + +slots.personCollection__entries = Slot(uri=LINKML_TUTORIAL_2024.entries, name="personCollection__entries", curie=LINKML_TUTORIAL_2024.curie('entries'), + model_uri=LINKML_TUTORIAL_2024.personCollection__entries, domain=None, range=Optional[Union[Dict[Union[str, PersonId], Union[dict, Person]], List[Union[dict, Person]]]]) + +slots.Person_primary_email = Slot(uri=SCHEMA.email, name="Person_primary_email", curie=SCHEMA.curie('email'), + model_uri=LINKML_TUTORIAL_2024.Person_primary_email, domain=Person, range=Optional[str], + pattern=re.compile(r'^\S+@[\S+\.]+\S+')) \ No newline at end of file diff --git a/src/linkml_tutorial_2024/schema/linkml_tutorial_2024.yaml b/src/linkml_tutorial_2024/schema/linkml_tutorial_2024.yaml new file mode 100644 index 0000000..f49f961 --- /dev/null +++ b/src/linkml_tutorial_2024/schema/linkml_tutorial_2024.yaml @@ -0,0 +1,96 @@ +--- +id: https://w3id.org/my-org/linkml-tutorial-2024 +name: linkml-tutorial-2024 +title: linkml-tutorial-2024 +description: |- + This is the project description. +license: Apache Software License 2.0 +see_also: + - https://my-org.github.io/linkml-tutorial-2024 + +prefixes: + linkml_tutorial_2024: https://w3id.org/my-org/linkml-tutorial-2024/ + linkml: https://w3id.org/linkml/ + biolink: https://w3id.org/biolink/ + schema: http://schema.org/ + PATO: http://purl.obolibrary.org/obo/PATO_ + example: https://example.org/ +default_prefix: linkml_tutorial_2024 +default_range: string + +imports: + - linkml:types + +classes: + + NamedThing: + description: >- + A generic grouping for any identifiable entity + slots: + - id + - name + - description + class_uri: schema:Thing + + Person: + is_a: NamedThing + description: >- + Represents a Person + slots: + - primary_email + - birth_date + - age_in_years + - vital_status + slot_usage: + primary_email: + pattern: "^\\S+@[\\S+\\.]+\\S+" + + PersonCollection: + tree_root: true + description: >- + A holder for Person objects + attributes: + entries: + range: Person + multivalued: true + inlined: true + +slots: + id: + identifier: true + slot_uri: schema:identifier + range: uriorcurie + description: A unique identifier for a thing + name: + slot_uri: schema:name + description: A human-readable name for a thing + description: + slot_uri: schema:description + description: A human-readable description for a thing + primary_email: + slot_uri: schema:email + description: The main email address of a person + birth_date: + slot_uri: schema:birthDate + range: date + description: Date on which a person is born + age_in_years: + range: integer + description: Number of years since birth + vital_status: + range: PersonStatus + description: living or dead status + +enums: + PersonStatus: + permissible_values: + ALIVE: + description: the person is living + meaning: PATO:0001421 + DEAD: + description: the person is deceased + meaning: PATO:0001422 + UNKNOWN: + description: the vital status is not known + todos: + - map this to an ontology diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..303e57e --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for linkml-tutorial-2024.""" diff --git a/tests/test_data.py b/tests/test_data.py new file mode 100644 index 0000000..d67cd6e --- /dev/null +++ b/tests/test_data.py @@ -0,0 +1,22 @@ +"""Data test.""" +import os +import glob +import unittest + +from linkml_runtime.loaders import yaml_loader +from linkml_tutorial_2024.datamodel.linkml_tutorial_2024 import PersonCollection + +ROOT = os.path.join(os.path.dirname(__file__), '..') +DATA_DIR = os.path.join(ROOT, "src", "data", "examples") + +EXAMPLE_FILES = glob.glob(os.path.join(DATA_DIR, '*.yaml')) + + +class TestData(unittest.TestCase): + """Test data and datamodel.""" + + def test_data(self): + """Data test.""" + for path in EXAMPLE_FILES: + obj = yaml_loader.load(path, target_class=PersonCollection) + assert obj