├── .github └── workflows │ ├── build.yml │ ├── cffconvert.yml │ └── pypi.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .zenodo.json ├── CHANGELOG.md ├── CITATION.cff ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs ├── assets │ ├── FAIR_data_principles.png │ ├── custom.css │ ├── fontawesome.min.js │ ├── icon.png │ ├── nanopub.png │ └── solid.min.js ├── getting-started │ ├── development.md │ ├── setup.md │ ├── test-server.md │ ├── use-the-cli.md │ └── what-are-nanopubs.md ├── index.md ├── publishing │ ├── profile.md │ ├── publish-nanopublications.md │ ├── retraction.md │ ├── setting-subgraphs.md │ ├── templates.md │ └── using-publication-namespace.md ├── reference │ ├── client.md │ ├── client.rst │ ├── config.md │ ├── namespaces.md │ ├── namespaces.rst │ ├── nanopub.md │ ├── profile.md │ ├── publication.rst │ └── templates.md └── searching │ ├── fetching.md │ └── searching.md ├── examples ├── controlling-subgraphs.ipynb ├── create_and_publish.ipynb ├── create_and_publish_fdo.ipynb ├── create_and_validate_fdo_exp.ipynb ├── create_validate_update_fdo_nanopub.ipynb ├── publishing_and_retracting.ipynb ├── searching.ipynb └── using_publication_namespace.ipynb ├── mkdocs.yml ├── nanopub ├── __init__.py ├── __main__.py ├── _version.py ├── client.py ├── constants.py ├── definitions.py ├── fdo_metadata.py ├── fdo_nanopub.py ├── fdo_ops.py ├── namespaces.py ├── nanopub.py ├── nanopub_conf.py ├── profile.py ├── py.typed ├── sign_utils.py ├── templates │ ├── __init__.py │ ├── nanopub_claim.py │ ├── nanopub_index.py │ ├── nanopub_introduction.py │ ├── nanopub_retract.py │ └── nanopub_update.py ├── trustyuri │ ├── CheckFile.py │ ├── ModuleDirectory.py │ ├── RunBatch.py │ ├── TrustyUriModule.py │ ├── TrustyUriResource.py │ ├── TrustyUriUtils.py │ ├── __init__.py │ ├── file │ │ ├── FileHasher.py │ │ ├── FileModule.py │ │ ├── ProcessFile.py │ │ └── __init__.py │ └── rdf │ │ ├── HashAdder.py │ │ ├── RdfHasher.py │ │ ├── RdfModule.py │ │ ├── RdfPreprocessor.py │ │ ├── RdfTransformer.py │ │ ├── RdfUtils.py │ │ ├── StatementComparator.py │ │ ├── TransformRdf.py │ │ └── __init__.py └── utils.py ├── pyproject.toml ├── scripts ├── all.sh ├── dev.py ├── dev.sh ├── docs.sh ├── format.sh ├── html-cov-test.sh ├── install.sh ├── lint.sh ├── nanopub-java ├── nanopub-java.bat ├── notebooks.sh └── test.sh └── tests ├── __init__.py ├── conftest.py ├── java_wrapper.py ├── resources ├── id_rsa ├── id_rsa.pub ├── many_bnodes_with_annotations.json ├── nanopub_sample_signed.trig └── nanopub_sample_signed.trig.signed.trig ├── test_cli.py ├── test_client.py ├── test_fdo_nanopub.py ├── test_fdo_ops.py ├── test_nanopub.py ├── test_profile.py ├── test_sign_utils.py ├── test_testsuite.py └── testsuite ├── invalid ├── plain │ ├── emptya.trig │ ├── emptyinfo.trig │ ├── emptyprov.trig │ ├── extragraph.trig │ ├── noinfolink.trig │ ├── noprovlink.trig │ └── valid_invalid1.trig ├── signed │ ├── simple1-invalid-dsa.trig │ └── simple1-invalid-rsa.trig └── trusty │ └── trusty1.trig ├── transform ├── signed │ └── rsa-key1 │ │ ├── key │ │ ├── id_rsa │ │ └── id_rsa.pub │ │ ├── simple1.in.trig │ │ ├── simple1.out.code │ │ └── simple1.out.trig └── trusty │ ├── aida1.in.trig │ ├── aida1.out.code │ ├── aida1.out.trig │ ├── simple1.in.trig │ ├── simple1.out.code │ └── simple1.out.trig └── valid ├── plain ├── aida1.trig ├── proteinatlas-16-1.trig ├── simple1.nq ├── simple1.trig └── simple1.xml ├── signed ├── Darwin-Core-schema-resource.trig ├── EduSocDL-community.trig ├── nanobench_hasRead-template-v5.trig ├── nanobench_new-individual-template-v3.trig ├── nanobench_somebodyElse-prtemplate.trig ├── physician-suicide-1.trig ├── python-step-1.trig ├── simple1-signed-dsa.trig ├── simple1-signed-rsa.trig └── workflow-1.trig └── trusty ├── disgenet-v2.1.0.0-1.trig ├── disgenet-v3.0.0.0-1.trig ├── fair-definition-1.trig ├── fair-maturity-1.trig ├── fip-ontology-1.trig ├── generif-aida-1.trig ├── generif-aida-index.trig ├── genuine-sempub-1.trig ├── genuine-sempub-2.trig ├── globalbioticinteractions_aps-turfgrasses-1.trig ├── globalbioticinteractions_bees-1.trig ├── globalbioticinteractions_inaturalist-1.trig ├── globalbioticinteractions_raymond-1.trig ├── liddi-1.trig ├── linkflows-article-1.trig ├── linkflows-review-1.trig ├── nextprot-1.trig ├── openbel-1.trig ├── provcorp-definition-1.trig ├── provcorp-parc-annotation-1.trig ├── trusty1.trig ├── wd-metabolite-species-1.trig ├── wikipathways-complexes-20170510-1.trig ├── wikipathways-interactions-20170510-1.trig └── wikipathways-pathwayParticipation-20170510-1.trig /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Tests and update docs 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | 7 | tests: 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | python-version: [3.7, 3.8, 3.9, '3.10'] 12 | rdflib-version: 13 | - rdflib==6.0.2 14 | - rdflib>6.0.2,<7.0.0 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - name: Set up Python ${{ matrix.python-version }} 20 | uses: actions/setup-python@v4 21 | with: 22 | python-version: ${{ matrix.python-version }} 23 | 24 | - name: Install dependencies with ${{ matrix.rdflib-version }} 25 | env: 26 | RDFLIB_VERSION: ${{ matrix.rdflib-version }} 27 | run: | 28 | pip install ".[test,dev]" "$RDFLIB_VERSION" 29 | 30 | - name: Lint with flake8, isort and mypy 31 | run: bash scripts/lint.sh 32 | 33 | - name: Setup nanopub profile (including RSA keys) 34 | run: | 35 | np setup --orcid-id https://orcid.org/0000-0000-0000-0000 --no-publish --name test --newkeys 36 | 37 | - name: Test with pytest 38 | run: | 39 | pytest --cov 40 | 41 | - name: Publish coverage to Coveralls 42 | env: 43 | COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} 44 | if: ${{ env.COVERALLS_REPO_TOKEN }} 45 | run: | 46 | coverage xml 47 | coveralls 48 | 49 | 50 | build-docs: 51 | needs: [ tests ] 52 | runs-on: ubuntu-latest 53 | 54 | steps: 55 | - uses: actions/checkout@v3 56 | 57 | - name: Set up Python 58 | uses: actions/setup-python@v4 59 | with: 60 | python-version: 3.9 61 | 62 | - name: Install dependencies 63 | run: | 64 | pip install ".[doc]" 65 | 66 | - name: Deploy mkdocs on GitHub Pages 67 | env: 68 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 69 | run: | 70 | git pull 71 | mkdocs gh-deploy 72 | -------------------------------------------------------------------------------- /.github/workflows/cffconvert.yml: -------------------------------------------------------------------------------- 1 | name: Validate CITATION.cff 2 | 3 | on: 4 | push: 5 | paths: 6 | - CITATION.cff 7 | 8 | jobs: 9 | validate: 10 | name: "validate" 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out a copy of the repository 14 | uses: actions/checkout@v3 15 | 16 | - name: Check whether the citation metadata from CITATION.cff is valid 17 | uses: citation-file-format/cffconvert-github-action@2.0.0 18 | with: 19 | args: "--validate" 20 | -------------------------------------------------------------------------------- /.github/workflows/pypi.yml: -------------------------------------------------------------------------------- 1 | name: Publish to PyPI 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | 13 | - name: Set up Python 14 | uses: actions/setup-python@v4 15 | with: 16 | python-version: "3.7" 17 | 18 | - name: Install build dependencies 19 | run: pip install build 20 | 21 | - name: Build distribution 22 | run: python -m build 23 | 24 | - name: Publish 25 | uses: pypa/gh-action-pypi-publish@release/v1 26 | with: 27 | password: ${{ secrets.PYPI_TOKEN }} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Signed nanopubs files in tests 2 | tests/testsuite/**/signed.*.* 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | lib/ 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | pip-wheel-metadata/ 28 | share/python-wheels/ 29 | *.egg-info/ 30 | .installed.cfg 31 | *.egg 32 | MANIFEST 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .nox/ 48 | .coverage 49 | .coverage.* 50 | .cache 51 | nosetests.xml 52 | coverage.xml 53 | *.cover 54 | *.py,cover 55 | .hypothesis/ 56 | .pytest_cache/ 57 | 58 | # Translations 59 | *.mo 60 | *.pot 61 | 62 | # Django stuff: 63 | *.log 64 | local_settings.py 65 | db.sqlite3 66 | db.sqlite3-journal 67 | 68 | # Flask stuff: 69 | instance/ 70 | .webassets-cache 71 | 72 | # Scrapy stuff: 73 | .scrapy 74 | 75 | # Sphinx documentation 76 | docs/_build/ 77 | 78 | # PyBuilder 79 | target/ 80 | 81 | # Jupyter Notebook 82 | .ipynb_checkpoints 83 | 84 | # IPython 85 | profile_default/ 86 | ipython_config.py 87 | 88 | # pyenv 89 | .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | 135 | # ide 136 | .idea 137 | .eclipse 138 | .vscode 139 | 140 | # Vim 141 | *.swp 142 | 143 | # Eclipse 144 | *.project 145 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # See https://pre-commit.com for more information 2 | # See https://pre-commit.com/hooks.html for more hooks 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.3.0 6 | hooks: 7 | - id: check-added-large-files 8 | name: 🐘 Check for added large files 9 | - id: check-toml 10 | name: ✔️ Check TOML 11 | - id: check-yaml 12 | name: ✔️ Check YAML 13 | args: 14 | - --unsafe 15 | - id: end-of-file-fixer 16 | name: 🪚 Fix end of files 17 | - id: trailing-whitespace 18 | name: ✂️ Trim trailing whitespaces 19 | # - repo: https://github.com/asottile/pyupgrade 20 | # rev: v2.37.3 21 | # hooks: 22 | # - id: pyupgrade 23 | # name: ⏫ Running pyupgrade 24 | # args: 25 | # - --py3-plus 26 | # - --keep-runtime-typing 27 | # - repo: https://github.com/myint/autoflake 28 | # rev: v1.5.3 29 | # hooks: 30 | # - id: autoflake 31 | # name: ❄️ Running autoflake 32 | # args: 33 | # - --recursive 34 | # - --in-place 35 | # - --remove-all-unused-imports 36 | # - --remove-unused-variables 37 | # - --expand-star-imports 38 | # - --exclude 39 | # - __init__.py 40 | # - --remove-duplicate-keys 41 | # - repo: https://github.com/pycqa/isort 42 | # rev: 5.10.1 43 | # hooks: 44 | # - id: isort 45 | # name: 🔄 Formatting imports with isort (python) 46 | ci: 47 | autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks 48 | autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate 49 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "creators": [ 3 | { 4 | "affiliation": "Netherlands eScience Center", 5 | "name": "van der Burg, Sven" 6 | }, 7 | { 8 | "affiliation": "Netherlands eScience Center", 9 | "name": "Richardson, Robin" 10 | }, 11 | { 12 | "affiliation": "Netherlands eScience Center", 13 | "name": "Smits, Djura" 14 | }, 15 | { 16 | "affiliation": "Maastricht University", 17 | "name": "Emonet, Vincent" 18 | } 19 | ], 20 | "description": "The nanopub python library provides a client for searching, publishing and modifying nanopublications.", 21 | "keywords": [ 22 | "semantic", 23 | "RDF", 24 | "FAIR", 25 | "nanopublications" 26 | ], 27 | "license": { 28 | "id": "Apache-2.0" 29 | }, 30 | "title": "nanopub: A python library for searching, publishing and modifying nanopublications" 31 | } 32 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # YAML 1.2 2 | --- 3 | abstract: "The nanopub python library provides a client for searching, publishing and modifying nanopublications." 4 | 5 | authors: 6 | - 7 | affiliation: "Netherlands eScience Center" 8 | family-names: Burg 9 | given-names: Sven 10 | name-particle: "van der" 11 | - 12 | affiliation: "Netherlands eScience Center" 13 | family-names: Richardson 14 | given-names: Robin 15 | orcid: "https://orcid.org/0000-0002-9984-2720" 16 | - 17 | affiliation: "Netherlands eScience Center" 18 | family-names: Smits 19 | given-names: Djura 20 | - 21 | affiliation: "Maastricht University" 22 | family-names: Emonet 23 | given-names: Vincent 24 | orcid: "https://orcid.org/0000-0002-1501-1082" 25 | cff-version: "1.0.3" 26 | keywords: 27 | - "semantic" 28 | - "RDF" 29 | - "FAIR" 30 | - "nanopublications" 31 | license: "Apache-2.0" 32 | message: "If you use this software, please cite it using these metadata." 33 | title: "nanopub: A python library for searching, publishing and modifying nanopublications" 34 | version: "2.0.0" 35 | date-released: "2022-12-15" 36 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | education, socio-economic status, nationality, personal appearance, race, 10 | religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at r.richardson@esciencecenter.nl. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines 2 | 3 | We welcome any kind of contribution to our software, from simple comment or question to a full fledged [pull request](https://help.github.com/articles/about-pull-requests/). Please read and follow our [Code of Conduct](CODE_OF_CONDUCT.md). 4 | 5 | A contribution can be one of the following cases: 6 | 7 | 1. you have a question; 8 | 1. you think you may have found a bug (including unexpected behavior); 9 | 1. you want to make some kind of change to the code base (e.g. to fix a bug, to add a new feature, to update documentation). 10 | 11 | The sections below outline the steps in each case. 12 | 13 | ## You have a question 14 | 15 | 1. use the search functionality [here](https://github.com/fair-workflows/nanopub/issues) to see if someone already filed the same issue; 16 | 1. if your issue search did not yield any relevant results, make a new issue; 17 | 1. apply the "Question" label; apply other labels when relevant. 18 | 19 | ## You think you may have found a bug 20 | 21 | 1. use the search functionality [here](https://github.com/fair-workflows/nanopub/issues) to see if someone already filed the same issue; 22 | 1. if your issue search did not yield any relevant results, make a new issue, making sure to provide enough information to the rest of the community to understand the cause and context of the problem. Depending on the issue, you may want to include: 23 | - the [SHA hashcode](https://help.github.com/articles/autolinked-references-and-urls/#commit-shas) of the commit that is causing your problem; 24 | - some identifying information (name and version number) for dependencies you're using; 25 | - information about the operating system; 26 | 1. apply relevant labels to the newly created issue. 27 | 28 | ## You want to make some kind of change to the code base 29 | 30 | 1. (**important**) announce your plan to the rest of the community _before you start working_. This announcement should be in the form of a (new) issue; 31 | 1. (**important**) wait until some kind of consensus is reached about your idea being a good idea; 32 | 1. if needed, fork the repository to your own Github profile and create your own feature branch off of the latest master commit. While working on your feature branch, make sure to stay up to date with the master branch by pulling in changes, possibly from the 'upstream' repository (follow the instructions [here](https://help.github.com/articles/configuring-a-remote-for-a-fork/) and [here](https://help.github.com/articles/syncing-a-fork/)); 33 | 1. visit the **[development page](https://nanopublication.github.io/nanopub-py/getting-started/development/)** on the documentation website for more details on the development workflow. 34 | 35 | 1. make sure the existing tests still work by running ``pytest``. Note that any pull requests to the nanopub repository on github will automatically trigger running of the test suite; 36 | 1. check that the code is in accordance with the PEP8 style guide (cf. [development page](https://nanopublication.github.io/nanopub-py/getting-started/development/) to run the lint script with `flake8` and `mypy`) 37 | 1. add your own tests (if necessary); 38 | 1. update or expand the documentation; 39 | 1. [push](http://rogerdudler.github.io/git-guide/) your feature branch to (your fork of) the nanopub repository on GitHub; 40 | 1. create the pull request, e.g. following the instructions [here](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | In case you feel like you've made a valuable contribution, but you don't know how to write or run tests for it, or how to generate the documentation: don't let this discourage you from making the pull request; we can help you! Just go ahead and submit the pull request, but keep in mind that you might be asked to append additional commits to your pull request. 43 | -------------------------------------------------------------------------------- /docs/assets/FAIR_data_principles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanopublication/nanopub-py/9482610f7463ca0b8e27fe6ea47fb3f4c185bf41/docs/assets/FAIR_data_principles.png -------------------------------------------------------------------------------- /docs/assets/custom.css: -------------------------------------------------------------------------------- 1 | 2 | code.highlight { 3 | font-size: 18px; 4 | } 5 | -------------------------------------------------------------------------------- /docs/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanopublication/nanopub-py/9482610f7463ca0b8e27fe6ea47fb3f4c185bf41/docs/assets/icon.png -------------------------------------------------------------------------------- /docs/assets/nanopub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanopublication/nanopub-py/9482610f7463ca0b8e27fe6ea47fb3f4c185bf41/docs/assets/nanopub.png -------------------------------------------------------------------------------- /docs/getting-started/setup.md: -------------------------------------------------------------------------------- 1 | # Setup instructions 2 | 3 | ## 📥️ Install the nanopub library 4 | Install using pip: 5 | ``` 6 | pip install nanopub 7 | ``` 8 | 9 | ## 🐍 Setup for users new to python 10 | We recommend using [anaconda](https://www.anaconda.com/products/individual) to install python and manage python dependencies 11 | 12 | ## 👤 Setup your profile 13 | 14 | To publish to the nanopub server you need to setup your profile (note that you can use fetch and search functionality without a profile). This allows the nanopub server to identify you. 15 | 16 | To check if your profile is properly set, run the following command in your terminal: 17 | 18 | ```bash 19 | np profile 20 | ``` 21 | 22 | To setup your profile, run the following interactive command: 23 | 24 | ```bash 25 | np setup 26 | ``` 27 | 28 | This will setup the following: 29 | 30 | ### Stored profile 31 | A local version of the profile will be stored in the nanopub user config dir (by default `HOMEDIR/.nanopub/profile.yml`) 32 | 33 | ### RSA keys 34 | It will add and store RSA keys to sign your nanopublications. By default they are stored under `HOMEDIR/.nanopub/id_rsa` and `HOMEDIR/.nanopub/id_rsa.pub`. 35 | 36 | ### ORCID iD 37 | This includes your [ORCID iD](https://orcid.org/) (i.e. https://orcid.org/0000-0000-0000-0000). 38 | 39 | If you don't have an ORCID iD yet, you need to [register](https://orcid.org/register). We use the ORCID iD to automatically add as author to the provenance of any nanopublication you will publish using this library. 40 | 41 | ### Introductory nanopublication 42 | We encourage you to make use of `np setup`'s option to publish your profile to the nanopub servers. This links your ORCID iD to your RSA key, thereby making all your publications linkable to you. Here is an [example introductory nanopublicaiton](http://purl.org/np/RAy1CYBfBYFd_TFI8Z_jr3taf6fB9u-grqsKyLzTmMvQI). The link to this nanopublication is also stored in your profile. 43 | 44 | ## ☑️ Check your profile 45 | 46 | You can check the profile currently used by default by running this command in your terminal: 47 | 48 | ```bash 49 | np profile 50 | ``` 51 | -------------------------------------------------------------------------------- /docs/getting-started/test-server.md: -------------------------------------------------------------------------------- 1 | # The nanopub test server 2 | Throughout this documentation we make use of the 3 | [nanopub test server](https://np.test.knowledgepixels.com/) 4 | by setting `use_test_server=True` when instantiating `NanopubConf` or `NanopubClient`: 5 | ```python 6 | from nanopub import NanopubClient, NanopubConf 7 | 8 | client = NanopubClient(use_test_server=True) 9 | np_conf = NanopubConf(use_test_server=True) 10 | ``` 11 | This will search and fetch from, and publish to the [nanopub test server](https://np.test.knowledgepixels.com/). 12 | 13 | When learning about nanopub using the testserver is a good idea, because: 14 | * You are free to experiment with publishing without polluting the production server. 15 | * You can draft a publication and know exactly what it will look like on the nanopub server without polluting the production server. 16 | * When searching (and to a lesser extent fetching) you are not putting an unnecessary load on the production server. 17 | 18 | ## Test purl URIs do not point to the test server 19 | There is one caveat when using the test server that can be confusing: 20 | The purl URI (for example: [http://purl.org/np/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8](http://server.nanopubs.lod.labs.vu.nl/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8)) 21 | points to the [nanopub production server](http://server.nanopubs.lod.labs.vu.nl/) 22 | resulting in a 404 page not found error. 23 | 24 | A manual workaround is: 25 | 1. Open [http://purl.org/np/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8](http://purl.org/np/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8) 26 | in your browser 27 | 2. Notice that the URL changed to [http://server.nanopubs.lod.labs.vu.nl/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8](http://server.nanopubs.lod.labs.vu.nl/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8). 28 | 3. Replace 'server' with 'test-server': [https://np.test.knowledgepixels.com/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8](https://np.test.knowledgepixels.com/RA71u9tYPd7ZQifE_6hXjqVim6pkweuvjoi-8ehvLvzg8). 29 | 30 | > **NB**: `NanopubClient.fetch()` does this for you if `use_test_server=True`. 31 | -------------------------------------------------------------------------------- /docs/getting-started/use-the-cli.md: -------------------------------------------------------------------------------- 1 | # Use the command line interface 2 | 3 | Once installed, you can use the `nanopub` library through the `np` command line interface to sign and publish Nanopublication. 4 | 5 | ## 👤 Check the current user profile 6 | 7 | ```bash 8 | np profile 9 | ``` 10 | 11 | ## ✍️ Set your user profile 12 | 13 | See the [setup instructions](/nanopub/getting-started/setup) page for more details about setting up your profile. 14 | 15 | ```bash 16 | np setup 17 | ``` 18 | 19 | ## ✒️ Sign nanopubs 20 | 21 | Sign a nanopublication from a file, this will generate the signed nanopub in a new file `signed.nanopub.trig` alongside the original: 22 | 23 | ```bash 24 | np sign nanopub.trig 25 | ``` 26 | 27 | ## 📬️ Publish nanopubs 28 | 29 | Publish a nanopublication from a signed file: 30 | 31 | ```bash 32 | np publish signed.nanopub.trig 33 | ``` 34 | 35 | Or directly publish a nanopublication from an unsigned file: 36 | 37 | ```bash 38 | np publish nanopub.trig 39 | ``` 40 | 41 | You can also publish to the test server: 42 | 43 | ```bash 44 | np publish nanopub.trig --test 45 | ``` 46 | 47 | ## ☑️ Check signed nanopubs 48 | 49 | Check if a signed nanopublication is valid: 50 | 51 | ```bash 52 | np check signed.nanopub.trig 53 | ``` 54 | 55 | ## ℹ️ Get help 56 | 57 | Display the help for the different commands with the `--help` flag. 58 | 59 | ```bash 60 | np --help 61 | np sign --help 62 | ``` 63 | -------------------------------------------------------------------------------- /docs/getting-started/what-are-nanopubs.md: -------------------------------------------------------------------------------- 1 | # What are nanopublications? 2 | Nanopublications are a formalized and machine-readable way of communicating the smallest possible units of publishable information. This could be, for example, the outcome of a scientific study or a claim 3 | made by a particular scientist. 4 | 5 | Nanopublications are searchable, citable, and contain authorship and attribution information. The aim is to encourage individual scientific results to be released in a traceable and interoperable format. As such, nanopublications are an effective [FAIR](https://www.go-fair.org/fair-principles/) means of communicating scientific claims and results. 6 | 7 | Read more about nanopublications at **[nanopub.org](https://nanopub.org)**. 8 | 9 | ## Different elements of a nanopublication 10 | _From [nanopub.org](http://nanopub.org/wordpress/?page_id=65) documentation (2020/12/02)_ 11 | 12 | ![Schematic representation of a nanopub](../assets/nanopub.png "Schematic representation of a nanopub") 13 | 14 | As can be seen in this image, a nanopublication has three basic elements: 15 | 16 | 1. Assertion: The assertion is the main content of a nanopublication in the form of an small atomic unit of information 17 | 2. Provenance: This part describes how the assertion above came to be. This can include the scientific methods that were used to generate the assertion, for example a reference to the kind of study that was performed and its parameters. 18 | 3. Publication Info: This part contains metadata about the nanopublication as a whole, such as when and by whom it was created and the license terms for its reuse. 19 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | 2 | # Welcome to nanopub's documentation! 3 | 4 | The `nanopub` library provides a high-level, user-friendly python interface for searching, publishing and retracting nanopublications. 5 | 6 | Nanopublications are a formalized and machine-readable way of communicating the smallest possible units of publishable information. See the [What are Nanopublications?](getting-started/what-are-nanopubs) page for more information. 7 | 8 | ## 📦️ Setup 9 | 10 | Install using pip: 11 | 12 | ```bash 13 | pip install nanopub 14 | ``` 15 | 16 | To publish to the nanopub server you need to setup your profile, this allows the nanopub server to identify you. To check if your profile is properly set, run `np profile` in your terminal. If it is not set yet, run the following interactive command to setup your profile: 17 | 18 | ```bash 19 | np setup 20 | ``` 21 | 22 | This will add and store RSA keys to sign your nanopublications, publish a nanopublication with your name and ORCID iD to declare that you are using using these RSA keys, and store your ORCID iD to automatically add as author to the provenance of any nanopublication you will publish using this library. 23 | 24 | ## ⚡️ Quick Start 25 | 26 | ### Publishing nanopublications 27 | 28 | Use `load_profile()` to load the user profile from `$HOME/.nanopub`, and `use_test_server` to point to the test server (remove it to publish to the nanopublication network) 29 | 30 | ```python 31 | import rdflib 32 | from nanopub import Nanopub, NanopubConf, load_profile 33 | 34 | # 1. Create the config 35 | np_conf = NanopubConf( 36 | profile=load_profile(), 37 | use_test_server=True, 38 | add_prov_generated_time=True, 39 | attribute_publication_to_profile=True, 40 | ) 41 | 42 | # 2. Construct a desired assertion (a graph of RDF triples) using rdflib 43 | my_assertion = rdflib.Graph() 44 | my_assertion.add(( 45 | rdflib.URIRef('www.example.org/timbernerslee'), 46 | rdflib.RDF.type, 47 | rdflib.FOAF.Person 48 | )) 49 | 50 | # 3. Make a Nanopub object with this assertion 51 | np = Nanopub( 52 | conf=np_conf, 53 | assertion=my_assertion 54 | ) 55 | 56 | # 4. Publish the Nanopub object 57 | np.publish() 58 | print(np) 59 | ``` 60 | 61 | You can also just sign the nanopub with `np.sign()`. Upon signing, or publishing, the `np` object will be automatically updated with the signed RDF and generated trusty URI. 62 | 63 | ### Searching for nanopublications 64 | 65 | ```python 66 | from nanopub import NanopubClient 67 | 68 | # Create the client 69 | client = NanopubClient() 70 | 71 | # Search for all nanopublications containing the text 'fair' 72 | results = client.find_nanopubs_with_text('fair') 73 | for result in results: 74 | print(result) 75 | ``` 76 | 77 | ### Fetching nanopublications and inspecting them 78 | 79 | ```python 80 | from nanopub import NanopubClient 81 | 82 | # Create the client 83 | client = NanopubClient() 84 | 85 | # Fetch the nanopublication at the specified URI 86 | np = client.fetch('http://purl.org/np/RApJG4fwj0szOMBMiYGmYvd5MCtRle6VbwkMJUb1SxxDM') 87 | print(np) 88 | 89 | # Iterate through all triples in the assertion graph 90 | for s, p, o in np.assertion: 91 | print(s, p, o) 92 | ``` 93 | -------------------------------------------------------------------------------- /docs/publishing/profile.md: -------------------------------------------------------------------------------- 1 | # Set the user profile 2 | 3 | !!! info "Prerequisite for publishing" 4 | 5 | Before you can sign and publish you should [setup your profile](/nanopub/getting-started/setup), check if it is properly set by running `np profile` in your terminal. 6 | 7 | ## 👤 Use the default user profile 8 | 9 | If you have setup a profile on your machine following the [setup instructions](/nanopub/getting-started/setup), you can easily load the default profile (defined in `$HOME/.nanopub/profile.yml`): 10 | 11 | ```python 12 | from nanopub import load_profile 13 | 14 | p = load_profile() 15 | ``` 16 | 17 | ## ✍️ Define the user profile 18 | 19 | Otherwise, if you wish to have flexibility when defining the user profile, there are multiple options: 20 | 21 | ### Load a profile file 22 | 23 | Provide a specific path to a `profile.yml` file when using the `load_profile()` function: 24 | 25 | ```python 26 | from nanopub import load_profile 27 | 28 | p = load_profile(Path('/path/to/profile.yml')) 29 | ``` 30 | 31 | ### Provide the keys filepaths 32 | 33 | If you need to switch between multiple keys it can be convenient to be able to define the profile directly in your code, you can do so with the `Profile` class: 34 | 35 | ```python 36 | from pathlib import Path 37 | from nanopub import Profile 38 | 39 | p1 = Profile( 40 | name='Your Name', 41 | orcid_id='https://orcid.org/0000-0000-0000-0000', 42 | private_key=Path.home() / "id_rsa", 43 | public_key=Path.home() / "id_rsa.pub" 44 | ) 45 | ``` 46 | 47 | ### Provide the keys as strings 48 | 49 | If you need to switch between multiple keys you can also provide the private and public keys as string, without needing to store them in files: 50 | 51 | ```python 52 | from nanopub import Profile 53 | 54 | p = Profile( 55 | name='Your Name', 56 | orcid_id='https://orcid.org/0000-0000-0000-0000', 57 | private_key="YOUR_PRIVATE_KEY", 58 | public_key="YOUR_PUBLIC_KEY" 59 | ) 60 | ``` 61 | 62 | ### Generate new keys for your nanopub profile 63 | 64 | If you do not provide private and public keys a new key pair will be automatically generated. You can then store it where you want. 65 | 66 | ```python 67 | from nanopub import Profile 68 | 69 | p = Profile( 70 | name='Your Name', 71 | orcid_id='https://orcid.org/0000-0000-0000-0000', 72 | ) 73 | # By default the profile and keys will be stored in $HOME/.nanopub 74 | p.store() 75 | ``` 76 | -------------------------------------------------------------------------------- /docs/publishing/retraction.md: -------------------------------------------------------------------------------- 1 | # Retracting a nanopublication 2 | A nanopublication is persistent, you can never edit nor delete it. You can however retract a nanopublication. This is done by publishing a new nanopublication that states that you retract the original publication. You can use `NanopubClient.retract()`: 3 | ```python 4 | from nanopub import NanopubConf, NanopubRetract 5 | 6 | np_conf = NanopubConf(profile=load_profile(), use_test_server=True) 7 | 8 | np = NanopubRetract( 9 | 'http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ', 10 | np_conf, 11 | ) 12 | np.publish() 13 | ``` 14 | View the full retraction nanopublication [here](http://purl.org/np/RAv75Xhhz5jv--Nnu9RDqIGy2xHr74REGC4vtOSxrwX4c). 15 | 16 | The assertion states that the researcher (denoted by the ORCID iD from your profile) retracts the provided nanopublication: 17 | ```turtle 18 | @prefix npx: . 19 | @prefix sub: . 20 | 21 | sub:assertion { 22 | npx:retracts . 23 | } 24 | ``` 25 | By default nanopublications that have a valid retraction do not show up in search results. A valid retraction is a retraction that is signed with the same public key as the nanopublication that it retracts. 26 | 27 | ## Retracting a nanopublication that is not yours 28 | By default we do not retract nanopublications that are not yours (i.e. signed with another public key). If you try to do this it will trigger an AssertionError. 29 | 30 | We can use `force=True` to override this behavior: 31 | ```python 32 | np = NanopubRetract( 33 | 'http://purl.org/np/RAfk_zBYDerxd6ipfv8fAcQHEzgZcVylMTEkiLlMzsgwQ', 34 | np_conf, 35 | force=True 36 | ) 37 | ``` 38 | 39 | ## Find retractions of a given nanopublication 40 | You can find out whether a given publication is retracted and what the nanopublications are that retract it using `NanopubClient.find_retractions_of`: 41 | ```python 42 | from nanopub import NanopubClient 43 | client = NanopubClient(use_test_server=True) 44 | # This URI has 1 retraction: 45 | client.find_retractions_of('http://purl.org/np/RAirauh-vy5f7UJEMTm08C5bh5pnWD-abb-qk3fPYWCzc') 46 | ['http://purl.org/np/RADjlGIB8Vqt7NbG1kqzw-4aIV_k7nyIRirMhPKEYVSlc'] 47 | # This URI has no retractions 48 | client.find_retractions_of('http://purl.org/np/RAeMfoa6I05zoUmK6sRypCIy3wIpTgS8gkum7vdfOamn8') 49 | [] 50 | ``` 51 | -------------------------------------------------------------------------------- /docs/reference/client.md: -------------------------------------------------------------------------------- 1 | # NanopubClient 2 | 3 | ::: nanopub.NanopubClient 4 | -------------------------------------------------------------------------------- /docs/reference/client.rst: -------------------------------------------------------------------------------- 1 | nanopub.client 2 | ============== 3 | .. automodule:: nanopub.client 4 | :members: 5 | -------------------------------------------------------------------------------- /docs/reference/config.md: -------------------------------------------------------------------------------- 1 | # NanopubConf 2 | 3 | ::: nanopub.NanopubConf 4 | -------------------------------------------------------------------------------- /docs/reference/namespaces.md: -------------------------------------------------------------------------------- 1 | # Namespaces 2 | 3 | ::: nanopub.namespaces 4 | -------------------------------------------------------------------------------- /docs/reference/namespaces.rst: -------------------------------------------------------------------------------- 1 | nanopub.namespaces 2 | ================== 3 | 4 | .. automodule:: nanopub.namespaces 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/reference/nanopub.md: -------------------------------------------------------------------------------- 1 | # Nanopub 2 | 3 | ::: nanopub.Nanopub 4 | -------------------------------------------------------------------------------- /docs/reference/profile.md: -------------------------------------------------------------------------------- 1 | # Profile 2 | 3 | ::: nanopub.profile 4 | -------------------------------------------------------------------------------- /docs/reference/publication.rst: -------------------------------------------------------------------------------- 1 | nanopub.publication 2 | =================== 3 | 4 | .. automodule:: nanopub.publication 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/reference/templates.md: -------------------------------------------------------------------------------- 1 | # Nanopublications templates 2 | 3 | ::: nanopub.templates.nanopub_claim 4 | 5 | ::: nanopub.templates.nanopub_retract 6 | 7 | ::: nanopub.templates.nanopub_index 8 | 9 | ::: nanopub.templates.nanopub_introduction 10 | -------------------------------------------------------------------------------- /docs/searching/fetching.md: -------------------------------------------------------------------------------- 1 | # Fetching nanopublications 2 | ## Fetch from the default server 3 | 4 | You can fetch nanopublications from the default nanopub server using the `Nanopub` class. 5 | 6 | ```python 7 | from nanopub import Nanopub 8 | 9 | # Fetch the nanopublication at the specified URI 10 | np = Nanopub('http://purl.org/np/RApJG4fwj0szOMBMiYGmYvd5MCtRle6VbwkMJUb1SxxDM') 11 | 12 | # Print the RDF contents of the nanopublication 13 | print(np) 14 | 15 | # Iterate through all triples in the assertion graph 16 | for s, p, o in np.assertion: 17 | print(s, p, o) 18 | 19 | # Iterate through the publication info 20 | for s, p, o in np.pubinfo: 21 | print(s, p, o) 22 | 23 | # Iterate through the provenance graph 24 | for s, p, o in np.provenance: 25 | print(s,p,o) 26 | 27 | # See the concept that is introduced by this nanopublication (if any) 28 | print(np.introduces_concept) 29 | ``` 30 | 31 | ## Fetch from a specific server 32 | 33 | You can fetch Nanopubs from the test server: 34 | 35 | ```python 36 | from nanopub import Nanopub 37 | 38 | np = Nanopub( 39 | source_uri='http://purl.org/np/RANGY8fx_EYVeZzJOinH9FoY-WrQBerKKUy2J9RCDWH6U', 40 | conf=NanopubConf(use_test_server=True) 41 | ) 42 | print(np) 43 | ``` 44 | 45 | Or from a specific nanopub server: 46 | 47 | ```python 48 | np = Nanopub( 49 | source_uri='http://purl.org/np/RApJG4fwj0szOMBMiYGmYvd5MCtRle6VbwkMJUb1SxxDM', 50 | conf=NanopubConf(use_server='https://np.petapico.org') 51 | ) 52 | print(np) 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/searching/searching.md: -------------------------------------------------------------------------------- 1 | # Searching the nanopub server 2 | The `NanopubClient` provides methods for searching the nanopub server. It provides an (incomplete) mapping to [Nanopub Query endpoints](https://query.knowledgepixels.com/). 3 | 4 | ## Text search 5 | Search for all nanopublications containing some text using `NanopubClient.find_nanopubs_with_text()` 6 | ```python 7 | from nanopub import NanopubClient 8 | 9 | client = NanopubClient() 10 | results = client.find_nanopubs_with_text('fair') 11 | ``` 12 | 13 | ## Triple pattern search 14 | Search for nanopublications whose assertions contain triples that match a specific pattern. 15 | ```python 16 | from nanopub import NanopubClient 17 | 18 | client = NanopubClient() 19 | # Search for nanopublications whose assertions contain triples that are ```rdf:Statement```s. 20 | results = client.find_nanopubs_with_pattern( 21 | pred='http://www.w3.org/1999/02/22-rdf-syntax-ns#type', 22 | obj='http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement' 23 | ) 24 | ``` 25 | 26 | ## Search on introduced concept 27 | Search for any nanopublications that introduce a concept of the given type, that contain text with the given search term. 28 | ```python 29 | from nanopub import NanopubClient 30 | 31 | client = NanopubClient() 32 | # Search for nanopublications that introduce a concept that is a ```p-plan:Step```. 33 | results = client.find_things('http://purl.org/net/p-plan#Step') 34 | ``` 35 | 36 | ## Interpreting search results 37 | Each search method returns a generator of dicts depicting matching nanopublications. 38 | 39 | Each dict has the following key-value pairs: 40 | * `date`: The date and time the nanopublication was created. 41 | * `description`: A description of the nanopublication that was parsed from the nanopublication RDF. 42 | * `np`: The URI of the matching nanopublication. 43 | 44 | Example results (from `NanopubClient.find_nanopubs_with_text('fair')`): 45 | ```python 46 | print(list(results)) 47 | [{'date': '2020-05-01T08:05:25.575Z', 48 | 'description': 'The primary objective of the VODAN Implementation Network is ' 49 | 'to showcase the creation and deployment of FAIR data related ' 50 | 'to COVID-19', 51 | 'np': 'http://purl.org/np/RAdDKjIGPt_2mE9oJtB3YQX6wGGdCC8ZWpkxEIoHsxOjE'}, 52 | {'date': '2020-05-14T09:34:53.554Z', 53 | 'description': 'FAIR IN community', 54 | 'np': 'http://purl.org/np/RAPE0A-NrIZDeX3pvFJr0uHshocfXuUj8n_J3BkY0sMuU'}] 55 | ``` 56 | 57 | ## Returning retracted publications in search 58 | By default nanopublications that have a valid retraction do not show up in search results. A valid retraction is a retraction that is signed with the same public key as the nanopublication that it retracts. 59 | 60 | You can toggle this behavior with the `filter_retracted` parameter, here is an example with `NanopubClient.find_nanopubs_with_text`: 61 | 62 | ```python 63 | from nanopub import NanopubClient 64 | 65 | client = NanopubClient() 66 | # Search for nanopublications containing the text fair, also returning retracted publications. 67 | results = client.find_nanopubs_with_text('fair', filter_retracted=False) 68 | ``` 69 | 70 | ## Filtering search results for a particular publication key 71 | You can filter search results to publications that are signed with a specific publication key (effectively filtering on publications from a single author). 72 | 73 | You use the `pubkey` argument for that. Here is an example with `NanopubClient.find_nanopubs_with_text`: 74 | 75 | ```python 76 | from nanopub import NanopubClient, profile 77 | 78 | # Search for nanopublications containing the text 'test', 79 | # filtering on publications signed with my publication key. 80 | client = NanopubClient(use_test_server=True) 81 | my_public_key = profile.public_key 82 | results = client.find_nanopubs_with_text('test', pubkey=my_public_key) 83 | ``` 84 | -------------------------------------------------------------------------------- /nanopub/__init__.py: -------------------------------------------------------------------------------- 1 | from ._version import __version__ 2 | from .nanopub_conf import NanopubConf 3 | from .fdo_nanopub import FDONanopub 4 | from .fdo_metadata import FdoMetadata 5 | from .fdo_ops import create_fdo_nanopub_from_handle, validate_fdo_nanopub, retrieve_metadata_from_id, update_metadata 6 | from .client import NanopubClient 7 | from .profile import Profile, load_profile, generate_keyfiles 8 | from .nanopub import Nanopub 9 | from .templates.nanopub_index import NanopubIndex, create_nanopub_index 10 | from .templates.nanopub_introduction import NanopubIntroduction 11 | from .templates.nanopub_claim import NanopubClaim 12 | from .templates.nanopub_retract import NanopubRetract 13 | from .templates.nanopub_update import NanopubUpdate 14 | -------------------------------------------------------------------------------- /nanopub/_version.py: -------------------------------------------------------------------------------- 1 | __version__ = "2.0.1" 2 | -------------------------------------------------------------------------------- /nanopub/constants.py: -------------------------------------------------------------------------------- 1 | from rdflib import Namespace 2 | 3 | HDL = Namespace("https://hdl.handle.net/") 4 | 5 | FDO_PROFILE_HANDLE = '21.T11966/FdoProfile' 6 | FDO_DATA_REF_HANDLE = '21.T11966/06a6c27e3e2ef27779ec' -------------------------------------------------------------------------------- /nanopub/definitions.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | from rdflib import Namespace 4 | 5 | ROOT_FILEPATH = Path(__file__).parent.parent 6 | TESTS_FILEPATH = ROOT_FILEPATH / "tests" 7 | TEST_RESOURCES_FILEPATH = TESTS_FILEPATH / "resources" 8 | USER_CONFIG_DIR = Path.home() / ".nanopub" 9 | DEFAULT_PROFILE_PATH = USER_CONFIG_DIR / "profile.yml" 10 | 11 | TEST_NANOPUB_REGISTRY_URL = 'https://test.registry.knowledgepixels.com/np/' 12 | # List of servers: https://monitor.petapico.org/.csv 13 | NANOPUB_REGISTRY_URLS = [ 14 | 'https://registry.petapico.org/np/', 15 | 'https://registry.knowledgepixels.com/np/', 16 | 'https://registry.np.trustyuri.net/np/', 17 | ] 18 | NANOPUB_FETCH_FORMAT = "trig" 19 | 20 | DUMMY_NANOPUB_URI = "http://purl.org/nanopub/temp/np" 21 | DUMMY_NAMESPACE = Namespace(DUMMY_NANOPUB_URI + "/") 22 | DUMMY_URI = DUMMY_NAMESPACE[""] 23 | 24 | NP_TEMP_PREFIX = "http://purl.org/nanopub/temp/" 25 | NP_PREFIX = "https://w3id.org/np/" 26 | 27 | MAX_NP_PER_INDEX = 1100 28 | MAX_TRIPLES_PER_NANOPUB = 1200 29 | 30 | RSA_KEY_SIZE = 2048 31 | 32 | NANOPUB_QUERY_URLS = [ 33 | 'https://query.knowledgepixels.com/api/', 34 | 'https://query.petapico.org/api/', 35 | 'https://query.np.trustyuri.net/api/', 36 | ] 37 | TEST_NANOPUB_QUERY_URL = 'https://query.knowledgepixels.com/api/' # we don't yet have a test server for this 38 | -------------------------------------------------------------------------------- /nanopub/fdo_metadata.py: -------------------------------------------------------------------------------- 1 | from rdflib import Graph, URIRef, Literal 2 | from typing import Optional, Union 3 | from rdflib.namespace import RDFS 4 | from nanopub.namespaces import HDL, FDOF 5 | from nanopub.constants import FDO_PROFILE_HANDLE 6 | 7 | 8 | class FdoMetadata: 9 | """ 10 | EXPERIMENTAL: This class is experimental and may change or be removed in future versions. 11 | """ 12 | 13 | def __init__(self, nanopub: Optional[Graph] = None): 14 | self.id: Optional[str] = None 15 | self.tuples: dict[URIRef, Union[Literal, URIRef]] = {} 16 | 17 | if nanopub: 18 | for s, p, o in nanopub: 19 | if p == FDOF.hasFdoProfile and self.id is None: 20 | self.id = self.extract_handle(s) 21 | self.tuples[p] = o 22 | 23 | if self.id is None: 24 | raise ValueError("Missing required FDO profile statement") 25 | 26 | def extract_handle(self, subject: URIRef) -> str: 27 | return str(subject).split("/")[-1] 28 | 29 | def get_statements(self) -> list[tuple[URIRef, URIRef, Union[Literal, URIRef]]]: 30 | """ 31 | Returns the metadata as a list of RDF triples. 32 | """ 33 | if not self.id: 34 | raise ValueError("FDO ID is not set") 35 | subject = URIRef(f"https://hdl.handle.net/{self.id}") 36 | return [(subject, p, o) for p, o in self.tuples.items()] 37 | 38 | def get_graph(self) -> Graph: 39 | """ 40 | Returns the metadata as an rdflib.Graph. 41 | """ 42 | g = Graph() 43 | for s, p, o in self.get_statements(): 44 | g.add((s, p, o)) 45 | return g 46 | 47 | def get_profile(self) -> Optional[URIRef]: 48 | val = self.tuples.get(FDOF.hasFdoProfile) 49 | return URIRef(val) if val else None 50 | 51 | def get_label(self) -> Optional[str]: 52 | val = self.tuples.get(RDFS.label) 53 | return str(val) if val else None 54 | 55 | def get_id(self) -> Optional[str]: 56 | return self.id 57 | 58 | def set_id(self, handle: str) -> None: 59 | self.id = handle 60 | 61 | def set_label(self, label: str) -> None: 62 | self.tuples[RDFS.label] = Literal(label) 63 | 64 | def set_profile(self, uri: Union[str, URIRef]) -> None: 65 | self.tuples[FDOF.hasFdoProfile] = URIRef(uri) 66 | 67 | def set_property(self, predicate: Union[str, URIRef], value: Union[str, URIRef, Literal]) -> None: 68 | pred = URIRef(predicate) 69 | obj = URIRef(value) if isinstance(value, str) and value.startswith("http") else Literal(value) 70 | self.tuples[pred] = obj 71 | 72 | def copy(self) -> "FdoMetadata": 73 | new_md = FdoMetadata() 74 | new_md.id = self.id 75 | new_md.tuples = self.tuples.copy() 76 | return new_md 77 | -------------------------------------------------------------------------------- /nanopub/fdo_nanopub.py: -------------------------------------------------------------------------------- 1 | from .nanopub import Nanopub 2 | import rdflib 3 | from rdflib.namespace import RDF, RDFS, XSD 4 | from nanopub.namespaces import HDL, FDOF, NPX 5 | from nanopub.constants import FDO_PROFILE_HANDLE, FDO_DATA_REF_HANDLE 6 | 7 | def to_hdl_uri(value): 8 | if isinstance(value, rdflib.URIRef): 9 | return value 10 | elif isinstance(value, str) and not value.startswith('http'): 11 | return HDL[value] 12 | else: 13 | raise ValueError(f"Invalid value: {value}") 14 | 15 | class FDONanopub(Nanopub): 16 | """ 17 | EXPERIMENTAL: This class is experimental and may change or be removed in future versions. 18 | """ 19 | 20 | def __init__(self, fdo_id: rdflib.URIRef | str, label: str, fdo_profile: str = None, *args, **kwargs): 21 | super().__init__(*args, **kwargs) 22 | self.fdo_uri = to_hdl_uri(fdo_id) 23 | self.fdo_profile = fdo_profile 24 | self._init_core_fdo_triples(label) 25 | 26 | def _init_core_fdo_triples(self, label: str): 27 | self.assertion.add((self.fdo_uri, RDF.type, FDOF.FAIRDigitalObject)) 28 | self.assertion.add((self.fdo_uri, RDFS.label, rdflib.Literal(label))) 29 | self.assertion.add((self.fdo_uri, FDOF.hasMetadata, self.metadata.np_uri)) 30 | if self.fdo_profile: 31 | profile_uri = to_hdl_uri(self.fdo_profile) 32 | self.assertion.add((self.fdo_uri, FDOF.hasFdoProfile, profile_uri)) 33 | 34 | self.pubinfo.add((self.metadata.np_uri, RDFS.label, rdflib.Literal(f"FAIR Digital Object: {label}"))) 35 | self.pubinfo.add((self.metadata.np_uri, NPX.introduces, self.fdo_uri)) 36 | 37 | def add_fdo_profile(self, profile_uri: rdflib.URIRef): 38 | profile_uri = to_hdl_uri(profile_uri) 39 | self.assertion.add((self.fdo_uri, FDOF.hasFdoProfile, rdflib.Literal(profile_uri))) 40 | self.pubinfo.add((HDL[FDO_PROFILE_HANDLE], RDFS.label, rdflib.Literal("FdoProfile"))) 41 | 42 | def add_fdo_data_ref(self, data_ref: rdflib.Literal): 43 | target_uri = to_hdl_uri(data_ref) 44 | self.assertion.add((self.fdo_uri, FDOF.isMaterializedBy, target_uri)) 45 | self.pubinfo.add((HDL[FDO_DATA_REF_HANDLE], RDFS.label, rdflib.Literal("DataRef"))) 46 | 47 | def add_attribute(self, attr_HANDLE: rdflib.URIRef, value: rdflib.Literal): 48 | attr_HANDLE = to_hdl_uri(attr_HANDLE) 49 | self.assertion.add((self.fdo_uri, attr_HANDLE, rdflib.Literal(value))) 50 | 51 | def add_attribute_label(self, attr_HANDLE: rdflib.URIRef, label: str): 52 | attr_HANDLE = to_hdl_uri(attr_HANDLE) 53 | self.pubinfo.add((attr_HANDLE, RDFS.label, rdflib.Literal(label))) 54 | 55 | -------------------------------------------------------------------------------- /nanopub/namespaces.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module holds handy namespaces that are often used in nanopublications. 3 | """ 4 | from rdflib import Namespace 5 | 6 | NP = Namespace("http://www.nanopub.org/nschema#") 7 | """Nanopub namespace""" 8 | 9 | NPX = Namespace("http://purl.org/nanopub/x/") 10 | """Nanopub/x namespace""" 11 | 12 | NTEMPLATE = Namespace("https://w3id.org/np/o/ntemplate/") 13 | """Nanopub template namespace""" 14 | 15 | PROV = Namespace("http://www.w3.org/ns/prov#") 16 | """Provenance Ontogoly (PROV-O) namespace""" 17 | 18 | HYCL = Namespace("http://purl.org/petapico/o/hycl#") 19 | """HYCL namespace for claims and hypothesis""" 20 | 21 | ORCID = Namespace("https://orcid.org/") 22 | """ORCID namespace""" 23 | 24 | PAV = Namespace("http://purl.org/pav/") 25 | """Provenance And Versioning namespace""" 26 | 27 | PMID = Namespace("http://www.ncbi.nlm.nih.gov/pubmed/") 28 | """PubMed namespace""" 29 | 30 | HDL = Namespace("https://hdl.handle.net/") 31 | """Handle namespace""" 32 | 33 | FDOF = Namespace("https://w3id.org/fdof/ontology#") 34 | """FAIR Digital Object Framework namespace""" -------------------------------------------------------------------------------- /nanopub/nanopub_conf.py: -------------------------------------------------------------------------------- 1 | from dataclasses import asdict, dataclass 2 | from typing import Optional 3 | 4 | from nanopub.definitions import NANOPUB_REGISTRY_URLS 5 | from nanopub.profile import Profile 6 | 7 | 8 | @dataclass 9 | class NanopubConf: 10 | """Represents the configuration for nanopubs. 11 | 12 | Args: 13 | profile: Profile of the user publishing the nanopub 14 | use_test_server: A boolean to automatically use the test server 15 | use_server: The URL of the server that will be used to publish the nanopub 16 | add_prov_generated_time: add generated time to provenance 17 | add_pubinfo_generated_time: add generated time to pubinfo 18 | attribute_assertion_to_profile: bool 19 | attribute_publication_to_profile: bool 20 | assertion_attributed_to: Optional str 21 | publication_attributed_to: Optional str 22 | derived_from: Optional str 23 | """ 24 | 25 | profile: Optional[Profile] = None 26 | 27 | use_test_server: bool = False 28 | use_server: str = NANOPUB_REGISTRY_URLS[0] 29 | 30 | add_prov_generated_time: bool = False 31 | add_pubinfo_generated_time: bool = False 32 | 33 | attribute_assertion_to_profile: bool = False 34 | attribute_publication_to_profile: bool = False 35 | 36 | assertion_attributed_to: Optional[str] = None 37 | publication_attributed_to: Optional[str] = None 38 | 39 | derived_from: Optional[str] = None 40 | 41 | 42 | dict = asdict 43 | -------------------------------------------------------------------------------- /nanopub/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanopublication/nanopub-py/9482610f7463ca0b8e27fe6ea47fb3f4c185bf41/nanopub/py.typed -------------------------------------------------------------------------------- /nanopub/templates/__init__.py: -------------------------------------------------------------------------------- 1 | from .nanopub_claim import NanopubClaim 2 | from .nanopub_index import NanopubIndex, create_nanopub_index 3 | from .nanopub_introduction import NanopubIntroduction 4 | from .nanopub_retract import NanopubRetract 5 | from .nanopub_update import NanopubUpdate 6 | -------------------------------------------------------------------------------- /nanopub/templates/nanopub_claim.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | 3 | from rdflib import RDF, RDFS, Literal, URIRef 4 | 5 | from nanopub.namespaces import HYCL 6 | from nanopub.nanopub import Nanopub 7 | from nanopub.nanopub_conf import NanopubConf 8 | from nanopub.profile import ProfileError 9 | 10 | 11 | class NanopubClaim(Nanopub): 12 | """Quickly claim a statement. 13 | 14 | Constructs statement triples around the provided text following the Hypotheses and Claims 15 | Ontology (http://purl.org/petapico/o/hycl). 16 | 17 | Args: 18 | conf: config for the nanopub 19 | claim (str): the text of the statement, example: 'All cats are grey' 20 | """ 21 | 22 | def __init__( 23 | self, 24 | claim: str, 25 | conf: NanopubConf, 26 | ) -> None: 27 | conf = deepcopy(conf) 28 | conf.add_prov_generated_time = True 29 | conf.add_pubinfo_generated_time = True 30 | conf.attribute_publication_to_profile = True 31 | super().__init__( 32 | conf=conf, 33 | ) 34 | 35 | if not self.profile: 36 | raise ProfileError("No profile provided, cannot generate a Nanopub Claim") 37 | 38 | this_statement = self._metadata.namespace.claim 39 | # this_statement = BNode("mystatement") 40 | self.assertion.add((this_statement, RDF.type, HYCL.Statement)) 41 | self.assertion.add((this_statement, RDFS.label, Literal(claim))) 42 | 43 | orcid_id_uri = URIRef(self.profile.orcid_id) 44 | self.provenance.add((orcid_id_uri, HYCL.claims, this_statement)) 45 | -------------------------------------------------------------------------------- /nanopub/templates/nanopub_introduction.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | from typing import Optional 3 | 4 | from rdflib import Literal, URIRef 5 | from rdflib.namespace import FOAF 6 | 7 | from nanopub.namespaces import NPX 8 | from nanopub.nanopub import Nanopub 9 | from nanopub.nanopub_conf import NanopubConf 10 | from nanopub.profile import ProfileError 11 | 12 | 13 | class NanopubIntroduction(Nanopub): 14 | """Publish a Nanopub introduction to introduce a key pair for an ORCID 15 | 16 | Args: 17 | conf: config for the nanopub 18 | host: the service where the keypair are hosted 19 | """ 20 | 21 | def __init__( 22 | self, 23 | conf: NanopubConf, 24 | host: Optional[str] = None, 25 | ) -> None: 26 | conf = deepcopy(conf) 27 | conf.add_prov_generated_time = False 28 | conf.add_pubinfo_generated_time = True 29 | conf.attribute_publication_to_profile = True 30 | conf.attribute_assertion_to_profile = True 31 | super().__init__( 32 | conf=conf, 33 | ) 34 | if not self.profile: 35 | raise ProfileError("No profile provided, cannot generate a Nanopub Introduction") 36 | 37 | key_declaration = self._metadata.namespace.keyDeclaration 38 | orcid_node = URIRef(self.conf.profile.orcid_id) 39 | 40 | self.assertion.add((key_declaration, NPX.declaredBy, orcid_node)) 41 | self.assertion.add((key_declaration, NPX.hasAlgorithm, Literal("RSA"))) 42 | self.assertion.add((key_declaration, NPX.hasPublicKey, Literal(self.conf.profile.public_key))) 43 | self.assertion.add((orcid_node, FOAF.name, Literal(self.conf.profile.name))) 44 | if host: 45 | self.assertion.add((key_declaration, NPX.hasKeyLocation, URIRef(host))) 46 | -------------------------------------------------------------------------------- /nanopub/templates/nanopub_retract.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | 3 | from rdflib import URIRef 4 | 5 | from nanopub.namespaces import NPX 6 | from nanopub.nanopub import Nanopub 7 | from nanopub.nanopub_conf import NanopubConf 8 | from nanopub.profile import ProfileError 9 | from nanopub.utils import MalformedNanopubError 10 | 11 | 12 | class NanopubRetract(Nanopub): 13 | """Retract a nanopublication. 14 | 15 | Publish a retraction nanpublication that declares retraction of the nanopublication that 16 | corresponds to the 'uri' argument. 17 | 18 | Args: 19 | conf: config for the nanopub 20 | uri (str): The uri pointing to the to-be-retracted nanopublication 21 | force (bool): Toggle using force to retract, this will even retract the 22 | nanopublication if it is signed with a different public key than the one 23 | in the user profile. 24 | """ 25 | 26 | def __init__( 27 | self, 28 | conf: NanopubConf, 29 | uri: str, 30 | force: bool = False, 31 | ) -> None: 32 | conf = deepcopy(conf) 33 | conf.add_prov_generated_time = True 34 | conf.add_pubinfo_generated_time = True 35 | conf.attribute_publication_to_profile = True 36 | conf.attribute_assertion_to_profile = True 37 | super().__init__( 38 | conf=conf, 39 | ) 40 | if not self.profile: 41 | raise ProfileError("No profile provided, cannot generate a Nanopub to retract another nanopub") 42 | 43 | if not force: 44 | self._check_public_keys_match(uri) 45 | orcid_id = self.profile.orcid_id 46 | self.assertion.add( 47 | (URIRef(orcid_id), NPX.retracts, URIRef(uri)) 48 | ) 49 | 50 | 51 | def _check_public_keys_match(self, uri): 52 | """Check for matching public keys of a nanopublication with the profile. 53 | 54 | Raises: 55 | AssertionError: When the nanopublication is signed with a public key that does not 56 | match the public key in the profile 57 | """ 58 | np = Nanopub( 59 | uri, 60 | conf=NanopubConf( 61 | use_test_server=self._conf.use_test_server, 62 | use_server=self._conf.use_server, 63 | ) 64 | ) 65 | if np.metadata.public_key is None: 66 | raise MalformedNanopubError(f"Public key not found in the nanopub {np.source_uri}") 67 | if self._conf.profile.public_key is None: 68 | raise ValueError(f"Public key not found for profile {self._conf.profile.orcid_id}") 69 | if np.metadata.public_key != self._conf.profile.public_key is None: 70 | raise AssertionError( 71 | "The public key in your profile does not match the public key" 72 | "that the publication that you want to retract is signed with." 73 | ) 74 | -------------------------------------------------------------------------------- /nanopub/templates/nanopub_update.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | from pathlib import Path 3 | from typing import Union 4 | 5 | from rdflib import ConjunctiveGraph, Graph, URIRef 6 | 7 | from nanopub.namespaces import NPX 8 | from nanopub.nanopub import Nanopub 9 | from nanopub.nanopub_conf import NanopubConf 10 | from nanopub.profile import ProfileError 11 | from nanopub.utils import MalformedNanopubError 12 | 13 | 14 | # TODO: improve to better inherit from the nanopub we want to update 15 | class NanopubUpdate(Nanopub): 16 | """Update a nanopublication. 17 | 18 | Publish a retraction nanpublication that declares retraction of the nanopublication that 19 | corresponds to the 'uri' argument. 20 | 21 | Args: 22 | conf: config for the nanopub 23 | uri (str): The uri pointing to the to-be-retracted nanopublication 24 | force (bool): Toggle using force to retract, this will even retract the 25 | nanopublication if it is signed with a different public key than the one 26 | in the user profile. 27 | """ 28 | 29 | def __init__( 30 | self, 31 | conf: NanopubConf, 32 | uri: str, 33 | force: bool = False, 34 | assertion: Graph = Graph(), 35 | provenance: Graph = Graph(), 36 | pubinfo: Graph = Graph(), 37 | rdf: Union[ConjunctiveGraph, Path] = None, 38 | ) -> None: 39 | conf = deepcopy(conf) 40 | conf.add_prov_generated_time = True 41 | conf.add_pubinfo_generated_time = True 42 | conf.attribute_publication_to_profile = True 43 | conf.attribute_assertion_to_profile = True 44 | super().__init__( 45 | conf=conf, 46 | assertion=assertion, 47 | provenance=provenance, 48 | pubinfo=pubinfo, 49 | rdf=rdf, 50 | ) 51 | if not self.profile: 52 | raise ProfileError("No profile provided, cannot generate a Nanopub to retract another nanopub") 53 | 54 | if not force: 55 | self._check_public_keys_match(uri) 56 | 57 | self.pubinfo.add( 58 | (self._metadata.namespace[""], NPX.supersedes, URIRef(uri)) 59 | ) 60 | 61 | 62 | def _check_public_keys_match(self, uri): 63 | """Check for matching public keys of a nanopublication with the profile. 64 | 65 | Raises: 66 | AssertionError: When the nanopublication is signed with a public key that does not 67 | match the public key in the profile 68 | """ 69 | np = Nanopub( 70 | uri, 71 | conf=NanopubConf( 72 | use_test_server=self._conf.use_test_server, 73 | use_server=self._conf.use_server, 74 | ) 75 | ) 76 | if np.metadata.public_key is None: 77 | raise MalformedNanopubError(f"Public key not found in the nanopub {np.source_uri}") 78 | if self._conf.profile.public_key is None: 79 | raise ValueError(f"Public key not found for profile {self._conf.profile.orcid_id}") 80 | if np.metadata.public_key != self._conf.profile.public_key is None: 81 | raise AssertionError( 82 | "The public key in your profile does not match the public key" 83 | "that the publication that you want to update is signed with." 84 | ) 85 | -------------------------------------------------------------------------------- /nanopub/trustyuri/CheckFile.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import logging 3 | import sys 4 | 5 | from nanopub.trustyuri import ModuleDirectory, TrustyUriUtils 6 | from nanopub.trustyuri.TrustyUriResource import TrustyUriResource 7 | 8 | try: 9 | from urllib2 import urlopen 10 | except Exception: 11 | from urllib.request import urlopen 12 | 13 | 14 | def check(args): 15 | filename = args[0] 16 | 17 | tail = TrustyUriUtils.get_trustyuri_tail(filename) 18 | module_id = tail[:2] 19 | module = ModuleDirectory.get_module(module_id) 20 | try: 21 | content = codecs.open(filename, 'r', 'utf-8').read() 22 | except Exception: 23 | content = urlopen(filename).read() 24 | resource = TrustyUriResource(filename, content, tail) 25 | if module.has_correct_hash(resource): 26 | print("Correct hash: " + tail) 27 | else: 28 | print("*** INCORRECT HASH ***") 29 | 30 | 31 | if __name__ == "__main__": 32 | logging.basicConfig(level=logging.ERROR) 33 | args = sys.argv 34 | args.pop(0) 35 | check(args) 36 | -------------------------------------------------------------------------------- /nanopub/trustyuri/ModuleDirectory.py: -------------------------------------------------------------------------------- 1 | from nanopub.trustyuri.file.FileModule import FileModule 2 | from nanopub.trustyuri.rdf.RdfModule import RdfModule 3 | 4 | modules: dict = {} 5 | 6 | 7 | def add_module(module): 8 | modules[module.module_id()] = module 9 | 10 | 11 | def get_module(name): 12 | return modules[name] 13 | 14 | 15 | add_module(FileModule()) 16 | add_module(RdfModule()) 17 | -------------------------------------------------------------------------------- /nanopub/trustyuri/RunBatch.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import re 3 | import sys 4 | import time 5 | 6 | from nanopub.trustyuri.file import ProcessFile 7 | from nanopub.trustyuri.rdf import TransformRdf 8 | 9 | from . import CheckFile 10 | 11 | logging.basicConfig(level=logging.ERROR) 12 | 13 | filename = sys.argv[1] 14 | 15 | with open(filename) as f: 16 | for line in f: 17 | line = line.strip() 18 | if (re.match(r'^#|^$', line)): 19 | continue 20 | print("COMMAND: " + line) 21 | cmdargs = line.split(' ') 22 | cmd = cmdargs.pop(0) 23 | starttime = time.time() 24 | try: 25 | if (cmd == "CheckFile"): 26 | CheckFile.check(cmdargs) 27 | elif (cmd == "ProcessFile"): 28 | ProcessFile.process(cmdargs) 29 | elif (cmd == "TransformRdf"): 30 | TransformRdf.transform(cmdargs) 31 | else: 32 | print("ERROR: Unrecognized command %s" % cmd) 33 | exit(1) 34 | except Exception: 35 | print(sys.exc_info()[0]) 36 | t = time.time() - starttime 37 | print("Time in seconds: %g" % t) 38 | print("---") 39 | -------------------------------------------------------------------------------- /nanopub/trustyuri/TrustyUriModule.py: -------------------------------------------------------------------------------- 1 | class TrustyUriModule: 2 | def module_id(self): 3 | return "" 4 | def has_correct_hash(self, resource): 5 | return False 6 | -------------------------------------------------------------------------------- /nanopub/trustyuri/TrustyUriResource.py: -------------------------------------------------------------------------------- 1 | class TrustyUriResource: 2 | def __init__(self, filename, content, hashstr): 3 | self.filename = filename 4 | self.content = content 5 | self.hashstr = hashstr 6 | def get_filename(self): 7 | return self.filename 8 | def get_hashstr(self): 9 | return self.hashstr 10 | def get_content(self): 11 | return self.content 12 | -------------------------------------------------------------------------------- /nanopub/trustyuri/TrustyUriUtils.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import re 3 | 4 | 5 | def get_trustyuri_tail(s): 6 | if not re.search(r'(.*[^A-Za-z0-9\-_]|)[A-Za-z0-9\-_]{25,}(\.[A-Za-z0-9\-_]{0,20})?', s): 7 | return "" 8 | return re.sub(r'^(.*[^A-Za-z0-9\-_]|)([A-Za-z0-9\-_]{25,})(\.[A-Za-z0-9\-_]{0,20})?$', r'\2', s) 9 | 10 | 11 | def get_base64(s): 12 | return re.sub(r'=', '', base64.b64encode(s, b'-_').decode('utf-8')) 13 | -------------------------------------------------------------------------------- /nanopub/trustyuri/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanopublication/nanopub-py/9482610f7463ca0b8e27fe6ea47fb3f4c185bf41/nanopub/trustyuri/__init__.py -------------------------------------------------------------------------------- /nanopub/trustyuri/file/FileHasher.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | 3 | from nanopub.trustyuri import TrustyUriUtils 4 | 5 | 6 | def make_hash(content): 7 | try: 8 | return "FA" + TrustyUriUtils.get_base64(hashlib.sha256(content).digest()) 9 | except Exception: 10 | return "FA" + TrustyUriUtils.get_base64(hashlib.sha256(content.encode()).digest()) 11 | -------------------------------------------------------------------------------- /nanopub/trustyuri/file/FileModule.py: -------------------------------------------------------------------------------- 1 | from nanopub.trustyuri.file import FileHasher 2 | from nanopub.trustyuri.TrustyUriModule import TrustyUriModule 3 | 4 | 5 | class FileModule(TrustyUriModule): 6 | def module_id(self): 7 | return "FA" 8 | def has_correct_hash(self, resource): 9 | h = FileHasher.make_hash(resource.get_content()) 10 | return resource.get_hashstr() == h 11 | -------------------------------------------------------------------------------- /nanopub/trustyuri/file/ProcessFile.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import sys 4 | 5 | from nanopub.trustyuri.file import FileHasher 6 | 7 | 8 | def process(args): 9 | filename = args[0] 10 | 11 | with open(filename) as f: 12 | hashstr = FileHasher.make_hash(f.read()) 13 | ext = "" 14 | base = filename 15 | if re.search(r'.\.[A-Za-z0-9\-_]{0,20}$', filename): 16 | ext = re.sub(r'^(.*)(\.[A-Za-z0-9\-_]{0,20})$', r'\2', filename) 17 | base = re.sub(r'^(.*)(\.[A-Za-z0-9\-_]{0,20})$', r'\1', filename) 18 | os.rename(filename, base + "." + hashstr + ext) 19 | 20 | 21 | if __name__ == "__main__": 22 | args = sys.argv 23 | args.pop(0) 24 | process(args) 25 | -------------------------------------------------------------------------------- /nanopub/trustyuri/file/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanopublication/nanopub-py/9482610f7463ca0b8e27fe6ea47fb3f4c185bf41/nanopub/trustyuri/file/__init__.py -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/HashAdder.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from rdflib.term import URIRef 4 | 5 | 6 | def addhash(quads, hashstr): 7 | newquads = [] 8 | for q in quads: 9 | c = transform(q[0], hashstr) 10 | s = transform(q[1], hashstr) 11 | p = transform(q[2], hashstr) 12 | o = q[3] 13 | if isinstance(q[3], URIRef): 14 | o = transform(q[3], hashstr) 15 | newquads.append((c, s, p, o)) 16 | return newquads 17 | 18 | 19 | def transform(uri, hashstr): 20 | if uri is None: 21 | return None 22 | return URIRef(re.sub(" ", hashstr, str(uri))) 23 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/RdfHasher.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | import re 3 | from functools import cmp_to_key 4 | 5 | from rdflib.term import Literal 6 | 7 | from nanopub.trustyuri import TrustyUriUtils 8 | from nanopub.trustyuri.rdf.RdfPreprocessor import preprocess 9 | from nanopub.trustyuri.rdf.StatementComparator import StatementComparator 10 | from nanopub.utils import log 11 | 12 | 13 | def normalize_quads(quads, hashstr=None, baseuri=None): 14 | quads.sort() 15 | quads = preprocess(quads, hashstr=hashstr, baseuri=baseuri) 16 | comp = StatementComparator(hashstr) 17 | quads = sorted(quads, key=cmp_to_key(lambda q1, q2: comp.compare(q1, q2))) 18 | s = "" 19 | previous = "" 20 | for q in quads: 21 | e = "" 22 | e = e + str(value_to_string(q[0])) 23 | e = e + str(value_to_string(q[1])) 24 | e = e + str(value_to_string(q[2])) 25 | e = e + str(value_to_string(q[3])) 26 | if not e == previous: 27 | s = s + e 28 | previous = e 29 | log.debug(f"Normalized quads before signing/hashing:\n{s}") 30 | return s 31 | 32 | 33 | def make_hash(quads, hashstr=None, baseuri=None) -> str: 34 | s = normalize_quads(quads, hashstr, baseuri) 35 | 36 | # Uncomment next line to see what goes into the hash: 37 | # print("NORMALIZED QUADS IN MAKE_HASH\n" + s + "NORMALIZED QUADS IN MAKE_HASH\n") 38 | return "RA" + TrustyUriUtils.get_base64(hashlib.sha256(s.encode('utf-8')).digest()) 39 | 40 | 41 | def value_to_string(value) -> str: 42 | if value is None: 43 | return "\n" 44 | elif isinstance(value, Literal): 45 | if value.language is not None: 46 | # TODO: proper canonicalization of language tags 47 | return f"@{value.language.lower()} {escape(value)}\n" 48 | if value.datatype is not None: 49 | return f"^{value.datatype} {escape(value)}\n" 50 | return f"^http://www.w3.org/2001/XMLSchema#string {escape(value)}\n" 51 | else: 52 | return f"{str(value)}\n" 53 | 54 | 55 | def escape(s) -> str: 56 | return re.sub(r'\n', r'\\n', re.sub(r'\\', r'\\\\', str(s))) 57 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/RdfModule.py: -------------------------------------------------------------------------------- 1 | from rdflib.graph import ConjunctiveGraph 2 | 3 | from nanopub.trustyuri.rdf import RdfHasher, RdfUtils 4 | from nanopub.trustyuri.TrustyUriModule import TrustyUriModule 5 | 6 | 7 | class RdfModule(TrustyUriModule): 8 | def module_id(self): 9 | return "RA" 10 | def has_correct_hash(self, resource): 11 | f = RdfUtils.get_format(resource.get_filename()) 12 | cg = ConjunctiveGraph() 13 | cg.parse(data=resource.get_content(), format=f) 14 | quads = RdfUtils.get_quads(cg) 15 | h = RdfHasher.make_hash(quads, resource.get_hashstr()) 16 | return resource.get_hashstr() == h 17 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/RdfPreprocessor.py: -------------------------------------------------------------------------------- 1 | from rdflib.term import BNode, URIRef 2 | 3 | from nanopub.trustyuri.rdf import RdfUtils 4 | 5 | 6 | def preprocess(quads, hashstr=None, baseuri=None): 7 | newquads = [] 8 | bnodemap = {} 9 | for q in quads: 10 | c = transform(q[0], hashstr, baseuri, bnodemap) 11 | s = transform(q[1], hashstr, baseuri, bnodemap) 12 | p = transform(q[2], hashstr, baseuri, bnodemap) 13 | o = q[3] 14 | if isinstance(q[3], URIRef) or isinstance(q[3], BNode): 15 | o = transform(q[3], hashstr, baseuri, bnodemap) 16 | newquads.append((c, s, p, o)) 17 | return newquads 18 | 19 | 20 | def transform(uri, hashstr, baseuri, bnodemap): 21 | if uri is None: 22 | return None 23 | 24 | if baseuri is None: 25 | try: 26 | return URIRef(RdfUtils.normalize(uri, hashstr).decode('utf-8')) 27 | except Exception: 28 | return URIRef(RdfUtils.normalize(uri, hashstr)) 29 | return RdfUtils.get_trustyuri(uri, baseuri, hashstr, bnodemap) 30 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/RdfTransformer.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | 4 | from nanopub.trustyuri.rdf import HashAdder, RdfHasher, RdfPreprocessor, RdfUtils 5 | 6 | 7 | def transform_to_file(conjgraph, baseuri, outdir, filename): 8 | quads = RdfUtils.get_quads(conjgraph) 9 | quads = RdfPreprocessor.preprocess(quads, baseuri=baseuri) 10 | hashstr = RdfHasher.make_hash(quads) 11 | quads = HashAdder.addhash(quads, hashstr) 12 | conjgraph = RdfUtils.get_conjunctivegraph(quads) 13 | name = "" 14 | if (baseuri is not None) and re.match('.*/.*', str(baseuri)): 15 | name = re.sub(r'^.*[^A-Za-z0-9.\-_]([A-Za-z0-9.\-_]*)$', r'\1', str(baseuri)) + "." 16 | ext = os.path.splitext(filename)[1] 17 | rdfFormat = RdfUtils.get_format(filename) 18 | conjgraph.serialize(outdir + "/" + name + hashstr + ext, format=rdfFormat) 19 | return RdfUtils.get_trustyuri(baseuri, baseuri, hashstr, None) 20 | 21 | 22 | def transform_to_string(conjgraph, baseuri): 23 | quads = RdfUtils.get_quads(conjgraph) 24 | quads = RdfPreprocessor.preprocess(quads, baseuri=baseuri) 25 | hashstr = RdfHasher.make_hash(quads) 26 | quads = HashAdder.addhash(quads, hashstr) 27 | conjgraph = RdfUtils.get_conjunctivegraph(quads) 28 | return conjgraph.serialize(format='trix') 29 | 30 | 31 | def transform(conjgraph, baseuri): 32 | quads = RdfUtils.get_quads(conjgraph) 33 | quads = RdfPreprocessor.preprocess(quads, baseuri=baseuri) 34 | hashstr = RdfHasher.make_hash(quads) 35 | quads = HashAdder.addhash(quads, hashstr) 36 | return RdfUtils.get_conjunctivegraph(quads) 37 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/RdfUtils.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from rdflib.graph import ConjunctiveGraph, Graph 4 | from rdflib.term import BNode, URIRef 5 | from rdflib.util import guess_format 6 | 7 | from nanopub.definitions import NP_PREFIX, NP_TEMP_PREFIX 8 | 9 | 10 | def get_trustyuri(resource, baseuri, hashstr, bnodemap): 11 | """Most of the work done to normalize URIs happens here""" 12 | if resource is None: 13 | return None 14 | np_uri = get_str(baseuri).decode('utf-8') 15 | # baseuri passed is the np namespace, np_uri is the nanopub URI without trailing # or / 16 | if np_uri.endswith('#') or np_uri.endswith('/'): 17 | np_uri = np_uri[:-1] 18 | # Extract the trusty artefact if present, or remove the trailing / if trusty not present 19 | prefix = "/".join(baseuri.split('/')[:-1]) + '/' 20 | if str(baseuri).startswith(NP_TEMP_PREFIX): 21 | prefix = NP_PREFIX 22 | if isinstance(resource, URIRef): 23 | suffix = get_suffix(resource, baseuri) 24 | if get_str(resource).decode('utf-8') == np_uri: 25 | return str(f"{prefix}{hashstr}") 26 | if suffix is None and not get_str(resource).decode('utf-8') == get_str(baseuri).decode('utf-8'): 27 | return str(resource) 28 | if suffix is None or suffix == "": 29 | return str(f"{prefix}{hashstr}") 30 | return str(f"{prefix}{hashstr}/{suffix}") 31 | if isinstance(resource, BNode): 32 | # NOTE: bnodes are replaced in nanopub.py by _replace_blank_nodes() most of the time 33 | bnode_unnamed = re.match(r'^[a-zA-Z0-9]{33}$', str(resource)) 34 | # Check if BNode in the form of N2b80343001e94f48bdee0901be566ebb 35 | # Which means it was automatically generated by rdflib: we use a number in this case 36 | if bnode_unnamed: 37 | n = get_bnode_number(resource, bnodemap) 38 | np_uri = str(f"{prefix}{hashstr}") 39 | return str(np_uri + "#_" + str(n)) 40 | else: 41 | # If the user gave a specific name to the bnode with rdflib 42 | return str(f"{prefix}{hashstr}" + "#_" + str(resource)) 43 | else: 44 | return None 45 | 46 | 47 | def get_suffix(plainuri, baseuri): 48 | p = get_str(plainuri) 49 | b = get_str(baseuri) 50 | if (p == b): 51 | return None 52 | if (p.startswith(b)): 53 | return p[len(b):].decode('utf-8') 54 | return None 55 | 56 | 57 | def normalize(uri, hashstr): 58 | if hashstr is None: 59 | return get_str(uri) 60 | try: 61 | return re.sub(hashstr, " ", str(uri)) 62 | except Exception: 63 | return re.sub(hashstr.decode('utf-8'), " ", str(uri)) 64 | 65 | 66 | def get_bnode_number(bnode, bnodemap): 67 | i = get_str(bnode) 68 | if i not in bnodemap.keys(): 69 | n = len(bnodemap) + 1 70 | bnodemap[i] = n 71 | return bnodemap[i] 72 | 73 | 74 | def expand_baseuri(baseuri): 75 | s = get_str(baseuri).decode('utf-8') 76 | if re.match(r'.*[A-Za-z0-9\-_]', s): 77 | s = s + "." 78 | return s 79 | 80 | 81 | def get_quads(conjunctivegraph): 82 | quads = [] 83 | for s, p, o, c in conjunctivegraph.quads((None, None, None)): 84 | g = c.identifier 85 | if not isinstance(g, URIRef): 86 | g = None 87 | quads.append((g, s, p, o)) 88 | quads.sort() 89 | return quads 90 | 91 | 92 | def get_conjunctivegraph(quads): 93 | cg = ConjunctiveGraph() 94 | # for (c, s, p, o) in quads: 95 | # cg.default_context = Graph(store=cg.store, identifier=c) 96 | # cg.add((s, p, o)) 97 | cg.addN([(s, p, o, Graph(store=cg.store, identifier=c)) for (c, s, p, o) in quads]) 98 | return cg 99 | 100 | 101 | def get_format(filename): 102 | return guess_format(filename, {'xml': 'trix', 'ttl': 'turtle', 'nq': 'nquads', 'nt': 'nt', 'rdf': 'xml'}) 103 | 104 | 105 | def get_str(s): 106 | return s.encode('utf-8') 107 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/StatementComparator.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from rdflib.term import Literal 4 | 5 | 6 | class StatementComparator: 7 | def __init__(self, hashstr=None): 8 | self.hashstr = hashstr 9 | 10 | def compare(self, q1, q2): 11 | c = self.compare_context(q1, q2) 12 | if not c == 0: 13 | return c 14 | c = self.compare_subject(q1, q2) 15 | if not c == 0: 16 | return c 17 | c = self.compare_predicate(q1, q2) 18 | if not c == 0: 19 | return c 20 | return self.compare_object(q1, q2) 21 | 22 | def compare_context(self, q1, q2): 23 | r1 = q1[0] 24 | r2 = q2[0] 25 | if (r1 is None) and (r2 is None): 26 | return 0 27 | if (r1 is None) and (r2 is not None): 28 | return -1 29 | if (r1 is not None) and (r2 is None): 30 | return 1 31 | return self.compare_uri(r1, r2) 32 | 33 | def compare_subject(self, q1, q2): 34 | return self.compare_uri(q1[1], q2[1]) 35 | 36 | def compare_predicate(self, q1, q2): 37 | return self.compare_uri(q1[2], q2[2]) 38 | 39 | def compare_object(self, q1, q2): 40 | r1 = q1[3] 41 | r2 = q2[3] 42 | if isinstance(r1, Literal) and not isinstance(r2, Literal): 43 | return 1 44 | if not isinstance(r1, Literal) and isinstance(r2, Literal): 45 | return -1 46 | if isinstance(r1, Literal): 47 | return self.compare_literal(r1, r2) 48 | else: 49 | return self.compare_uri(r1, r2) 50 | 51 | def compare_literal(self, l1, l2): 52 | x1 = l1.encode('utf-8') 53 | x2 = l2.encode('utf-8') 54 | if (x1 < x2): 55 | return -1 56 | if (x1 > x2): 57 | return 1 58 | x1 = l1.datatype 59 | if (l1.language is not None): 60 | x1 = None 61 | if (l1.language is None and x1 is None): 62 | x1 = 'http://www.w3.org/2001/XMLSchema#string' 63 | x2 = l2.datatype 64 | if (l2.language is not None): 65 | x2 = None 66 | if (l2.language is None and x2 is None): 67 | x2 = 'http://www.w3.org/2001/XMLSchema#string' 68 | if (x1 is None) and (x2 is not None): 69 | return -1 70 | if (x1 is not None) and (x2 is None): 71 | return 1 72 | if (x1 is not None) and (x1 < x2): 73 | return -1 74 | if (x1 is not None) and (x1 > x2): 75 | return 1 76 | x1 = l1.language 77 | x2 = l2.language 78 | if (x1 is None) and (x2 is not None): 79 | return -1 80 | if (x1 is not None) and (x2 is None): 81 | return 1 82 | if (x1 is not None) and (x1 < x2): 83 | return -1 84 | if (x1 is not None) and (x1 > x2): 85 | return 1 86 | return 0 87 | 88 | def compare_uri(self, r1, r2): 89 | s1 = r1.encode('utf-8') 90 | s2 = r2.encode('utf-8') 91 | p1 = s1 92 | p2 = s2 93 | if self.hashstr is not None: 94 | try: 95 | p1 = re.sub(self.hashstr, ' ', s1) 96 | except Exception: 97 | p1 = re.sub(self.hashstr, ' ', r1) 98 | try: 99 | p2 = re.sub(self.hashstr, ' ', s2) 100 | except Exception: 101 | p2 = re.sub(self.hashstr, ' ', r2) 102 | if p1 < p2: 103 | return -1 104 | if p1 == p2: 105 | return 0 106 | return 1 107 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/TransformRdf.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | import sys 4 | 5 | from rdflib.graph import ConjunctiveGraph 6 | from rdflib.term import URIRef 7 | 8 | from nanopub.trustyuri.rdf import RdfTransformer, RdfUtils 9 | 10 | 11 | def transform(args): 12 | filename = args[0] 13 | baseuristr = args[1] 14 | 15 | with open(filename) as f: 16 | rdfFormat = RdfUtils.get_format(filename) 17 | cg = ConjunctiveGraph() 18 | cg.parse(data=f.read(), format=rdfFormat) 19 | baseuri = URIRef(baseuristr) 20 | outdir = os.path.abspath(os.path.join(str(filename), os.pardir)) 21 | RdfTransformer.transform_to_file(cg, baseuri, outdir, filename) 22 | 23 | 24 | if __name__ == "__main__": 25 | logging.basicConfig(level=logging.ERROR) 26 | args = sys.argv 27 | args.pop(0) 28 | transform(args) 29 | -------------------------------------------------------------------------------- /nanopub/trustyuri/rdf/__init__.py: -------------------------------------------------------------------------------- 1 | import rdflib 2 | 3 | rdflib.NORMALIZE_LITERALS = False 4 | -------------------------------------------------------------------------------- /nanopub/utils.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import re 3 | from dataclasses import asdict, dataclass 4 | from typing import Any, Optional 5 | 6 | from rdflib import ConjunctiveGraph, Namespace, URIRef 7 | 8 | from nanopub.definitions import DUMMY_NAMESPACE, DUMMY_URI 9 | 10 | log = logging.getLogger() 11 | 12 | 13 | class MalformedNanopubError(ValueError): 14 | """Error to be raised if a Nanopub is not formed correctly.""" 15 | 16 | 17 | @dataclass 18 | class NanopubMetadata: 19 | """Represents the different URIs and namespace used for a nanopub.""" 20 | 21 | namespace: Namespace = DUMMY_NAMESPACE 22 | np_uri: URIRef = DUMMY_URI 23 | 24 | head: URIRef = DUMMY_NAMESPACE["Head"] 25 | assertion: URIRef = DUMMY_NAMESPACE["assertion"] 26 | provenance: URIRef = DUMMY_NAMESPACE["provenance"] 27 | pubinfo: URIRef = DUMMY_NAMESPACE["pubinfo"] 28 | 29 | sig_uri: URIRef = DUMMY_NAMESPACE["sig"] 30 | signature: Optional[str] = None 31 | public_key: Optional[str] = None 32 | algorithm: Optional[str] = None 33 | 34 | trusty: Optional[str] = None 35 | 36 | dict = asdict 37 | 38 | 39 | def extract_np_metadata(g: ConjunctiveGraph) -> NanopubMetadata: 40 | """Extract a nanopub URI, namespace and head/assertion/prov/pubinfo contexts from a Graph""" 41 | get_np_query = """prefix np: 42 | 43 | SELECT DISTINCT ?np ?head ?assertion ?provenance ?pubinfo ?sigUri ?signature ?pubkey ?algo 44 | WHERE { 45 | GRAPH ?head { 46 | ?np a np:Nanopublication ; 47 | np:hasAssertion ?assertion ; 48 | np:hasProvenance ?provenance ; 49 | np:hasPublicationInfo ?pubinfo . 50 | } 51 | GRAPH ?pubinfo { 52 | OPTIONAL { 53 | ?sigUri npx:hasSignatureTarget ?np ; 54 | npx:hasPublicKey ?pubkey ; 55 | npx:hasAlgorithm ?algo ; 56 | npx:hasSignature ?signature . 57 | } 58 | } 59 | } 60 | """ 61 | qres: Any = g.query(get_np_query) 62 | if len(qres) < 1: 63 | raise MalformedNanopubError( 64 | "\033[1mNo nanopublication\033[0m has been found in the provided RDF. " 65 | "It should contain a np:Nanopublication object in a Head graph, pointing to 3 graphs: assertion, provenance and pubinfo" 66 | ) 67 | if len(qres) > 1: 68 | np_found: list = [] 69 | for row in qres: 70 | np_found.append(row.np) 71 | raise MalformedNanopubError( 72 | f"\033[1mMultiple nanopublications\033[0m are defined in this graph: {', '.join(np_found)}. " 73 | "The Nanopub object can only handles 1 nanopublication at a time" 74 | ) 75 | np_meta = NanopubMetadata() 76 | for row in qres: 77 | np_meta.head = row.head 78 | np_meta.assertion = row.assertion 79 | np_meta.provenance = row.provenance 80 | np_meta.pubinfo = row.pubinfo 81 | np_meta.np_uri = row.np 82 | np_meta.sig_uri = row.sigUri 83 | np_meta.signature = row.signature 84 | np_meta.public_key = row.pubkey 85 | np_meta.algorithm = row.algo 86 | 87 | # Check if the nanopub URI has a trusty artefact: 88 | separator_char = '/' 89 | # Regex to extract base URI, separator and trusty URI (if any) 90 | extract_trusty = re.search(r'^(.*?)(\/|#)?(RA.*)?$', str(np_meta.np_uri)) 91 | if extract_trusty: 92 | base_uri = extract_trusty.group(1) 93 | if extract_trusty.group(2): 94 | separator_char = extract_trusty.group(2) 95 | np_meta.namespace = Namespace(base_uri + separator_char) 96 | 97 | if extract_trusty.group(3): 98 | np_meta.trusty = extract_trusty.group(3) 99 | # TODO: improve as the signed np namespace might be using / or # or . 100 | np_meta.namespace = Namespace(np_meta.np_uri + '#') 101 | 102 | return np_meta 103 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "nanopub" 7 | description = "Python client for Nanopublications" 8 | readme = "README.md" 9 | requires-python = ">=3.7" 10 | license = { file = "LICENSE" } 11 | authors = [ 12 | { name = "Robin Richardson", email = "r.richardson@esciencecenter.nl" }, 13 | { name = "Djura Smits" }, 14 | { name = "Sven van den Burg" }, 15 | { name = "Vincent Emonet", email = "vincent.emonet@gmail.com" }, 16 | ] 17 | keywords = [ 18 | "Nanopublication", 19 | "RDF", 20 | "Linked Data", 21 | "Publishing" 22 | ] 23 | classifiers = [ 24 | "License :: OSI Approved :: Apache Software License", 25 | "Operating System :: OS Independent", 26 | "Programming Language :: Python :: 3", 27 | "Programming Language :: Python :: 3.7", 28 | "Programming Language :: Python :: 3.8", 29 | "Programming Language :: Python :: 3.9", 30 | "Programming Language :: Python :: 3.10", 31 | ] 32 | dynamic = ["version"] 33 | 34 | dependencies = [ 35 | "rdflib >=6.0.2", 36 | "requests", 37 | "typer", 38 | "yatiml", 39 | "pycryptodome >=3.15.0", 40 | ] 41 | 42 | [project.optional-dependencies] 43 | test = [ 44 | "pytest >=7.1.3", 45 | "pytest-cov >=3.0.0", 46 | "coveralls", 47 | "mypy >=0.991", 48 | "isort >=5.11.0", 49 | "flake8 >=5.0.0", 50 | "Flake8-pyproject >=1.2.2", 51 | "flaky", 52 | ] 53 | doc = [ 54 | "mkdocs >=1.4.2", 55 | "mkdocs-material >=8.2.7", 56 | "mkdocstrings[python] >=0.19.1", 57 | "mdx-include >=1.4.1", 58 | "mkdocs-markdownextradata-plugin >=0.2.5", 59 | ] 60 | dev = [ 61 | "pre-commit >=2.17.0,<3.0.0", 62 | "autoflake >=1.4.0,<2.0.0", 63 | "jupyter", 64 | "notebook", 65 | "types-requests", 66 | ] 67 | 68 | 69 | [project.scripts] 70 | np = "nanopub.__main__:cli" 71 | 72 | 73 | [project.urls] 74 | Homepage = "https://fair-workflows.github.io/nanopub" 75 | Documentation = "https://fair-workflows.github.io/nanopub" 76 | History = "https://github.com/fair-workflows/nanopub/releases" 77 | Tracker = "https://github.com/fair-workflows/nanopub/issues" 78 | Source = "https://github.com/fair-workflows/nanopub" 79 | 80 | 81 | 82 | # ENVIRONMENTS AND SCRIPTS 83 | [tool.hatch.envs.default] 84 | features = [ 85 | "test", 86 | "doc", 87 | "dev", 88 | ] 89 | post-install-commands = [ 90 | "pre-commit install", 91 | ] 92 | 93 | [tool.hatch.envs.default.scripts] 94 | dev = "./scripts/dev.sh" 95 | test = "./scripts/test.sh {args}" 96 | docs = "./scripts/docs.sh {args}" 97 | format = "./scripts/format.sh" 98 | lint = "./scripts/lint.sh" 99 | 100 | 101 | # TOOLS 102 | [tool.hatch.version] 103 | path = "nanopub/_version.py" 104 | 105 | 106 | [tool.isort] 107 | line_length = 120 108 | skip = ["nanopub/__init__.py"] 109 | profile = "black" 110 | 111 | 112 | [tool.coverage.run] 113 | source = ["nanopub"] 114 | branch = true 115 | 116 | [tool.coverage.report] 117 | omit = ["nanopub/trustyuri/*", "tests/*"] 118 | 119 | 120 | [tool.flake8] 121 | max-complexity = 17 122 | max-line-length = 120 123 | per-file-ignores = [ 124 | "__init__.py:F401", 125 | ] 126 | ignore = [ 127 | "E501", # line too long 128 | "E303", # too many blank lines 129 | "E301", # expected 1 blank lines found 0 130 | "W503", # line break before binary operator 131 | ] 132 | 133 | 134 | [tool.mypy] 135 | strict = false 136 | implicit_reexport = true 137 | follow_imports = "normal" 138 | ignore_missing_imports = true 139 | pretty = true 140 | show_column_numbers = true 141 | warn_no_return = true 142 | warn_unused_ignores = false 143 | warn_redundant_casts = true 144 | disallow_untyped_defs = false 145 | no_implicit_optional = false 146 | 147 | 148 | [tool.pytest.ini_options] 149 | markers = [ 150 | "no_rsa_key: mark a test as a test only run when there is no nanopub RSA key setup.", 151 | ] 152 | -------------------------------------------------------------------------------- /scripts/all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | bash ./scripts/format.sh 7 | 8 | bash ./scripts/lint.sh 9 | 10 | bash ./scripts/test.sh 11 | -------------------------------------------------------------------------------- /scripts/dev.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from rdflib import Graph, Literal, URIRef 4 | 5 | from nanopub import Nanopub, NanopubConf, load_profile, namespaces 6 | 7 | log = logging.getLogger() 8 | log.setLevel(logging.INFO) 9 | console_handler = logging.StreamHandler() 10 | formatter = logging.Formatter( 11 | "%(asctime)s %(levelname)s: [%(module)s:%(funcName)s] %(message)s" 12 | ) 13 | console_handler.setFormatter(formatter) 14 | log.addHandler(console_handler) 15 | 16 | 17 | conf = NanopubConf( 18 | add_prov_generated_time=False, 19 | add_pubinfo_generated_time=True, 20 | attribute_assertion_to_profile=True, 21 | attribute_publication_to_profile=True, 22 | profile=load_profile(), 23 | # use_test_server=True, 24 | ) 25 | 26 | assertion = Graph() 27 | assertion.add(( 28 | URIRef('http://test'), namespaces.HYCL.claims, Literal('This is a test for the nanopub python library') 29 | )) 30 | 31 | np = Nanopub(conf=conf, assertion=assertion) 32 | 33 | np.sign() 34 | # np.publish() 35 | print(np) 36 | -------------------------------------------------------------------------------- /scripts/dev.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | clear 6 | python scripts/dev.py 7 | -------------------------------------------------------------------------------- /scripts/docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | mkdocs serve -a localhost:8001 ${@} 6 | -------------------------------------------------------------------------------- /scripts/format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | set -x 3 | 4 | autoflake --remove-all-unused-imports --recursive --remove-unused-variables --in-place nanopub tests --exclude=__init__.py 5 | isort nanopub tests 6 | pre-commit run --all-files || true 7 | 8 | # black nanopub tests 9 | -------------------------------------------------------------------------------- /scripts/html-cov-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | bash scripts/test.sh --cov-report=html ${@} 7 | 8 | python -m webbrowser ./htmlcov/index.html 9 | -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | echo "Make sure you use a virtual environment when working in development:" 6 | echo "python -m venv .venv" 7 | echo "source .venv/bin/activate" 8 | echo 9 | read -p "Hit [Enter] to continue, or [Ctrl+C] to cancel" -n 1 -r 10 | echo 11 | 12 | pip install -e ".[dev,test,doc]" 13 | 14 | pre-commit install 15 | -------------------------------------------------------------------------------- /scripts/lint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -x 5 | 6 | isort nanopub tests --check-only 7 | flake8 nanopub tests 8 | mypy nanopub 9 | -------------------------------------------------------------------------------- /scripts/nanopub-java: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | function download-nanopub-jar { 6 | mkdir -p $LIBDIR 7 | # echo "Getting latest nanopub version..." 8 | # NANOPUB_LATEST_LOCATION=$( 9 | # curl --head -s https://github.com/Nanopublication/nanopub-java/releases/latest \ 10 | # | egrep -i '^location:' 11 | # ) 12 | # NANOPUB_VERSION=${NANOPUB_LATEST_LOCATION##*-} 13 | # NANOPUB_VERSION="${NANOPUB_VERSION%"${NANOPUB_VERSION##*[![:space:]]}"}" 14 | NANOPUB_VERSION=1.47 15 | echo "Downloading nanopub jar file version $NANOPUB_VERSION in $LIBDIR/nanopub-${NANOPUB_VERSION}-jar-with-dependencies.jar" 16 | curl -L --output "$LIBDIR/nanopub-${NANOPUB_VERSION}-jar-with-dependencies.jar" "https://github.com/Nanopublication/nanopub-java/releases/download/nanopub-${NANOPUB_VERSION}/nanopub-${NANOPUB_VERSION}-jar-with-dependencies.jar" 17 | } 18 | 19 | WORKINGDIR=`pwd` 20 | LIBDIR="$WORKINGDIR/lib" 21 | 22 | NANOPUBJAR=$(find $LIBDIR -maxdepth 1 -name "nanopub-*-jar-with-dependencies.jar" 2>/dev/null | sort -n | tail -1) 23 | 24 | if [ -z "$NANOPUBJAR" ]; then 25 | download-nanopub-jar 26 | NANOPUBJAR=$(find $LIBDIR -maxdepth 1 -name "nanopub-*-jar-with-dependencies.jar" 2>/dev/null | sort -n | tail -1) 27 | fi 28 | 29 | if [ ! -z "$NANOPUBJAR" ]; then 30 | exec java -Dsun.jnu.encoding=utf8 -Duser.language=en -Duser.country=US -Dfile.encoding=utf8 -jar $NANOPUBJAR "$@" 31 | fi 32 | 33 | echo "ERROR: Failed to find nanopub jar file." 34 | exit 1 35 | -------------------------------------------------------------------------------- /scripts/nanopub-java.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem nanopub-java startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | echo FOR THE TESTS TO WORK DOWNLOAD THE NANOPUB JAR AT https://github.com/Nanopublication/nanopub-java/releases/latest and place it in a lib/ folder to create in the root of the repository 12 | 13 | set DIRNAME=%~dp0 14 | if "%DIRNAME%" == "" set DIRNAME=. 15 | set APP_BASE_NAME=%~n0 16 | set APP_HOME=%DIRNAME%.. 17 | 18 | @rem Find java.exe 19 | if defined JAVA_HOME goto findJavaFromJavaHome 20 | 21 | set JAVA_EXE=java.exe 22 | %JAVA_EXE% -version >NUL 2>&1 23 | if "%ERRORLEVEL%" == "0" goto init 24 | 25 | echo. 26 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 27 | echo. 28 | echo Please set the JAVA_HOME variable in your environment to match the 29 | echo location of your Java installation. 30 | 31 | goto fail 32 | 33 | :findJavaFromJavaHome 34 | set JAVA_HOME=%JAVA_HOME:"=% 35 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 36 | 37 | if exist "%JAVA_EXE%" goto init 38 | 39 | echo. 40 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 41 | echo. 42 | echo Please set the JAVA_HOME variable in your environment to match the 43 | echo location of your Java installation. 44 | 45 | goto fail 46 | 47 | :init 48 | @rem Get command-line arguments, handling Windows variants 49 | 50 | if not "%OS%" == "Windows_NT" goto win9xME_args 51 | 52 | :win9xME_args 53 | @rem Slurp the command line arguments. 54 | set CMD_LINE_ARGS= 55 | set _SKIP=2 56 | 57 | :win9xME_args_slurp 58 | if "x%~1" == "x" goto execute 59 | 60 | set CMD_LINE_ARGS=%* 61 | 62 | :execute 63 | @rem Setup the command line 64 | 65 | set CLASSPATH=%APP_HOME%\lib\nanopub-1.33-jar-with-dependencies.jar 66 | 67 | @rem Execute nanopub-java 68 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% -jar "%CLASSPATH%" %CMD_LINE_ARGS% 69 | 70 | :end 71 | @rem End local scope for the variables with windows NT shell 72 | if "%ERRORLEVEL%"=="0" goto mainEnd 73 | 74 | :fail 75 | exit /b 1 76 | 77 | :mainEnd 78 | if "%OS%"=="Windows_NT" endlocal 79 | -------------------------------------------------------------------------------- /scripts/notebooks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | jupyter notebook examples 6 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | pytest --cov=nanopub --cov-report=term-missing:skip-covered ${@} 6 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nanopublication/nanopub-py/9482610f7463ca0b8e27fe6ea47fb3f4c185bf41/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tempfile 3 | 4 | import pytest 5 | import requests 6 | 7 | from nanopub import NanopubConf, load_profile 8 | from nanopub.client import TEST_NANOPUB_QUERY_URL 9 | from nanopub.definitions import TEST_RESOURCES_FILEPATH 10 | from tests.java_wrapper import JavaWrapper 11 | 12 | 13 | def pytest_addoption(parser): 14 | parser.addoption('--no_rsa_key', action='store_true', default=False, 15 | help="enable no_rsa_key decorated tests") 16 | 17 | 18 | def pytest_configure(config): 19 | if not config.option.no_rsa_key: 20 | setattr(config.option, 'markexpr', 'not no_rsa_key') 21 | 22 | 23 | skip_if_nanopub_server_unavailable = ( 24 | pytest.mark.skipif( 25 | requests.get(TEST_NANOPUB_QUERY_URL).status_code != 200, 26 | reason='Nanopub server is unavailable' 27 | ) 28 | ) 29 | 30 | 31 | # Create a temporary profile.yml file for testing 32 | profile_test_path = os.path.join(tempfile.mkdtemp(), "profile.yml") 33 | profile_yaml = f"""orcid_id: https://orcid.org/0000-0000-0000-0000 34 | name: Python Tests 35 | public_key: {os.path.join(TEST_RESOURCES_FILEPATH, "id_rsa.pub")} 36 | private_key: {os.path.join(TEST_RESOURCES_FILEPATH, "id_rsa")} 37 | introduction_nanopub_uri: 38 | """ 39 | with open(profile_test_path, "w") as f: 40 | f.write(profile_yaml) 41 | 42 | profile_test = load_profile(profile_test_path) 43 | 44 | default_conf = NanopubConf( 45 | profile=profile_test, 46 | use_test_server=True, 47 | add_prov_generated_time=False, 48 | add_pubinfo_generated_time=False, 49 | attribute_assertion_to_profile=True, 50 | attribute_publication_to_profile=True, 51 | assertion_attributed_to=None, 52 | publication_attributed_to=None, 53 | derived_from=None 54 | ) 55 | 56 | testsuite_conf = NanopubConf( 57 | profile=profile_test, 58 | use_test_server=True, 59 | add_prov_generated_time=False, 60 | add_pubinfo_generated_time=False, 61 | attribute_assertion_to_profile=False, 62 | attribute_publication_to_profile=False, 63 | ) 64 | 65 | java_wrap = JavaWrapper(private_key=profile_test.private_key) 66 | -------------------------------------------------------------------------------- /tests/resources/id_rsa: -------------------------------------------------------------------------------- 1 | MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPdEfIdHtZYoFh6/DWorzoHpFXMjugqW+CGpe9uk4BfUq54MToi2u7fgdGGtXLg4wsJFBYETdVeS0p1uA7EPe8LhwjHPktf5c6AZbO/lYpKM59e7/Ih4mvOy4iTIe/Dv+1OgasTSK0nXAbKUm/5iJ6LOYa82JQeE/QnT5gUw2e97AgMBAAECgYBbNQnyJINYpeSy5qoeFZaQ2Ncup2kCavmQASJMvJ5ka+/51nRJfY30n3iOZxIiad19J1SGbhUEfoXtyBzYfOubF2i2GJtdF5VyjdSoU6w/gOo2/vnbH+GCHnMclrWshohOADGQU/Y8pYhIvlQqcb6xEOts9m9C9g4uwvPXqjmhoQJBAPkmSFIZwF3i2UvJlHyeXi599L0jkGTUJy/Y4IjieUx5suwvAtG47ejhgIPKK06VtW49oGPHWjWc3cJAmnV+vTMCQQD+EPTvNtLpX9QiDEJD7b8woDwmVrvH/RUosP/cXpMQd7BUVgPlpffAlFJGDlOzwwjZjy+8kc6MYevh1kWqobSZAkEAyCs+nV99ErEHnYEFoB1oU3f0oeSpxKhCF4np03AIvi1kV6bpX+9wjNJnevp5UriqvDgc3S0zx7EQ5Vkb/1vkywJBAMMw59y4tAVT+DhITsi9aTvEfzG9RPt6trzSb2Aw0K/AJJpGkyvl/JfZ2/Oyoh/jYXM0DKrFIni76mtRIajcH1ECQQCJi6aXOaRkRPmf7FYY9cRaJdR1BtZkKZbDg6ZMD1bY97cGiM9STTMeldYcCtQBtyhVCTEObI/V6/0FAvY9Zi7w 2 | -------------------------------------------------------------------------------- /tests/resources/id_rsa.pub: -------------------------------------------------------------------------------- 1 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3RHyHR7WWKBYevw1qK86B6RVzI7oKlvghqXvbpOAX1KueDE6Itru34HRhrVy4OMLCRQWBE3VXktKdbgOxD3vC4cIxz5LX+XOgGWzv5WKSjOfXu/yIeJrzsuIkyHvw7/tToGrE0itJ1wGylJv+YieizmGvNiUHhP0J0+YFMNnvewIDAQAB 2 | -------------------------------------------------------------------------------- /tests/test_cli.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | import pytest 5 | from typer.testing import CliRunner 6 | 7 | from nanopub.__main__ import cli, validate_orcid_id 8 | from nanopub._version import __version__ 9 | from nanopub.definitions import DEFAULT_PROFILE_PATH 10 | from tests.conftest import TEST_RESOURCES_FILEPATH 11 | 12 | runner = CliRunner() 13 | 14 | PRIVATE_KEY_PATH = os.path.join(TEST_RESOURCES_FILEPATH, "id_rsa") 15 | 16 | 17 | def test_validate_orcid_id(): 18 | valid_ids = ['https://orcid.org/1234-5678-1234-5678', 19 | 'https://orcid.org/1234-5678-1234-567X'] 20 | for orcid_id in valid_ids: 21 | assert validate_orcid_id(ctx=None, param=None, orcid_id=orcid_id) == orcid_id 22 | 23 | invalid_ids = ['https://orcid.org/abcd-efgh-abcd-efgh', 24 | 'https://orcid.org/1234-5678-1234-567', 25 | 'https://orcid.org/1234-5678-1234-56789', 26 | 'https://other-url.org/1234-5678-1234-5678', 27 | '0000-0000-0000-0000'] 28 | for orcid_id in invalid_ids: 29 | with pytest.raises(ValueError): 30 | validate_orcid_id(ctx=None, param=None, orcid_id=orcid_id) 31 | 32 | 33 | def test_setup(): 34 | # np setup --orcid-id https://orcid.org/0000-0000-0000-0000 --name "Python test" --newkeys --no-publish 35 | result = runner.invoke(cli, [ 36 | "setup", 37 | "--orcid-id", "https://orcid.org/0000-0000-0000-0000", 38 | "--name", "Python test", 39 | "--newkeys", "--no-publish" 40 | ]) 41 | assert result.exit_code == 1 42 | assert "Setting up nanopub profile" in result.stdout 43 | assert Path(DEFAULT_PROFILE_PATH).exists() 44 | 45 | 46 | def test_profile(): 47 | result = runner.invoke(cli, [ 48 | "profile", 49 | ]) 50 | assert "User profile in" in result.stdout 51 | 52 | 53 | def test_publish(): 54 | test_file = "./tests/testsuite/valid/plain/simple1.trig" 55 | result = runner.invoke(cli, [ 56 | "publish", test_file, "--test" 57 | ]) 58 | assert result.exit_code == 0 59 | assert "Nanopub published at" in result.stdout 60 | 61 | 62 | def test_sign_with_key(): 63 | test_file = "./tests/testsuite/valid/plain/simple1.trig" 64 | result = runner.invoke(cli, [ 65 | "sign", test_file, 66 | "-k", PRIVATE_KEY_PATH, 67 | ]) 68 | assert result.exit_code == 0 69 | assert "Nanopub signed in" in result.stdout 70 | 71 | 72 | def test_version(): 73 | result = runner.invoke(cli, ["version"]) 74 | assert result.exit_code == 0 75 | assert __version__ == result.stdout.strip() 76 | -------------------------------------------------------------------------------- /tests/test_fdo_nanopub.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import rdflib 3 | from rdflib import RDF, RDFS 4 | from nanopub.namespaces import HDL, FDOF, NPX 5 | from nanopub.fdo_nanopub import FDONanopub, to_hdl_uri 6 | from nanopub.constants import FDO_DATA_REF_HANDLE_URI, FDO_PROFILE_HANDLE_URI, FDO_SERVICE_HANDLE_URI, FDO_TYPE_HANDLE_URI, FDO_STATUS_HANDLE_URI 7 | 8 | FAKE_HANDLE = "21.T11966/test" 9 | FAKE_URI = HDL[FAKE_HANDLE] 10 | FAKE_LABEL = "Test Object" 11 | FAKE_TYPE_JSON = '{"@type": "Dataset"}' 12 | FAKE_STATUS = "active" 13 | FAKE_ATTR_VALUE = rdflib.Literal("some value") 14 | FAKE_ATTR_LABEL = "Test Attribute" 15 | 16 | 17 | @pytest.mark.parametrize("fdo_id", [FAKE_HANDLE, HDL[FAKE_HANDLE]]) 18 | def test_initial_fdo_triples(fdo_id): 19 | fdo = FDONanopub(fdo_id, FAKE_LABEL) 20 | fdo_uri = to_hdl_uri(fdo_id) 21 | 22 | assert (fdo_uri, RDF.type, FDOF.FAIRDigitalObject) in fdo.assertion 23 | assert (fdo_uri, RDFS.label, rdflib.Literal(FAKE_LABEL)) in fdo.assertion 24 | assert (fdo_uri, FDOF.hasMetadata, fdo.metadata.np_uri) in fdo.assertion 25 | assert (fdo.metadata.np_uri, RDFS.label, rdflib.Literal(f"FAIR Digital Object: {FAKE_LABEL}")) in fdo.pubinfo 26 | assert (fdo.metadata.np_uri, NPX.introduces, fdo_uri) in fdo.pubinfo 27 | 28 | @pytest.mark.parametrize("fdo_profile", [FAKE_HANDLE, HDL[FAKE_HANDLE]]) 29 | def test_add_fdo_profile(fdo_profile): 30 | fdo = FDONanopub(FAKE_HANDLE, FAKE_LABEL) 31 | uri = to_hdl_uri(fdo_profile) 32 | fdo.add_fdo_profile(fdo_profile) 33 | assert (fdo.fdo_uri, FDO_PROFILE_HANDLE_URI, rdflib.Literal(uri)) in fdo.assertion 34 | assert (FDO_PROFILE_HANDLE_URI, RDFS.label, rdflib.Literal("FdoProfile")) in fdo.pubinfo 35 | 36 | @pytest.mark.parametrize("data_ref", [FAKE_HANDLE, HDL[FAKE_HANDLE]]) 37 | def test_add_fdo_data_ref(data_ref): 38 | fdo = FDONanopub(FAKE_HANDLE, FAKE_LABEL) 39 | uri = to_hdl_uri(data_ref) 40 | fdo.add_fdo_data_ref(data_ref) 41 | assert (fdo.fdo_uri, FDO_DATA_REF_HANDLE_URI, uri) in fdo.assertion 42 | assert (FDO_DATA_REF_HANDLE_URI, RDFS.label, rdflib.Literal("DataRef")) in fdo.pubinfo 43 | 44 | @pytest.mark.parametrize("service_uri", [FAKE_HANDLE, HDL[FAKE_HANDLE]]) 45 | def test_add_fdo_service(service_uri): 46 | fdo = FDONanopub(FAKE_HANDLE, FAKE_LABEL) 47 | uri = to_hdl_uri(service_uri) 48 | fdo.add_fdo_service(service_uri) 49 | assert (fdo.fdo_uri, FDO_SERVICE_HANDLE_URI, rdflib.Literal(uri)) in fdo.assertion 50 | assert (FDO_SERVICE_HANDLE_URI, RDFS.label, rdflib.Literal("FdoService")) in fdo.pubinfo 51 | 52 | @pytest.mark.parametrize("attr_HANDLE", [FAKE_HANDLE, HDL[FAKE_HANDLE]]) 53 | def test_add_attribute_and_label(attr_HANDLE): 54 | fdo = FDONanopub(FAKE_HANDLE, FAKE_LABEL) 55 | uri = to_hdl_uri(attr_HANDLE) 56 | fdo.add_attribute(attr_HANDLE, FAKE_ATTR_VALUE) 57 | fdo.add_attribute_label(attr_HANDLE, FAKE_ATTR_LABEL) 58 | assert (fdo.fdo_uri, uri, FAKE_ATTR_VALUE) in fdo.assertion 59 | assert (uri, RDFS.label, rdflib.Literal(FAKE_ATTR_LABEL)) in fdo.pubinfo 60 | 61 | def test_add_fdo_type(): 62 | fdo = FDONanopub(FAKE_HANDLE, FAKE_LABEL) 63 | fdo.add_fdo_type(FAKE_TYPE_JSON) 64 | # Related to https://github.com/RDFLib/rdflib/issues/1830 65 | # assert (fdo.fdo_uri, fdo.FDO_TYPE_HANDLE, rdflib.Literal(FAKE_TYPE_JSON, datatype=XSD.string)) in fdo.assertion 66 | assert (FDO_TYPE_HANDLE_URI, RDFS.label, rdflib.Literal("FdoType")) in fdo.pubinfo 67 | 68 | def test_add_fdo_status(): 69 | fdo = FDONanopub(FAKE_HANDLE, FAKE_LABEL) 70 | fdo.add_fdo_status(FAKE_STATUS) 71 | assert (fdo.fdo_uri, FDO_STATUS_HANDLE_URI, rdflib.Literal(FAKE_STATUS)) in fdo.assertion 72 | assert (FDO_STATUS_HANDLE_URI, RDFS.label, rdflib.Literal("FdoStatus")) in fdo.pubinfo 73 | -------------------------------------------------------------------------------- /tests/test_sign_utils.py: -------------------------------------------------------------------------------- 1 | from rdflib import Graph, Literal, URIRef 2 | 3 | from nanopub import Nanopub, namespaces 4 | from nanopub.client import DUMMY_NAMESPACE 5 | from nanopub.sign_utils import add_signature 6 | from tests.conftest import default_conf, java_wrap, profile_test 7 | 8 | 9 | def test_nanopub_sign(): 10 | expected_np_uri = "http://purl.org/np/RAoXkQkJe_lpMhYW61Y9mqWDHa5MAj1o4pWIiYLmAzY50" 11 | 12 | assertion = Graph() 13 | assertion.add(( 14 | URIRef('http://test'), namespaces.HYCL.claims, Literal('This is a test of nanopub-python') 15 | )) 16 | 17 | np = Nanopub( 18 | conf=default_conf, 19 | assertion=assertion 20 | ) 21 | java_np = java_wrap.sign(np) 22 | 23 | signed_g = add_signature( 24 | np.rdf, 25 | profile_test, 26 | DUMMY_NAMESPACE, 27 | np.pubinfo 28 | ) 29 | np.update_from_signed(signed_g) 30 | assert np.source_uri == expected_np_uri 31 | assert np.source_uri == java_np 32 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/plain/emptya.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | } 19 | 20 | :provenance { 21 | :assertion prov:hadPrimarySource . 22 | } 23 | 24 | :pubinfo { 25 | : dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 26 | pav:createdBy ; 27 | a npx:ExampleNanopub . 28 | } 29 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/plain/emptyinfo.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | } 20 | 21 | :provenance { 22 | :assertion prov:hadPrimarySource . 23 | } 24 | 25 | :pubinfo { 26 | } 27 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/plain/emptyprov.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | } 20 | 21 | :provenance { 22 | } 23 | 24 | :pubinfo { 25 | : dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 26 | pav:createdBy ; 27 | a npx:ExampleNanopub . 28 | } 29 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/plain/extragraph.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | } 20 | 21 | :foobar { 22 | ex:mosquito ex:transmits ex:malaria . 23 | } 24 | 25 | :provenance { 26 | :assertion prov:hadPrimarySource . 27 | } 28 | 29 | :pubinfo { 30 | : dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 31 | pav:createdBy ; 32 | a npx:ExampleNanopub . 33 | } 34 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/plain/noinfolink.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | ex:mosquito2 ex:transmits ex:malaria4 . 20 | } 21 | 22 | :provenance { 23 | :assertion prov:hadPrimarySource . 24 | } 25 | 26 | :pubinfo { 27 | :something dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 28 | pav:createdBy ; 29 | a npx:ExampleNanopub . 30 | } 31 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/plain/noprovlink.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | } 20 | 21 | :provenance { 22 | :assertionFoo prov:hadPrimarySource . 23 | } 24 | 25 | :pubinfo { 26 | : dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 27 | pav:createdBy ; 28 | a npx:ExampleNanopub . 29 | } 30 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/plain/valid_invalid1.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix ex: . 8 | 9 | :Head { 10 | : a np:Nanopublication ; np:hasAssertion :assertion ; 11 | np:hasProvenance :provenance ; np:hasPublicationInfo :pubinfo . 12 | } 13 | :assertion { 14 | ex:mosquito ex:transmits ex:malaria . 15 | } 16 | :provenance { 17 | :assertion prov:wasDerivedFrom . 18 | } 19 | :pubinfo { 20 | : pav:createdBy . 21 | : dc:created "2014-07-09T13:54:11+01:00"^^xsd:dateTime . 22 | } 23 | 24 | 25 | @prefix : . 26 | @prefix xsd: . 27 | @prefix dc: . 28 | @prefix pav: . 29 | @prefix prov: . 30 | @prefix np: . 31 | @prefix ex: . 32 | 33 | :Head { 34 | : a np:Nanopublication ; np:hasAssertion :assertion ; 35 | np:hasProvenance :provenance ; np:hasPublicationInfo :pubinfo . 36 | } 37 | :assertion { 38 | ex:Gene1 ex:isRealtedTo ex:malaria . 39 | } 40 | :provenance { 41 | :assertion prov:wasDerivedFrom . 42 | } 43 | :pubinfo { 44 | : pav:createdBy . 45 | : dc:created "2014-07-09T13:54:11+01:00"^^xsd:dateTime . 46 | } 47 | 48 | 49 | @prefix : . 50 | @prefix xsd: . 51 | @prefix dc: . 52 | @prefix pav: . 53 | @prefix prov: . 54 | @prefix np: . 55 | @prefix ex: . 56 | 57 | :Head { 58 | : a np:Nanopublication ; 59 | np:hasProvenance :provenance ; np:hasPublicationInfo :pubinfo . 60 | } 61 | :provenance { 62 | :assertion prov:wasDerivedFrom . 63 | } 64 | :pubinfo { 65 | : pav:createdBy . 66 | : dc:created "2014-07-09T13:54:11+01:00"^^xsd:dateTime . 67 | } 68 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/signed/simple1-invalid-dsa.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | @prefix ex: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion ; 13 | np:hasProvenance sub:provenance ; 14 | np:hasPublicationInfo sub:pubinfo ; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | ex:mosquito ex:transmits ex:malAria . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | sub:signature npx:hasAlgorithm "DSA" ; 28 | npx:hasPublicKey "MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAEHvFRpU7ryp1gAOi2yoy2VX8jraJdwPo6ZC1idtsGVcmou89Y3KOoJmlW3VU8ZPolpVWuM+EPNmLNFmifYr+svu8AOQkilZBLdkS5BrPVxIpV0dLeaBUroof1wPsVuwEPOdNzWsEmPF1Az8qLGEdPbyn7ehWqO/lNVmW8+c4O2k=" ; 29 | npx:hasSignature "MCwCFFMlGKFn+75HC3sP6JjBNubA1yPKAhReEzogcNHOueSlRzocjB7fyU4zFw==" ; 30 | npx:hasSignatureTarget this: . 31 | 32 | this: dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 33 | pav:createdBy ; 34 | a npx:ExampleNanopub . 35 | } 36 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/signed/simple1-invalid-rsa.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | @prefix ex: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion ; 13 | np:hasProvenance sub:provenance ; 14 | np:hasPublicationInfo sub:pubinfo ; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | ex:moSquito ex:transmits ex:malaria . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | sub:signature npx:hasAlgorithm "RSA" ; 28 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB" ; 29 | npx:hasSignature "OC0xJTavw9h/JSZIZl/NLzEZqQk1E7XWV3o1btD1cojxf9FMtgZuMMOtnPcgydRn3gK0wbUh+ATV4sEFdG51khsrOOH7+RylqnaE9XD4L65dwPZ/PpI32/LMYsQ62rsb0ajWtXr5cKDIKaoah0U1V85XlLGhoEyzrLZCU5uqJbo=" ; 30 | npx:hasSignatureTarget this: . 31 | 32 | this: dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 33 | pav:createdBy ; 34 | a npx:ExampleNanopub . 35 | } 36 | -------------------------------------------------------------------------------- /tests/testsuite/invalid/trusty/trusty1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | 10 | sub:Head { 11 | this: np:hasAssertion sub:assertion ; 12 | np:hasProvenance sub:provenance ; 13 | np:hasPublicationInfo sub:pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | sub:assertion { 18 | sub:assertion npx:asSentence ; 19 | a npx:UnderspecifiedAssertion . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | this: dc:created "2014-07-29T10:13:35+01:00"^^xsd:dateTime ; 28 | pav:createdBy ; 29 | a npx:ExampleNanopub . 30 | } 31 | -------------------------------------------------------------------------------- /tests/testsuite/transform/signed/rsa-key1/key/id_rsa: -------------------------------------------------------------------------------- 1 | MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPdEfIdHtZYoFh6/DWorzoHpFXMjugqW+CGpe9uk4BfUq54MToi2u7fgdGGtXLg4wsJFBYETdVeS0p1uA7EPe8LhwjHPktf5c6AZbO/lYpKM59e7/Ih4mvOy4iTIe/Dv+1OgasTSK0nXAbKUm/5iJ6LOYa82JQeE/QnT5gUw2e97AgMBAAECgYBbNQnyJINYpeSy5qoeFZaQ2Ncup2kCavmQASJMvJ5ka+/51nRJfY30n3iOZxIiad19J1SGbhUEfoXtyBzYfOubF2i2GJtdF5VyjdSoU6w/gOo2/vnbH+GCHnMclrWshohOADGQU/Y8pYhIvlQqcb6xEOts9m9C9g4uwvPXqjmhoQJBAPkmSFIZwF3i2UvJlHyeXi599L0jkGTUJy/Y4IjieUx5suwvAtG47ejhgIPKK06VtW49oGPHWjWc3cJAmnV+vTMCQQD+EPTvNtLpX9QiDEJD7b8woDwmVrvH/RUosP/cXpMQd7BUVgPlpffAlFJGDlOzwwjZjy+8kc6MYevh1kWqobSZAkEAyCs+nV99ErEHnYEFoB1oU3f0oeSpxKhCF4np03AIvi1kV6bpX+9wjNJnevp5UriqvDgc3S0zx7EQ5Vkb/1vkywJBAMMw59y4tAVT+DhITsi9aTvEfzG9RPt6trzSb2Aw0K/AJJpGkyvl/JfZ2/Oyoh/jYXM0DKrFIni76mtRIajcH1ECQQCJi6aXOaRkRPmf7FYY9cRaJdR1BtZkKZbDg6ZMD1bY97cGiM9STTMeldYcCtQBtyhVCTEObI/V6/0FAvY9Zi7w 2 | -------------------------------------------------------------------------------- /tests/testsuite/transform/signed/rsa-key1/key/id_rsa.pub: -------------------------------------------------------------------------------- 1 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3RHyHR7WWKBYevw1qK86B6RVzI7oKlvghqXvbpOAX1KueDE6Itru34HRhrVy4OMLCRQWBE3VXktKdbgOxD3vC4cIxz5LX+XOgGWzv5WKSjOfXu/yIeJrzsuIkyHvw7/tToGrE0itJ1wGylJv+YieizmGvNiUHhP0J0+YFMNnvewIDAQAB 2 | -------------------------------------------------------------------------------- /tests/testsuite/transform/signed/rsa-key1/simple1.in.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | } 20 | 21 | :provenance { 22 | :assertion prov:hadPrimarySource . 23 | } 24 | 25 | :pubinfo { 26 | : dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 27 | pav:createdBy ; 28 | a npx:ExampleNanopub . 29 | } 30 | -------------------------------------------------------------------------------- /tests/testsuite/transform/signed/rsa-key1/simple1.out.code: -------------------------------------------------------------------------------- 1 | RALbDbWVnLmLqpNgOsI_AaYfLbEnlOfZy3CoRRLs9XqVk 2 | -------------------------------------------------------------------------------- /tests/testsuite/transform/signed/rsa-key1/simple1.out.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix np: . 4 | @prefix ex: . 5 | @prefix pav: . 6 | @prefix npx: . 7 | @prefix xsd: . 8 | @prefix prov: . 9 | @prefix dc: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion; 13 | np:hasProvenance sub:provenance; 14 | np:hasPublicationInfo sub:pubinfo; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | ex:mosquito ex:transmits ex:malaria . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | sub:sig npx:hasAlgorithm "RSA"; 28 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3RHyHR7WWKBYevw1qK86B6RVzI7oKlvghqXvbpOAX1KueDE6Itru34HRhrVy4OMLCRQWBE3VXktKdbgOxD3vC4cIxz5LX+XOgGWzv5WKSjOfXu/yIeJrzsuIkyHvw7/tToGrE0itJ1wGylJv+YieizmGvNiUHhP0J0+YFMNnvewIDAQAB"; 29 | npx:hasSignature "9Z7zk22V1SgJ+jSw4WAkK3yJ7xuoEkIPJWSLEzx0b6OgHiqiioS0DMziQYCjQA8gBWu0zlJr64tj8Ip38fKynxriznwgVtcjBSKtjnLfZEZPZrtasLKxmtrobYbnyNPBi0Geq8oQpeg9Qg5MldhI7HoiEFTaOkmZJEt0TjrOUVc="; 30 | npx:hasSignatureTarget this: . 31 | 32 | this: dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime; 33 | pav:createdBy ; 34 | a npx:ExampleNanopub . 35 | } 36 | -------------------------------------------------------------------------------- /tests/testsuite/transform/trusty/aida1.in.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | :assertion npx:asSentence ; 19 | a npx:UnderspecifiedAssertion . 20 | } 21 | 22 | :provenance { 23 | :assertion prov:hadPrimarySource . 24 | } 25 | 26 | :pubinfo { 27 | : dc:created "2014-07-29T10:13:35+01:00"^^xsd:dateTime ; 28 | pav:createdBy ; 29 | a npx:ExampleNanopub . 30 | } 31 | -------------------------------------------------------------------------------- /tests/testsuite/transform/trusty/aida1.out.code: -------------------------------------------------------------------------------- 1 | RAPpJU5UOB4pavfWyk7FE3WQiam5yBpmIlviAQWtBSC4M 2 | -------------------------------------------------------------------------------- /tests/testsuite/transform/trusty/aida1.out.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | 10 | sub:Head { 11 | this: np:hasAssertion sub:assertion; 12 | np:hasProvenance sub:provenance; 13 | np:hasPublicationInfo sub:pubinfo; 14 | a np:Nanopublication . 15 | } 16 | 17 | sub:assertion { 18 | sub:assertion npx:asSentence ; 19 | a npx:UnderspecifiedAssertion . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | this: dc:created "2014-07-29T10:13:35+01:00"^^xsd:dateTime; 28 | pav:createdBy ; 29 | a npx:ExampleNanopub . 30 | } 31 | -------------------------------------------------------------------------------- /tests/testsuite/transform/trusty/simple1.in.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | } 20 | 21 | :provenance { 22 | :assertion prov:hadPrimarySource . 23 | } 24 | 25 | :pubinfo { 26 | : dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 27 | pav:createdBy ; 28 | a npx:ExampleNanopub . 29 | } 30 | -------------------------------------------------------------------------------- /tests/testsuite/transform/trusty/simple1.out.code: -------------------------------------------------------------------------------- 1 | RAtAU6U_xKTH016Eoiu11SswQkBu1elB_3_BoDJWH3arA 2 | -------------------------------------------------------------------------------- /tests/testsuite/transform/trusty/simple1.out.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | @prefix ex: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion; 13 | np:hasProvenance sub:provenance; 14 | np:hasPublicationInfo sub:pubinfo; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | ex:mosquito ex:transmits ex:malaria . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | this: dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime; 28 | pav:createdBy ; 29 | a npx:ExampleNanopub . 30 | } 31 | -------------------------------------------------------------------------------- /tests/testsuite/valid/plain/aida1.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | :assertion npx:asSentence ; 19 | a npx:UnderspecifiedAssertion . 20 | } 21 | 22 | :provenance { 23 | :assertion prov:hadPrimarySource . 24 | } 25 | 26 | :pubinfo { 27 | : dc:created "2014-07-29T10:13:35+01:00"^^xsd:dateTime ; 28 | pav:createdBy ; 29 | a npx:ExampleNanopub . 30 | } 31 | -------------------------------------------------------------------------------- /tests/testsuite/valid/plain/proteinatlas-16-1.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix hpa: . 3 | @prefix hpas: . 4 | @prefix tissue: . 5 | @prefix xsd: . 6 | @prefix rdfs: . 7 | @prefix np: . 8 | @prefix prov: . 9 | @prefix prv: . 10 | @prefix pav: . 11 | @prefix dcterms: . 12 | @prefix sio: . 13 | @prefix owl: . 14 | @prefix eco: . 15 | @prefix msh: . 16 | @prefix lld: . 17 | @prefix bfo: . 18 | @prefix bao: . 19 | @prefix nif: . 20 | @prefix wi: . 21 | @prefix wp: . 22 | @prefix nih: . 23 | 24 | :ENSG00000000003_ih_TS_0030_head { 25 | :ENSG00000000003_ih_TS_0030 a np:Nanopublication . 26 | :ENSG00000000003_ih_TS_0030_assertion a np:Assertion ; 27 | rdfs:comment "IHC shows Not_detected protein expression of ENSG00000000003 in lung(macrophages) with a Approved evidence/reliability"^^xsd:string . 28 | :ENSG00000000003_ih_TS_0030_provenance a np:Provenance . 29 | :ENSG00000000003_ih_TS_0030_publicationInfo a np:PublicationInfo . 30 | :ENSG00000000003_ih_TS_0030 np:hasAssertion :ENSG00000000003_ih_TS_0030_assertion ; 31 | np:hasProvenance :ENSG00000000003_ih_TS_0030_provenance ; 32 | np:hasPublicationInfo :ENSG00000000003_ih_TS_0030_publicationInfo . 33 | } 34 | :ENSG00000000003_ih_TS_0030_assertion { 35 | hpa:ENSG00000000003 bfo:BFO_0000066 hpa:TS-0030 ; # Occurs in 36 | nif:nlx_qual_1010003 "Not_detected"^^xsd:string . # Expression level 37 | hpa:TS-0030 a tissue:TS-0030 . 38 | } 39 | :ENSG00000000003_ih_TS_0030_provenance { 40 | :ENSG00000000003_ih_TS_0030_assertion a :IHCEvidence . 41 | :ENSG00000000003_ih_TS_0030 prov:wasGeneratedBy :ConclusionalEvidence ; 42 | prov:wasDerivedFrom :IHCAssay ; 43 | prov:wasGeneratedBy :ManualCuration ; 44 | prv:usedData hpas:HPA004109 ; 45 | prv:usedData hpa:ENSG00000000003 ; 46 | wi:evidence "Approved"^^xsd:string . 47 | } 48 | :ENSG00000000003_ih_TS_0030_publicationInfo { 49 | :ENSG00000000003_ih_TS_0030 prv:usedData :HumanProteinAtlas ; 50 | pav:authoredBy "Human Protein Atlas project"; 51 | pav:createdBy "Kalle von Feilitzen"; 52 | dcterms:contributor ; 53 | dcterms:contributor ; 54 | dcterms:contributor ; 55 | dcterms:contributor ; 56 | dcterms:contributor ; 57 | dcterms:rights ; 58 | dcterms:rightsHolder . 59 | } 60 | -------------------------------------------------------------------------------- /tests/testsuite/valid/plain/simple1.nq: -------------------------------------------------------------------------------- 1 | . 2 | . 3 | . 4 | . 5 | . 6 | . 7 | "2014-07-24T18:05:11+01:00"^^ . 8 | . 9 | . 10 | -------------------------------------------------------------------------------- /tests/testsuite/valid/plain/simple1.trig: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix xsd: . 3 | @prefix dc: . 4 | @prefix pav: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix npx: . 8 | @prefix ex: . 9 | 10 | :Head { 11 | : np:hasAssertion :assertion ; 12 | np:hasProvenance :provenance ; 13 | np:hasPublicationInfo :pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | :assertion { 18 | ex:mosquito ex:transmits ex:malaria . 19 | } 20 | 21 | :provenance { 22 | :assertion prov:hadPrimarySource . 23 | } 24 | 25 | :pubinfo { 26 | : dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 27 | pav:createdBy ; 28 | a npx:ExampleNanopub . 29 | } 30 | -------------------------------------------------------------------------------- /tests/testsuite/valid/plain/simple1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | http://example.org/nanopub-validator-example/Head 5 | 6 | http://example.org/nanopub-validator-example/ 7 | http://www.nanopub.org/nschema#hasAssertion 8 | http://example.org/nanopub-validator-example/assertion 9 | 10 | 11 | http://example.org/nanopub-validator-example/ 12 | http://www.nanopub.org/nschema#hasProvenance 13 | http://example.org/nanopub-validator-example/provenance 14 | 15 | 16 | http://example.org/nanopub-validator-example/ 17 | http://www.nanopub.org/nschema#hasPublicationInfo 18 | http://example.org/nanopub-validator-example/pubinfo 19 | 20 | 21 | http://example.org/nanopub-validator-example/ 22 | http://www.w3.org/1999/02/22-rdf-syntax-ns#type 23 | http://www.nanopub.org/nschema#Nanopublication 24 | 25 | 26 | 27 | http://example.org/nanopub-validator-example/assertion 28 | 29 | http://example.org/mosquito 30 | http://example.org/transmits 31 | http://example.org/malaria 32 | 33 | 34 | 35 | http://example.org/nanopub-validator-example/provenance 36 | 37 | http://example.org/nanopub-validator-example/assertion 38 | http://www.w3.org/ns/prov#hadPrimarySource 39 | http://dx.doi.org/10.3233/ISU-2010-0613 40 | 41 | 42 | 43 | http://example.org/nanopub-validator-example/pubinfo 44 | 45 | http://example.org/nanopub-validator-example/ 46 | http://purl.org/dc/terms/created 47 | 2014-07-24T18:05:11+01:00 48 | 49 | 50 | http://example.org/nanopub-validator-example/ 51 | http://purl.org/pav/createdBy 52 | http://orcid.org/0000-0002-1267-0234 53 | 54 | 55 | http://example.org/nanopub-validator-example/ 56 | http://www.w3.org/1999/02/22-rdf-syntax-ns#type 57 | http://purl.org/nanopub/x/ExampleNanopub 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/Darwin-Core-schema-resource.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix rdfs: . 5 | @prefix dct: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix orcid: . 9 | @prefix nt: . 10 | @prefix npx: . 11 | @prefix fip: . 12 | 13 | sub:Head { 14 | this: np:hasAssertion sub:assertion; 15 | np:hasProvenance sub:provenance; 16 | np:hasPublicationInfo sub:pubinfo; 17 | a np:Nanopublication . 18 | } 19 | 20 | sub:assertion { 21 | sub:DwC a fip:Available-FAIR-Enabling-Resource, fip:Data-schema, fip:FAIR-Enabling-Resource; 22 | rdfs:comment "Darwin Core schema"; 23 | rdfs:label "Darwin Core" . 24 | } 25 | 26 | sub:provenance { 27 | sub:assertion prov:wasAttributedTo orcid:0000-0001-8050-0299 . 28 | } 29 | 30 | sub:pubinfo { 31 | sub:sig npx:hasAlgorithm "RSA"; 32 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK0bP9YbOpX9gkjJ2pgsWHTSa7bNQUGoh1LmmALJZyElQjEswZH0UgweLiB0qO74y9XGnbjFUDJiQGeVML6XugTWR29ujRUk9vOU0YKe2ZXTjSm87bMD4S7w2kTIKg1EFu27TKmJwR1l4RoGJpB0YMzR/zris//sbDhpKYPUaA0QIDAQAB"; 33 | npx:hasSignature "Qi7p95ignv+MnRvc/pDFxYYDUeFkrNloQEk81INsr+un26CS/mNnoUXoEquiu2R5ObZ8DTywzPkFQUqO4tLIQN/qvVmrGSvoreNBO14Uwh2X2Z9DJIPgUr/t0JvDwbj16oufAi07oUVRZJ3F/W1l5hlfu6JR7DSJn4cAT3KJgB0="; 34 | npx:hasSignatureTarget this: . 35 | 36 | this: dct:created "2020-10-05T10:49:41.102+02:00"^^xsd:dateTime; 37 | dct:creator orcid:0000-0001-8050-0299; 38 | npx:introduces sub:DwC; 39 | nt:wasCreatedFromProvenanceTemplate ; 40 | nt:wasCreatedFromPubinfoTemplate ; 41 | nt:wasCreatedFromTemplate . 42 | } 43 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/EduSocDL-community.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix rdfs: . 5 | @prefix dct: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix orcid: . 9 | @prefix nt: . 10 | @prefix npx: . 11 | @prefix fip: . 12 | 13 | sub:Head { 14 | this: np:hasAssertion sub:assertion; 15 | np:hasProvenance sub:provenance; 16 | np:hasPublicationInfo sub:pubinfo; 17 | a np:Nanopublication . 18 | } 19 | 20 | sub:assertion { 21 | sub:EduSocDL a fip:FAIR-Implementation-Community; 22 | rdfs:comment "New research project trying to bring data on COVID-19 together from different discipline"; 23 | rdfs:label "Data Linking across Social and Educational Sciences on COVID-19"; 24 | rdfs:seeAlso ; 25 | fip:has-research-domain , , 26 | . 27 | } 28 | 29 | sub:provenance { 30 | sub:assertion prov:wasAttributedTo orcid:0000-0003-3517-8071 . 31 | } 32 | 33 | sub:pubinfo { 34 | sub:sig npx:hasAlgorithm "RSA"; 35 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK4NfUi+AdFS8l/WeyiKQmCyFyjrjfGnpHvUvdGUlkg2+FkOY3+31U4a4SdeLUdhf4hnxL8kQOjD8BuggdBkuwUoMA0RXPv+RblmlF5INhXDJvxTqeUMLj1EVuOtotpl//NVFZ3BE0zeuscT35szmX4L+2m14Z/PqreP2lMzbj3wIDAQAB"; 36 | npx:hasSignature "bjcX/F0FWKJldeC1/8UuLDiiqw+zumSJTnQ3Pc2QZK1f6hsY9qteB4y7fGOoh2sD558pE6JFtjozp3UsuFkvzZB7KUCTu2HRu5aek3wrQtUpYPYEiW2BJNyqlkVwF7Hkm8Cw5GfSUi1cIaE817KaOWS9DiuzJ9xnPqLYNm/NZwE="; 37 | npx:hasSignatureTarget this: . 38 | 39 | this: dct:created "2020-10-05T16:20:03.409+02:00"^^xsd:dateTime; 40 | dct:creator orcid:0000-0003-3517-8071; 41 | npx:introduces sub:EduSocDL; 42 | nt:wasCreatedFromProvenanceTemplate ; 43 | nt:wasCreatedFromPubinfoTemplate ; 44 | nt:wasCreatedFromTemplate . 45 | } 46 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/nanobench_hasRead-template-v5.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix dct: . 7 | @prefix pav: . 8 | @prefix prov: . 9 | @prefix np: . 10 | @prefix orcid: . 11 | @prefix nt: . 12 | @prefix pc: . 13 | @prefix npx: . 14 | 15 | sub:Head { 16 | this: np:hasAssertion sub:assertion; 17 | np:hasProvenance sub:provenance; 18 | np:hasPublicationInfo sub:pubinfo; 19 | a np:Nanopublication . 20 | } 21 | 22 | sub:assertion { 23 | sub:assertion a nt:AssertionTemplate; 24 | rdfs:label "Announcing a paper that I have read"; 25 | nt:hasStatement sub:st1, sub:st2 . 26 | 27 | sub:comment a nt:LiteralPlaceholder; 28 | rdfs:label "comment text" . 29 | 30 | sub:paper a nt:UriPlaceholder; 31 | rdfs:label "DOI for the paper starting with '10.'"; 32 | nt:hasPrefix "https://doi.org/"; 33 | nt:hasPrefixLabel "the paper with DOI"; 34 | nt:hasRegex "10.(\\d)+/(\\S)+" . 35 | 36 | sub:st1 rdf:object sub:paper; 37 | rdf:predicate pc:hasRead; 38 | rdf:subject nt:CREATOR; 39 | a rdf:Statement; 40 | nt:statementOrder 1 . 41 | 42 | sub:st2 rdf:object sub:comment; 43 | rdf:predicate rdfs:comment; 44 | rdf:subject sub:paper; 45 | a nt:OptionalStatement; 46 | nt:statementOrder 2 . 47 | 48 | pc:hasRead rdfs:label "have read the paper" . 49 | 50 | rdfs:comment rdfs:label "has my comment" . 51 | } 52 | 53 | sub:provenance { 54 | sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 . 55 | } 56 | 57 | sub:pubinfo { 58 | sub:sig npx:hasAlgorithm "RSA"; 59 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB"; 60 | npx:hasSignature "GJs6X2F9V9bRnL+DGujqWDUwlNVFM2KAGJQGjw2bUjaIn/irTQRGwGmaBJ8YEzIOQxlZqTbwCSxnWx5J8tqgg2QuPRvyLw+IKR20IdjWeupNkLeSrJqHOhcj6Fn7iPlxgHkduzHSt2mzBJ/BFt9qSZsZWFjrkJIBqwoRMsSrVQ8="; 61 | npx:hasSignatureTarget this: . 62 | 63 | this: dct:created "2020-04-27T14:57:06.343+02:00"^^xsd:dateTime; 64 | npx:supersedes , 65 | ; 66 | pav:createdBy orcid:0000-0002-1267-0234 . 67 | } 68 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/nanobench_new-individual-template-v3.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix owl: . 7 | @prefix dct: . 8 | @prefix prov: . 9 | @prefix np: . 10 | @prefix orcid: . 11 | @prefix nt: . 12 | @prefix npx: . 13 | 14 | sub:Head { 15 | this: np:hasAssertion sub:assertion; 16 | np:hasProvenance sub:provenance; 17 | np:hasPublicationInfo sub:pubinfo; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | dct:description rdfs:label "can be described as follows:" . 23 | 24 | sub:assertion a nt:AssertionTemplate; 25 | rdfs:label "Defining a new individual"; 26 | nt:hasStatement sub:st0, sub:st1, sub:st2, sub:st3 . 27 | 28 | sub:class a nt:GuidedChoicePlaceholder; 29 | rdfs:label "the URI of the class this individual belongs to"; 30 | nt:possibleValue owl:Thing; 31 | nt:possibleValuesFromApi "http://purl.org/nanopub/api/find_signed_things?type=http%3A%2F%2Fwww.w3.org%2F2002%2F07%2Fowl%23Class&searchterm=", 32 | "https://www.wikidata.org/w/api.php?action=wbsearchentities&language=en&format=json&limit=5&search=" . 33 | 34 | sub:description a nt:LiteralPlaceholder; 35 | rdfs:label "description of the individual" . 36 | 37 | sub:individual a nt:IntroducedResource, nt:LocalResource, nt:UriPlaceholder; 38 | rdfs:label "short name, used as URI suffix" . 39 | 40 | sub:name a nt:LiteralPlaceholder; 41 | rdfs:label "the name of the individual" . 42 | 43 | sub:seeAlsoLink a nt:UriPlaceholder; 44 | rdfs:label "a URL where more information about this individual can be found" . 45 | 46 | sub:st0 rdf:object sub:class; 47 | rdf:predicate rdf:type; 48 | rdf:subject sub:individual; 49 | a nt:Statement; 50 | nt:statementOrder 0 . 51 | 52 | sub:st1 rdf:object sub:name; 53 | rdf:predicate rdfs:label; 54 | rdf:subject sub:individual; 55 | a rdf:Statement; 56 | nt:statementOrder 1 . 57 | 58 | sub:st2 rdf:object sub:description; 59 | rdf:predicate dct:description; 60 | rdf:subject sub:individual; 61 | a rdf:Statement; 62 | nt:statementOrder 2 . 63 | 64 | sub:st3 rdf:object sub:seeAlsoLink; 65 | rdf:predicate rdfs:seeAlso; 66 | rdf:subject sub:individual; 67 | a nt:OptionalStatement; 68 | nt:statementOrder 3 . 69 | 70 | rdf:type rdfs:label "is a" . 71 | 72 | rdfs:label rdfs:label "is called" . 73 | 74 | rdfs:seeAlso rdfs:label "is further explained at" . 75 | 76 | owl:Thing rdfs:label "thing" . 77 | } 78 | 79 | sub:provenance { 80 | sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 . 81 | } 82 | 83 | sub:pubinfo { 84 | sub:sig npx:hasAlgorithm "RSA"; 85 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB"; 86 | npx:hasSignature "bTApJ68j73RNNXIaN/itDZCkVQfJ0WQ3s3Y2tfFc0L2QrArOj/6kaPx5NnQg63yTrUqSAJhxC+Vrg0d3eckNl9GUNXpGQoj3mvoCvndA7U/MHvitGw0ji/oU7uijY9mvYe1xx2Vim+tiPugyi1L6IJkr8wiQ/22trlXhtuwWIyw="; 87 | npx:hasSignatureTarget this: . 88 | 89 | this: dct:created "2020-07-08T13:00:20.583+02:00"^^xsd:dateTime; 90 | dct:creator orcid:0000-0002-1267-0234; 91 | npx:supersedes . 92 | } 93 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/nanobench_somebodyElse-prtemplate.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix rdf: . 5 | @prefix rdfs: . 6 | @prefix dct: . 7 | @prefix pav: . 8 | @prefix prov: . 9 | @prefix np: . 10 | @prefix orcid: . 11 | @prefix nt: . 12 | @prefix npx: . 13 | 14 | sub:Head { 15 | this: np:hasAssertion sub:assertion; 16 | np:hasProvenance sub:provenance; 17 | np:hasPublicationInfo sub:pubinfo; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | sub:assertion a nt:ProvenanceTemplate; 23 | rdfs:label "Attributed to somebody else"; 24 | nt:hasStatement sub:st1 . 25 | 26 | sub:somebodyElse a nt:UriPlaceholder; 27 | rdfs:label "ORCID identifier of the person to be attributed"; 28 | nt:hasPrefix "https://orcid.org/"; 29 | nt:hasRegex "[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{3}[0-9X]" . 30 | 31 | sub:st1 rdf:object sub:somebodyElse; 32 | rdf:predicate prov:wasAttributedTo; 33 | rdf:subject nt:ASSERTION; 34 | a rdf:Statement . 35 | 36 | prov:wasAttributedTo rdfs:label "is attributed to" . 37 | } 38 | 39 | sub:provenance { 40 | sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 . 41 | } 42 | 43 | sub:pubinfo { 44 | sub:sig npx:hasAlgorithm "RSA"; 45 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB"; 46 | npx:hasSignature "pHlUZFzESjBcAFEQeyDN5qagrzloaWEAvmKr7a6UIP7w7iJVDqR7ERe1GQWY+1MXjvWIeIpofF0Q1wQW+XVubxHz/+DgAJtNfTVnDlrv2kTyR9JapNUYGuPuvixJ9T6lNj8kf9vXVtDtJPKYsttaQJrnMSz5Ww8FDVa3xXMXBgA="; 47 | npx:hasSignatureTarget this: . 48 | 49 | this: dct:created "2020-07-07T20:13:18.606+02:00"^^xsd:dateTime; 50 | pav:createdBy orcid:0000-0002-1267-0234 . 51 | } 52 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/physician-suicide-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dct: . 5 | @prefix prov: . 6 | @prefix np: . 7 | @prefix orcid: . 8 | @prefix nt: . 9 | @prefix fabio: . 10 | @prefix sio: . 11 | @prefix npx: . 12 | 13 | sub:Head { 14 | this: np:hasAssertion sub:assertion; 15 | np:hasProvenance sub:provenance; 16 | np:hasPublicationInfo sub:pubinfo; 17 | a np:Nanopublication . 18 | } 19 | 20 | sub:assertion { 21 | sub:local dct:creator "McGuire, T.; Moutier, C.; Downs, N.; Zisook, S."; 22 | dct:date "2013"; 23 | dct:identifier ; 24 | dct:title "In response to \"Details on suicide among US physicians: data from the National Violent Death Reporting System\""; 25 | dct:type fabio:PositionPaper; 26 | sio:SIO_000277 , 27 | ; 28 | prov:quotedText "finally as an acknowledgement of the significant rate of 300 to 400 annual physician suicides in the United States" . 29 | } 30 | 31 | sub:provenance { 32 | sub:assertion prov:wasAttributedTo orcid:0000-0002-6007-4023 . 33 | } 34 | 35 | sub:pubinfo { 36 | sub:sig npx:hasAlgorithm "RSA"; 37 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCk/t11RFdsK8IUlbD7CznUrl1IYZtmFhTuGCtzFASFh3p0KsIDEAJtmYJ0CRWUlolT9XPht31Rh0iKGsJpr1PP1H/bcnV0ogspLq5JQj7LNoldB28Mz0/TDGN/YUYVvJjomkEEXHFnKR5vPRYb8gTMifFaTWYYv6JIYVPWJJ+4YwIDAQAB"; 38 | npx:hasSignature "I3xNAfKMtDofyvHmfbw/SZhGNhBoBgmlRySf34uVutbnINtvjmJr7IYNed0VERhHmPeFAsohAysf3e0wHgcKkO+6aNkMuJaXTjiagUvTdJr4l8UWB/hR2536PTI4IlxiKiBiP8jHCT6cYFS3NWTKydDQ71/960qwhvRbhGfuByA="; 39 | npx:hasSignatureTarget this: . 40 | 41 | this: dct:created "2020-04-30T00:07:02.805+02:00"^^xsd:dateTime; 42 | dct:creator orcid:0000-0002-6007-4023; 43 | nt:wasCreatedFromTemplate . 44 | } 45 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/python-step-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix bpmn: . 4 | @prefix np: . 5 | @prefix npx: . 6 | @prefix ns1: . 7 | @prefix pplan: . 8 | @prefix prov: . 9 | @prefix rdfs: . 10 | @prefix xsd: . 11 | 12 | sub:Head { 13 | this: np:hasAssertion sub:assertion; 14 | np:hasProvenance sub:provenance; 15 | np:hasPublicationInfo sub:pubInfo; 16 | a np:Nanopublication . 17 | } 18 | 19 | sub:assertion { 20 | sub:a a "int", pplan:Variable . 21 | 22 | sub:add_output1 a "int", pplan:Variable . 23 | 24 | sub:b a "int", pplan:Variable . 25 | 26 | sub:step ns1:description """@mark_as_fairstep(label='add integers', is_script_task=True) 27 | def add(a: int, b: int) -> int: 28 | \"\"\" 29 | Computational step adding two ints together. 30 | \"\"\" 31 | return a + b 32 | """; 33 | pplan:hasInputVar sub:a, sub:b; 34 | pplan:hasOutputVar sub:add_output1; 35 | a bpmn:ScriptTask, pplan:Step; 36 | rdfs:label "add integers" . 37 | } 38 | 39 | sub:provenance { 40 | sub:assertion prov:generatedAtTime "2020-12-29T16:54:20.582254"^^xsd:dateTime . 41 | } 42 | 43 | sub:pubInfo { 44 | sub:sig npx:hasAlgorithm "RSA"; 45 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHcBtjfkmhqvHAg/vG73ky2txQkMk+QSrN6i+DvOGEXhv0g4hf89gqfg0gYIn8pHykxnrEyk6pC+3rcYVxqjsQ6l7XN/b2Q7FKKOJxt/qpLmrIe4/XNxVBeceTIdxrRy9r4dVBI4o5BzKFiNSM6PPToWtOoHR7obxL8gfRPfcXWQIDAQAB"; 46 | npx:hasSignature "mpQaGvS/Z0bBgyEaaTEzP9xbSMUF5bDgMLmahBSM9WYX7tWFmv5cmowobNQYL4gTMLn6fc3eNZeqIY95yGWFcBJpqrnZsl/HCUuEmxYI/tqruDYa5gJXv3tJQuOJsNFDe/Bss2dkSU+/htsKpqbVL5pWrlH9U+7diHi9ou17kCU="; 47 | npx:hasSignatureTarget this: . 48 | 49 | this: npx:introduces sub:step; 50 | prov:generatedAtTime "2020-12-29T16:54:20.582254"^^xsd:dateTime; 51 | prov:wasAttributedTo . 52 | } 53 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/simple1-signed-dsa.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | @prefix ex: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion ; 13 | np:hasProvenance sub:provenance ; 14 | np:hasPublicationInfo sub:pubinfo ; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | ex:mosquito ex:transmits ex:malaria . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | sub:signature npx:hasAlgorithm "DSA" ; 28 | npx:hasPublicKey "MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAEHvFRpU7ryp1gAOi2yoy2VX8jraJdwPo6ZC1idtsGVcmou89Y3KOoJmlW3VU8ZPolpVWuM+EPNmLNFmifYr+svu8AOQkilZBLdkS5BrPVxIpV0dLeaBUroof1wPsVuwEPOdNzWsEmPF1Az8qLGEdPbyn7ehWqO/lNVmW8+c4O2k=" ; 29 | npx:hasSignature "MCwCFFMlGKFn+75HC3sP6JjBNubA1yPKAhReEzogcNHOueSlRzocjB7fyU4zFw==" ; 30 | npx:hasSignatureTarget this: . 31 | 32 | this: dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 33 | pav:createdBy ; 34 | a npx:ExampleNanopub . 35 | } 36 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/simple1-signed-rsa.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | @prefix ex: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion ; 13 | np:hasProvenance sub:provenance ; 14 | np:hasPublicationInfo sub:pubinfo ; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | ex:mosquito ex:transmits ex:malaria . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | sub:signature npx:hasAlgorithm "RSA" ; 28 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwUtewGCpT5vIfXYE1bmf/Uqu1ojqnWdYxv+ySO80ul8Gu7m8KoyPAwuvaPj0lvPtHrg000qMmkxzKhYknEjq8v7EerxZNYp5B3/3+5ZpuWOYAs78UnQVjbHSmDdmryr4D4VvvNIiUmd0yxci47dTFUj4DvfHnGd6hVe5+goqdcwIDAQAB" ; 29 | npx:hasSignature "OC0xJTavw9h/JSZIZl/NLzEZqQk1E7XWV3o1btD1cojxf9FMtgZuMMOtnPcgydRn3gK0wbUh+ATV4sEFdG51khsrOOH7+RylqnaE9XD4L65dwPZ/PpI32/LMYsQ62rsb0ajWtXr5cKDIKaoah0U1V85XlLGhoEyzrLZCU5uqJbo=" ; 30 | npx:hasSignatureTarget this: . 31 | 32 | this: dc:created "2014-07-24T18:05:11+01:00"^^xsd:dateTime ; 33 | pav:createdBy ; 34 | a npx:ExampleNanopub . 35 | } 36 | -------------------------------------------------------------------------------- /tests/testsuite/valid/signed/workflow-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix dcterms: . 4 | @prefix np: . 5 | @prefix npx: . 6 | @prefix ns1: . 7 | @prefix ns2: . 8 | @prefix ns3: . 9 | @prefix prov: . 10 | @prefix rdfs: . 11 | @prefix xsd: . 12 | 13 | sub:Head { 14 | this: np:hasAssertion sub:assertion; 15 | np:hasProvenance sub:provenance; 16 | np:hasPublicationInfo sub:pubInfo; 17 | a np:Nanopublication . 18 | } 19 | 20 | sub:assertion { 21 | ns2:isStepOfPlan 22 | sub:plan . 23 | 24 | ns2:isStepOfPlan 25 | sub:plan; 26 | ns1:precedes . 27 | 28 | ns2:isStepOfPlan 29 | sub:plan; 30 | ns1:precedes . 31 | 32 | sub:plan dcterms:description "This is a test workflow."; 33 | ns3:hasFirstStep ; 34 | a ns2:Plan; 35 | rdfs:label "Test workflow" . 36 | } 37 | 38 | sub:provenance { 39 | sub:assertion prov:generatedAtTime "2020-10-27T10:46:36.512175"^^xsd:dateTime . 40 | } 41 | 42 | sub:pubInfo { 43 | sub:sig npx:hasAlgorithm "RSA"; 44 | npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoZmUKAHAF0CY2sKahOanR1V8wP62NOw3G0wcVLULWxqXB/gcW25bGPcA5RKoiuhT6dUbfcRXmwLknE29h6KWfKYLtNaqdrHbjSnNC65dNmNxCNp0i6ZLZRh51mxw9IPJHZrDqQ9bcLwm9d1G1fDKasA+h1vrF3Hv1YrQsF9aW1QIDAQAB"; 45 | npx:hasSignature "mSPg6u6lW+2TW+J5UrdmgqTpMfcCXdHeV1TrXeQQnzEY0P+c5Spf3YGbEgH9ZFtY+zKP70oM/M1wAyYhBhiEBwKsmsQpkl8nzMpClCEC0qxMcfSDkwTto9/EqYEC5nw5AYGnQKIetyCtRffmdommVb7hez/UQbNUbWwwoPHQhWA="; 46 | npx:hasSignatureTarget this: . 47 | 48 | this: npx:introduces sub:plan; 49 | prov:generatedAtTime "2020-10-27T10:46:36.512175"^^xsd:dateTime . 50 | } 51 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/disgenet-v3.0.0.0-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix rdfs: . 3 | @prefix xsd: . 4 | @prefix sio: . 5 | @prefix ncit: . 6 | @prefix lld: . 7 | @prefix miriam-gene: . 8 | @prefix miriam-pubmed: . 9 | @prefix eco: . 10 | @prefix wi: . 11 | @prefix prov: . 12 | @prefix pav: . 13 | @prefix prv: . 14 | @prefix dcterms: . 15 | @prefix np: . 16 | @prefix dgn-np: . 17 | @prefix dgn-gda: . 18 | @prefix dgn-void: . 19 | 20 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_head { 21 | this: np:hasAssertion dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_assertion ; 22 | np:hasProvenance dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_provenance ; 23 | np:hasPublicationInfo dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_publicationInfo ; 24 | a np:Nanopublication . 25 | 26 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_assertion a np:Assertion . 27 | 28 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_provenance a np:Provenance . 29 | 30 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_publicationInfo a np:PublicationInfo . 31 | } 32 | 33 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_assertion { 34 | miriam-gene:102724023 a ncit:C16612 . 35 | 36 | lld:C0035412 a ncit:C7057 . 37 | 38 | dgn-gda:DGN3b53ea037f55c5beeac8a85909a77158 sio:SIO_000628 miriam-gene:102724023 , lld:C0035412 ; 39 | a sio:SIO_001121 . 40 | } 41 | 42 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_provenance { 43 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_assertion dcterms:description "[HES1 is highly expressed in rhabdomyosarcomas, and the inhibition of HES1 restores differentiation in these cells.]. Sentence from MEDLINE/PubMed, a database of the U.S. National Library of Medicine."@en ; 44 | wi:evidence dgn-void:source_evidence_literature ; 45 | sio:SIO_000772 miriam-pubmed:20022559 ; 46 | prov:wasDerivedFrom dgn-void:befree-20150227 ; 47 | prov:wasGeneratedBy eco:ECO_0000203 . 48 | 49 | dgn-void:befree-20150227 pav:importedOn "2015-02-27"^^xsd:date . 50 | 51 | dgn-void:source_evidence_literature a eco:ECO_0000212 ; 52 | rdfs:comment "Gene-disease associations inferred from text-mining the literature."@en ; 53 | rdfs:label "DisGeNET evidence - LITERATURE"@en . 54 | } 55 | 56 | dgn-np:NP1018131.RA_gZ5_7VswlR91iNxwIQZj33tOrzZHDug6ix4FPs6h7s130_publicationInfo { 57 | this: dcterms:created "2015-08-25T14:48:12+02:00"^^xsd:dateTime ; 58 | dcterms:rights ; 59 | dcterms:rightsHolder dgn-void:IBIGroup ; 60 | dcterms:subject sio:SIO_000983 ; 61 | prv:usedData dgn-void:disgenetv3.0rdf ; 62 | pav:authoredBy , , , , ; 63 | pav:createdBy ; 64 | pav:version "v3.0.0.0" . 65 | 66 | dgn-void:disgenetv3.0rdf pav:version "v3.0.0" . 67 | } 68 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/fair-definition-1.trig: -------------------------------------------------------------------------------- 1 | @prefix dcterms: . 2 | @prefix npx: . 3 | @prefix this: . 4 | @prefix sub: . 5 | @prefix latest: . 6 | @prefix fair: . 7 | @prefix np: . 8 | @prefix prov: . 9 | @prefix rdfs: . 10 | @prefix xsd: . 11 | @prefix orcid: . 12 | @prefix skos: . 13 | 14 | sub:Head { 15 | this: np:hasAssertion sub:assertion; 16 | np:hasProvenance sub:provenance; 17 | np:hasPublicationInfo sub:pubinfo; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | fair:F1 a fair:FAIR-SubPrinciple; 23 | rdfs:isDefinedBy latest:; 24 | rdfs:label "F1"@en; 25 | skos:definition "(meta)data are assigned a globally unique and persistent identifier"@en . 26 | } 27 | 28 | sub:provenance { 29 | sub:assertion prov:hadPrimarySource . 30 | } 31 | 32 | sub:pubinfo { 33 | this: dcterms:created "2019-07-12T08:07:27.988+02:00"^^xsd:dateTime; 34 | dcterms:creator orcid:0000-0002-1267-0234, orcid:0000-0003-4727-9435; 35 | dcterms:rights ; 36 | npx:supersedes . 37 | } 38 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/fair-maturity-1.trig: -------------------------------------------------------------------------------- 1 | @prefix dcterms: . 2 | @prefix this: . 3 | @prefix sub: . 4 | @prefix fairmi: . 5 | @prefix dce: . 6 | @prefix np: . 7 | @prefix pav: . 8 | @prefix rdfs: . 9 | @prefix xsd: . 10 | @prefix fair: . 11 | @prefix foaf: . 12 | @prefix dcat: . 13 | @prefix orcid: . 14 | @prefix void: . 15 | 16 | sub:Head { 17 | this: np:hasAssertion sub:assertion; 18 | np:hasProvenance sub:provenance; 19 | np:hasPublicationInfo sub:pubinfo; 20 | a np:Nanopublication . 21 | } 22 | 23 | sub:assertion { 24 | fairmi:Gen2_MI_A2 a fairmi:FAIR-Maturity-Indicator; 25 | rdfs:label "FAIR Maturity Indicator Gen2-MI-A2"; 26 | foaf:primaryTopic fair:A2; 27 | fairmi:comments ""; 28 | fairmi:examples ""; 29 | fairmi:measuring "If there is a policy for metadata persistence"; 30 | fairmi:procedure """The GUID is resolved. Any hash-style metadata (e.g. JSON or microformat) is queried for a 'persistencePolicy' key. 31 | If that key exists, the test passes. Any Linked Data is queried for the http://www.w3.org/2000/10/swap/pim/doc"""; 32 | fairmi:rationale "Cross-references to data from third-party’s FAIR data and metadata will naturally degrade over time, and become “stale links”. In such cases, it is important for FAIR providers to continue to provide descriptors of what the data was to assist in the continued interpretation of those third-party data. As per FAIR Principle F3, this metadata remains discoverable, even in the absence of the data, because it contains an explicit reference to the IRI of the data."; 33 | fairmi:relevance "All"; 34 | fairmi:requirements "The Metadata GUID."; 35 | fairmi:validation "The presence of a persistencePolicy key, or a http://www.w3.org/2000/10/swap/pim/doc" . 36 | } 37 | 38 | sub:provenance { 39 | sub:_1 dce:format "text/markdown"; 40 | a void:Dataset, dcat:Distribution; 41 | dcat:downloadURL fairmi:Gen2_MI_A2.md . 42 | 43 | sub:assertion pav:authoredBy orcid:0000-0001-5306-5690, orcid:0000-0001-6960-357X, 44 | orcid:0000-0001-8888-635X, orcid:0000-0002-1164-1351, orcid:0000-0003-4727-9435; 45 | dcat:distribution sub:_1 . 46 | } 47 | 48 | sub:pubinfo { 49 | orcid:0000-0001-6960-357X foaf:name "Mark Wilkinson" . 50 | 51 | this: dcterms:created "2019-02-26"^^xsd:dateTime; 52 | dcterms:rights ; 53 | dcterms:rightsHolder ; 54 | pav:authoredBy orcid:0000-0001-6960-357X; 55 | pav:createdBy orcid:0000-0002-1267-0234 . 56 | } 57 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/fip-ontology-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix owl: . 4 | @prefix latest: . 5 | @prefix fip: . 6 | @prefix fair: . 7 | @prefix rdfs: . 8 | @prefix xsd: . 9 | @prefix dct: . 10 | @prefix np: . 11 | @prefix orcid: . 12 | @prefix skos: . 13 | 14 | sub:Head { 15 | this: np:hasAssertion sub:assertion; 16 | np:hasProvenance sub:provenance; 17 | np:hasPublicationInfo sub:pubinfo; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | fip:FIP-Question-F1-MD a owl:NamedIndividual; 23 | rdfs:isDefinedBy latest:; 24 | rdfs:label "FIP Question F1-MD"@en; 25 | skos:definition "What globally unique, persistent, resolvable identifiers do you use for metadata records?"@en; 26 | fip:refers-to-principle fair:F1 . 27 | } 28 | 29 | sub:provenance { 30 | sub:assertion dct:creator orcid:0000-0001-8888-635X, orcid:0000-0002-1267-0234, orcid:0000-0003-2195-3997 . 31 | } 32 | 33 | sub:pubinfo { 34 | this: dct:created "2021-01-11T16:25:38.313+01:00"^^xsd:dateTime; 35 | dct:creator orcid:0000-0001-8888-635X, orcid:0000-0002-1267-0234, orcid:0000-0003-2195-3997; 36 | dct:license . 37 | } 38 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/generif-aida-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix rdf: . 6 | @prefix dc: . 7 | @prefix pav: . 8 | @prefix prov: . 9 | @prefix np: . 10 | @prefix npx: . 11 | 12 | sub:Head { 13 | this: np:hasAssertion sub:assertion ; 14 | np:hasProvenance sub:provenance ; 15 | np:hasPublicationInfo sub:pubinfo ; 16 | a np:Nanopublication . 17 | } 18 | 19 | sub:assertion { 20 | sub:assertion npx:asSentence ; 21 | rdf:about , ; 22 | a npx:UnderspecifiedAssertion . 23 | } 24 | 25 | sub:provenance { 26 | sub:assertion prov:hadPrimarySource ; 27 | prov:wasDerivedFrom . 28 | } 29 | 30 | sub:pubinfo { 31 | this: dc:created "2014-06-16T13:47:00Z"^^xsd:dateTime ; 32 | dc:isPartOf ; 33 | pav:createdBy ; 34 | pav:version "1.3" ; 35 | rdfs:seeAlso . 36 | } 37 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/generif-aida-index.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix dc: . 6 | @prefix pav: . 7 | @prefix np: . 8 | @prefix npx: . 9 | @prefix ns1: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion ; 13 | np:hasProvenance sub:provenance ; 14 | np:hasPublicationInfo sub:pubinfo ; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | this: npx:appendsIndex ; 20 | npx:includesElement ns1:GeneRIF770912.RAEzc-_92gDoffTdT-lO1lfs0G-3cbFqE8M9TwHekmPCU , ns1:GeneRIF770914.RAiTr6l7lQeUPUtLbnbR_5nR2gHIJzZ-mc3GJ4W8LyJUw , ns1:GeneRIF770916.RAM9hxCFOK5l1MzOP01YV2VRkqMNsqtE2yvhMhZRbUjeE , ns1:GeneRIF770917.RAfg9jezQnZptz6WaV3L9I-rIfihPHT0rlBLclNZmyYl0 , ns1:GeneRIF770923.RAXQ3a60li67bfkHBGMfPhv3aR1e6fy93NYWOK_7TQfEw , ns1:GeneRIF770924.RAHQev9xmXlBoU3cnKretzYOLQ7B-QSiqNpkBG8ZB4LBo , ns1:GeneRIF770927.RA7rA6ka4mWFVDgGhJW5eRAIyZgt-dMT3KiwpFDrdFXLY , ns1:GeneRIF770933.RAZiwHAjDXxbEeT4gB4TtAv2wAMI_k1WBn8VXkBEsyX-k , ns1:GeneRIF770935.RABYwTUzdXTRe83LJr3la16Tn76mcGNl22aSFh_TiuybM , ns1:GeneRIF770946.RAyS4gnPbMRmcZBlaPQcxKWkxsix7HKEqL5gumIaNJSa4 , ns1:GeneRIF770947.RAwI9LKf_aso3psHtfxWFWdkuMnUMfPrvxuBqrq_9uLME , ns1:GeneRIF770948.RAXUVXmiehjSGiQfp91IOeqNcq9Mq1aduOepKcwDwlz-s , ns1:GeneRIF770951.RAWWhfEDEqMrvMTZaudCqGSNw4MTAyXSkSwEqAt0mLFgI , ns1:GeneRIF770952.RAATjHWaKGeBiHWAigP0tN6mbWlG-IbpH6juA5f7GqkL8 , ns1:GeneRIF770967.RAeBfHsvg1m57Q53zYWT8BLbs_o-EU9-n3sqVKMeoTx_A , ns1:GeneRIF770970.RAisrSrNn_b9cgie64rvMDZWuANlHRDmgptiHYk8Hgg-o , ns1:GeneRIF770977.RASwC4E-rE7mHePLKewFhZPF8g2qK7t96YqOYfa5RX3u4 , ns1:GeneRIF770978.RA7Kmmugi8OuCirfe5WKchnJhC3FuhQDi6M4O8mgR0CqE , ns1:GeneRIF770983.RAPrpJ2AVjds9nkgPjTs1dxmBj5PwM2edAUoI4EFVYUBc , ns1:GeneRIF770986.RASC2_WRCl0rpsl2QrZ6wHQ6vYIA9owdBeZfPmtjOFgU8 , ns1:GeneRIF771002.RAvz69kmd3ygiB2RW6jgg_cIrTo02hWhfqIVZKNfZcNTE , ns1:GeneRIF771007.RA7HhA9mfznlNtMsrtOzycpRpZVvWOBAWeZgMmydECqTQ , ns1:GeneRIF771011.RA2T6dvYGGwDwsj4DQiIH0DegLFRqq1603b_Zp49Bk6bw , ns1:GeneRIF771014.RA2C8hNaq75IfMUE1elTZY68BbCqQoOoBdV73wygIUxl8 , ns1:GeneRIF771017.RAE_yFyFDHqt9JB1tPvgbSaI-35vCXtmPGb1GNBQRKIXk , ns1:GeneRIF771021.RAJ8sgaowaLD0m5Dj5cHIDqOGZc1DsP7KvgNWQzBJ75t0 . 21 | } 22 | 23 | sub:provenance { 24 | sub:assertion a npx:IndexAssertion . 25 | } 26 | 27 | sub:pubinfo { 28 | this: "These nanopubs with AIDA sentences were automatically extracted from GeneRIF (updated format). See: Kuhn et al., Broadening the Scope of Nanopublications, ESWC 2013." ; 29 | "AIDA Nanopubs extracted from GeneRIF" ; 30 | dc:created "2015-03-04T10:39:03.941-08:00"^^xsd:dateTime ; 31 | pav:createdBy ; 32 | a npx:NanopubIndex ; 33 | rdfs:seeAlso . 34 | } 35 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/genuine-sempub-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix paper: . 4 | @prefix : . 5 | @prefix xsd: . 6 | @prefix dct: . 7 | @prefix pav: . 8 | @prefix prov: . 9 | @prefix np: . 10 | @prefix orcid: . 11 | @prefix fabio: . 12 | @prefix foaf: . 13 | @prefix prism: . 14 | @prefix schema: . 15 | 16 | sub:Head { 17 | this: np:hasAssertion sub:assertion ; 18 | np:hasProvenance sub:provenance ; 19 | np:hasPublicationInfo sub:pubinfo ; 20 | a np:Nanopublication . 21 | } 22 | 23 | sub:assertion { 24 | orcid:0000-0002-1267-0234 schema:affiliation :vu-cs ; 25 | schema:email "t.kuhn@vu.nl" ; 26 | schema:name "Tobias Kuhn" ; 27 | a foaf:Person . 28 | 29 | orcid:0000-0003-4727-9435 schema:affiliation :mu-ids ; 30 | schema:email "michel.dumontier@maastrichtuniversity.nl" ; 31 | schema:name "Michel Dumontier" ; 32 | a foaf:Person . 33 | 34 | :mu-ids schema:name "Institute of Data Science, Maastricht University, Netherlands" . 35 | 36 | :vu-cs schema:name "Department of Computer Science, VU University Amsterdam, Netherlands" . 37 | 38 | paper: prism:keyword "Linked Data" , "scholarly communication" , "semantic publishing" ; 39 | dct:title "Genuine Semantic Publishing" ; 40 | pav:authoredBy orcid:0000-0002-1267-0234 , orcid:0000-0003-4727-9435 ; 41 | a fabio:ResearchPaper . 42 | } 43 | 44 | sub:provenance { 45 | sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 , orcid:0000-0003-4727-9435 . 46 | } 47 | 48 | sub:pubinfo { 49 | this: dct:created "2017-06-15T14:39:51+02:00"^^xsd:dateTime ; 50 | pav:createdBy orcid:0000-0002-1267-0234 . 51 | } 52 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/genuine-sempub-2.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix paper: . 4 | @prefix : . 5 | @prefix xsd: . 6 | @prefix dct: . 7 | @prefix pav: . 8 | @prefix prov: . 9 | @prefix np: . 10 | @prefix orcid: . 11 | @prefix dbpedia: . 12 | @prefix cito: . 13 | 14 | sub:Head { 15 | this: np:hasAssertion sub:assertion ; 16 | np:hasProvenance sub:provenance ; 17 | np:hasPublicationInfo sub:pubinfo ; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | paper: cito:critiques dbpedia:Semantic_publishing ; 23 | cito:describes :GenuineSemanticPublishing ; 24 | cito:supports :GenuineSemanticPublishing . 25 | } 26 | 27 | sub:provenance { 28 | sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 , orcid:0000-0003-4727-9435 . 29 | } 30 | 31 | sub:pubinfo { 32 | this: dct:created "2017-06-15T14:39:51+02:00"^^xsd:dateTime ; 33 | pav:createdBy orcid:0000-0002-1267-0234 . 34 | } 35 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/globalbioticinteractions_aps-turfgrasses-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix np: . 4 | @prefix dcterms: . 5 | @prefix prov: . 6 | @prefix pav: . 7 | @prefix rdfs: . 8 | @prefix obo: . 9 | 10 | sub:Head { 11 | this: np:hasAssertion sub:Assertion; 12 | np:hasProvenance sub:Provenance; 13 | np:hasPublicationInfo sub:Pubinfo; 14 | a np:Nanopublication . 15 | } 16 | 17 | sub:Assertion { 18 | sub:Interaction obo:RO_0000057 sub:Organism_1, sub:Organism_2; 19 | a obo:GO_0044419 . 20 | 21 | sub:Organism_1 obo:RO_0002556 sub:Organism_2; 22 | rdfs:label "Agraricales" . 23 | 24 | sub:Organism_2 rdfs:label "Pennisetum clandestinum" . 25 | } 26 | 27 | sub:Provenance { 28 | sub:Assertion prov:wasDerivedFrom sub:Study . 29 | 30 | sub:Study dcterms:bibliographicCitation "Richard W. Smiley, primary collator* (last update 7/18/05). Diseases of Turfgrasses. The American Phytopathological Society. Accessed on 2017-05-25 at http://www.apsnet.org/publications/commonnames/Pages/Turfgrasses.aspx" . 31 | } 32 | 33 | sub:Pubinfo { 34 | this: dcterms:license ; 35 | pav:createdBy ; 36 | prov:wasDerivedFrom . 37 | 38 | dcterms:bibliographicCitation 39 | "Poelen, JH (2017). Plant pathogen-host interactions semi-automatically scraped from Common Names of Plant Diseases published by the American Phytopathological Society at http://www.apsnet.org/publications/commonnames/Pages/Turfgrasses.aspx using Samara, a Planteome (http://planteome.org) plant-trait scraper." . 40 | } 41 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/globalbioticinteractions_bees-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix np: . 4 | @prefix dcterms: . 5 | @prefix prov: . 6 | @prefix pav: . 7 | @prefix rdfs: . 8 | @prefix obo: . 9 | 10 | sub:Head { 11 | this: np:hasAssertion sub:Assertion; 12 | np:hasProvenance sub:Provenance; 13 | np:hasPublicationInfo sub:Pubinfo; 14 | a np:Nanopublication . 15 | } 16 | 17 | sub:Assertion { 18 | sub:Interaction obo:RO_0000057 sub:Organism_1, sub:Organism_2; 19 | a obo:GO_0044419 . 20 | 21 | sub:Organism_1 obo:RO_0002622 sub:Organism_2; 22 | rdfs:label "Lasioglossum mosselinum" . 23 | 24 | sub:Organism_2 rdfs:label "Compositae" . 25 | } 26 | 27 | sub:Provenance { 28 | sub:Assertion prov:wasDerivedFrom sub:Study . 29 | 30 | sub:Study dcterms:bibliographicCitation "Pauly, A., J. Gibbs and M. Kuhlmann. 2012. Capalictus, a new subgenus of Lasioglossum Curtis, 1833 from South Africa, with description of three new species (Hymenoptera, Apoidea, Halictidae). European Journal of Taxonomy 28: 1-28" . 31 | } 32 | 33 | sub:Pubinfo { 34 | this: dcterms:license ; 35 | pav:createdBy ; 36 | prov:wasDerivedFrom . 37 | 38 | dcterms:bibliographicCitation "Eardley C, Coetzer W. 2011. Catalogue of Afrotropical Bees. http://doi.org/10.15468/u9ezbh" . 39 | } 40 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/globalbioticinteractions_inaturalist-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix np: . 4 | @prefix dcterms: . 5 | @prefix prov: . 6 | @prefix pav: . 7 | @prefix rdfs: . 8 | @prefix obo: . 9 | 10 | sub:Head { 11 | this: np:hasAssertion sub:Assertion; 12 | np:hasProvenance sub:Provenance; 13 | np:hasPublicationInfo sub:Pubinfo; 14 | a np:Nanopublication . 15 | } 16 | 17 | sub:Assertion { 18 | sub:Interaction obo:RO_0000057 sub:Organism_1, sub:Organism_2; 19 | a obo:GO_0044419 . 20 | 21 | sub:Organism_1 obo:RO_0002454 sub:Organism_2; 22 | a ; 23 | rdfs:label "Callophrys augustinus" . 24 | 25 | sub:Organism_2 a ; 26 | rdfs:label "Cuscuta californica" . 27 | } 28 | 29 | sub:Provenance { 30 | sub:Assertion prov:wasDerivedFrom sub:Study . 31 | 32 | sub:Study dcterms:bibliographicCitation "Paul G. Johnson. 2016. Callophrys augustinus insect host plant Cuscuta californica. iNaturalist.org. Accessed at <https://www.inaturalist.org/observations/3149374> on 05 Apr 2018." . 33 | } 34 | 35 | sub:Pubinfo { 36 | this: dcterms:license ; 37 | pav:createdBy ; 38 | prov:wasDerivedFrom . 39 | 40 | dcterms:bibliographicCitation 41 | "http://iNaturalist.org is a place where you can record what you see in nature, meet other nature lovers, and learn about the natural world." . 42 | } 43 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/globalbioticinteractions_raymond-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix np: . 4 | @prefix dcterms: . 5 | @prefix prov: . 6 | @prefix pav: . 7 | @prefix rdfs: . 8 | @prefix obo: . 9 | @prefix geo: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:Assertion; 13 | np:hasProvenance sub:Provenance; 14 | np:hasPublicationInfo sub:Pubinfo; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:Assertion { 19 | sub:Interaction obo:RO_0000057 sub:Organism_1, sub:Organism_2; 20 | a obo:GO_0044419; 21 | geo:latitude -61.5; 22 | geo:longitude -43.5 . 23 | 24 | sub:Organism_1 obo:RO_0002470 sub:Organism_2; 25 | rdfs:label "Fulmarus glacialoides" . 26 | 27 | sub:Organism_2 rdfs:label "Gnathophausia sp." . 28 | } 29 | 30 | sub:Provenance { 31 | sub:Assertion prov:wasDerivedFrom sub:Study . 32 | 33 | sub:Study dcterms:bibliographicCitation "Ainley, D.G., Ribic, C.A. and Fraser, W.R. (1992) Does prey preference affect habitat choice in Antarctic seabirds? Marine Ecology Progress Series 90: 207-221" . 34 | } 35 | 36 | sub:Pubinfo { 37 | dcterms:bibliographicCitation "Raymond, B., Marshall, M., Nevitt, G., Gillies, C., van den Hoff, J., Stark, J.S., Losekoot, M., Woehler, E.J., and Constable, A.J. (2011) A Southern Ocean dietary database. Ecology 92(5):1188. Available from http://dx.doi.org/10.1890/10-1907.1 . Data set supplied by Ben Raymond." . 38 | 39 | this: dcterms:license ; 40 | pav:createdBy ; 41 | prov:wasDerivedFrom . 42 | } 43 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/liddi-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix np: . 4 | @prefix rdfs: . 5 | @prefix xsd: . 6 | @prefix dcterms: . 7 | @prefix prov: . 8 | @prefix ddiv: . 9 | @prefix ddir: . 10 | @prefix mesh: . 11 | @prefix umls: . 12 | @prefix orcid: . 13 | 14 | sub:head { 15 | this: np:hasAssertion sub:assertion ; 16 | np:hasProvenance sub:provenance ; 17 | np:hasPublicationInfo sub:publicationInfo ; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | ddir:EID0011 ddiv:mapstomesh mesh:D007003 ; 23 | ddiv:mapstoumls umls:C0020615 ; 24 | dcterms:identifier "LIDDI_resource:EID0002" ; 25 | dcterms:title "Hypoglycaemia"@en ; 26 | rdfs:label "Hypoglycaemia [LIDDI_resource:EID0002]"@en ; 27 | rdfs:type ddiv:event . 28 | } 29 | 30 | sub:provenance { 31 | sub:assertion prov:wasGeneratedBy sub:dataset_extraction . 32 | 33 | sub:dataset_extraction dcterms:creator ddir:mappingSoftware ; 34 | dcterms:title "Software Generated."@en ; 35 | a prov:Activity ; 36 | prov:startedAtTime "2015-07-17T03:40:07.572343"^^xsd:dateTime . 37 | 38 | ddir:mappingSoftware dcterms:title "Event Mapping Script"@en ; 39 | a prov:SoftwareAgent ; 40 | prov:Location . 41 | } 42 | 43 | sub:publicationInfo { 44 | this: dcterms:license ; 45 | prov:generatedAtTime "2015-07-17T03:40:07.572359"^^xsd:dateTime ; 46 | prov:wasAttributedTo orcid:0000-0001-8499-824X . 47 | } 48 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/linkflows-article-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix prov: . 6 | @prefix pav: . 7 | @prefix np: . 8 | @prefix doco: . 9 | @prefix c4o: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion; 13 | np:hasProvenance sub:provenance; 14 | np:hasPublicationInfo sub:pubinfo; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | sub:paragraph c4o:hasContent "Definition 4. (Microtask). A microtask m is a set of 3-tuples (t, h t , Q), where t is an RDF triple, h t corre- sponds to human-readable information that describes t, and Q is the set of quality issues to be assessed on triple t."; 20 | a doco:Paragraph . 21 | } 22 | 23 | sub:provenance { 24 | sub:assertion prov:hadPrimarySource ; 25 | prov:wasAttributedTo . 26 | } 27 | 28 | sub:pubinfo { 29 | this: dc:created "2019-11-08T18:05:11+01:00"^^xsd:dateTime; 30 | pav:createdBy . 31 | } 32 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/linkflows-review-1.trig: -------------------------------------------------------------------------------- 1 | @prefix dc: . 2 | @prefix this: . 3 | @prefix sub: . 4 | @prefix p7: . 5 | @prefix p4: . 6 | @prefix xsd: . 7 | @prefix prov: . 8 | @prefix pav: . 9 | @prefix np: . 10 | @prefix linkflows: . 11 | 12 | sub:Head { 13 | this: np:hasAssertion sub:assertion; 14 | np:hasProvenance sub:provenance; 15 | np:hasPublicationInfo sub:pubinfo; 16 | a np:Nanopublication . 17 | } 18 | 19 | sub:assertion { 20 | sub:comment-29 a linkflows:ActionNeededComment, linkflows:ContentComment, linkflows:NegativeComment, 21 | linkflows:ReviewComment; 22 | linkflows:hasCommentText "- Several times the word “fusion” is used as a verb, but it is a noun (cf. page 4, 17)"; 23 | linkflows:hasImpact "3"^^xsd:positiveInteger; 24 | linkflows:refersTo , 25 | p4:\#paragraph, , 26 | , p7:\#paragraph . 27 | } 28 | 29 | sub:provenance { 30 | sub:assertion prov:hadPrimarySource ; 31 | prov:wasAttributedTo . 32 | } 33 | 34 | sub:pubinfo { 35 | this: dc:created "2019-11-26T09:05:11+01:00"^^xsd:dateTime; 36 | pav:createdBy . 37 | } 38 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/nextprot-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix bfo: . 4 | @prefix dcterms: . 5 | @prefix eco: . 6 | @prefix efo: . 7 | @prefix np: . 8 | @prefix nx: . 9 | @prefix pav: . 10 | @prefix prov: . 11 | @prefix prv: . 12 | @prefix rdfs: . 13 | @prefix ro: . 14 | @prefix ts: . 15 | @prefix wi: . 16 | @prefix xsd: . 17 | 18 | sub:Head { 19 | this: np:hasAssertion sub:assertion ; 20 | np:hasProvenance sub:provenance ; 21 | np:hasPublicationInfo sub:pubinfo ; 22 | a np:Nanopublication . 23 | } 24 | 25 | sub:assertion { 26 | nx:NX_Q9Y6K8 bfo:BFO_0000066 ts:TS-2083 ; 27 | ro:has_quality "positive" . 28 | } 29 | 30 | sub:provenance { 31 | a eco:ECO_0000205 ; 32 | rdfs:label "neXtProt gold" . 33 | 34 | sub:_1 a efo:EFO_00027688 . 35 | 36 | sub:_10 a eco:ECO_0000218 . 37 | 38 | sub:_2 a eco:ECO_0000218 . 39 | 40 | sub:_3 a efo:EFO_00027688 . 41 | 42 | sub:_4 a eco:ECO_0000218 . 43 | 44 | sub:_5 a efo:EFO_00027688 . 45 | 46 | sub:_6 a eco:ECO_0000218 . 47 | 48 | sub:_7 a efo:EFO_00027688 . 49 | 50 | sub:_8 a eco:ECO_0000218 . 51 | 52 | sub:_9 a efo:EFO_00027688 . 53 | 54 | sub:assertion prv:usedData , , , , ; 55 | wi:evidence ; 56 | a eco:ECO_0000220 ; 57 | rdfs:comment " data, NX_Q9Y6K8 is expressed in Breast" ; 58 | prov:wasDerivedFrom sub:_1 , sub:_3 , sub:_5 , sub:_7 , sub:_9 ; 59 | prov:wasGeneratedBy sub:_10 , sub:_2 , sub:_4 , sub:_6 , sub:_8 . 60 | } 61 | 62 | sub:pubinfo { 63 | this: dcterms:created "2014-09-19T00:00:00.0Z"^^xsd:dateTime ; 64 | dcterms:rights ; 65 | dcterms:rightsHolder ; 66 | prv:usedData "neXtProt database" ; 67 | pav:authoredBy "CALIPHO project" , , , , ; 68 | pav:versionNumber "2" ; 69 | prov:wasGeneratedBy sub:_11 , sub:_12 , sub:_13 , sub:_14 , sub:_15 . 70 | 71 | sub:_11 a eco:ECO_0000205 . 72 | 73 | sub:_12 a eco:ECO_0000205 . 74 | 75 | sub:_13 a eco:ECO_0000205 . 76 | 77 | sub:_14 a eco:ECO_0000205 . 78 | 79 | sub:_15 a eco:ECO_0000205 . 80 | } 81 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/openbel-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix beldoc: . 4 | @prefix rdfs: . 5 | @prefix rdf: . 6 | @prefix xsd: . 7 | @prefix dct: . 8 | @prefix dce: . 9 | @prefix pav: . 10 | @prefix np: . 11 | @prefix belv: . 12 | @prefix prov: . 13 | @prefix schem: . 14 | @prefix go: . 15 | @prefix Protein: . 16 | @prefix hgnc: . 17 | @prefix geneProductOf: . 18 | @prefix hasAgent: . 19 | @prefix obo: . 20 | @prefix occursIn: . 21 | @prefix species: . 22 | @prefix pubmed: . 23 | @prefix orcid: . 24 | 25 | sub:Head { 26 | this: np:hasAssertion sub:assertion ; 27 | np:hasProvenance sub:provenance ; 28 | np:hasPublicationInfo sub:pubinfo ; 29 | a np:Nanopublication . 30 | } 31 | 32 | sub:assertion { 33 | sub:_1 hasAgent: sub:_2 ; 34 | a go:0003824 . 35 | 36 | sub:_2 geneProductOf: hgnc:12517 ; 37 | a Protein: . 38 | 39 | sub:_3 occursIn: obo:UBERON_0001134 , species:9606 ; 40 | rdf:object sub:_1 ; 41 | rdf:predicate belv:decreases ; 42 | rdf:subject schem:Adenosine%20triphosphate ; 43 | a rdf:Statement . 44 | 45 | sub:assertion rdfs:label "a(SCHEM:\"Adenosine triphosphate\") -| cat(p(HGNC:UCP1))" . 46 | } 47 | 48 | sub:provenance { 49 | beldoc: dce:description "Approximately 61,000 statements." ; 50 | dce:rights "Copyright (c) 2011-2012, Selventa. All rights reserved." ; 51 | dce:title "BEL Framework Large Corpus Document" ; 52 | pav:authoredBy sub:_5 ; 53 | pav:version "20131211" . 54 | 55 | sub:_4 prov:value "UCP1 contains six potential transmembrane a-helices (72) and acts under the form of a homodimer (73). Its uncoupling activity is increased by FFA (74–77) and by long chain fatty acyl CoA esters (78, 79), and decreased by purine nucleotide di- or tri-phosphates (12, 74)." ; 56 | prov:wasQuotedFrom pubmed:9703368 . 57 | 58 | sub:_5 rdfs:label "Selventa" . 59 | 60 | sub:assertion prov:hadPrimarySource pubmed:9703368 ; 61 | prov:wasDerivedFrom beldoc: , sub:_4 . 62 | } 63 | 64 | sub:pubinfo { 65 | this: dct:created "2014-07-03T14:34:13.226+02:00"^^xsd:dateTime ; 66 | pav:createdBy orcid:0000-0001-6818-334X , orcid:0000-0002-1267-0234 . 67 | } 68 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/provcorp-definition-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix latest: . 4 | @prefix np: . 5 | @prefix pav: . 6 | @prefix dct: . 7 | @prefix owl: . 8 | @prefix rdfs: . 9 | @prefix xsd: . 10 | @prefix orcid: . 11 | @prefix skos: . 12 | @prefix pvcpf: . 13 | @prefix oa: . 14 | 15 | sub:Head { 16 | this: np:hasAssertion sub:assertion; 17 | np:hasProvenance sub:provenance; 18 | np:hasPublicationInfo sub:pubinfo; 19 | a np:Nanopublication . 20 | } 21 | 22 | sub:assertion { 23 | pvcpf:hasSourceID a owl:DatatypeProperty; 24 | rdfs:domain oa:Annotation; 25 | rdfs:isDefinedBy latest:; 26 | rdfs:label "has Source ID"@en; 27 | skos:definition "Gives the source id of the annotated source."@en . 28 | } 29 | 30 | sub:provenance { 31 | sub:assertion pav:authoredBy orcid:0000-0002-1267-0234, orcid:0000-0002-3429-2879, 32 | orcid:0000-0002-5347-5750, orcid:0000-0002-8356-6469 . 33 | } 34 | 35 | sub:pubinfo { 36 | this: dct:created "2020-03-06T11:26:40.511+01:00"^^xsd:dateTime; 37 | dct:creator orcid:0000-0002-1267-0234, orcid:0000-0002-3429-2879, orcid:0000-0002-5347-5750, 38 | orcid:0000-0002-8356-6469; 39 | dct:license . 40 | } 41 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/provcorp-parc-annotation-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dct: . 5 | @prefix np: . 6 | @prefix pvcpp: . 7 | @prefix oa: . 8 | @prefix rdfs: . 9 | @prefix textoffset: . 10 | 11 | sub:Head { 12 | this: np:hasAssertion sub:assertion; 13 | np:hasProvenance sub:provenance; 14 | np:hasPublicationInfo sub:pubinfo; 15 | a np:Nanopublication . 16 | } 17 | 18 | sub:assertion { 19 | sub:annotation dct:isPartOf ; 20 | a oa:Annotation; 21 | oa:hasBody this:; 22 | pvcpp:hasAttrID "wsj_0132_PDTB_annotation_level.xml_set_1"; 23 | pvcpp:hasContentAnnotatedWord textoffset:1002-1008, textoffset:891-904, textoffset:905-910, 24 | textoffset:911-916, textoffset:917-926, textoffset:927-930, textoffset:931-936, textoffset:937-943, 25 | textoffset:944-947, textoffset:948-955, textoffset:956-960, textoffset:961-964, textoffset:965-968, 26 | textoffset:969-975, textoffset:976-980, textoffset:981-989, textoffset:990-992, textoffset:993-1001; 27 | pvcpp:hasCueAnnotatedWord textoffset:1022-1027; 28 | pvcpp:hasSourceAnnotatedWord textoffset:1010-1013, textoffset:1014-1021 . 29 | } 30 | 31 | sub:provenance { 32 | sub:assertion dct:created "2016-05-01T00:00:00"^^xsd:dateTime; 33 | dct:creator . 34 | } 35 | 36 | sub:pubinfo { 37 | this: dct:created "2020-06-18T13:52:04.167+02:00"^^xsd:dateTime; 38 | dct:creator , , 39 | , ; 40 | dct:license ; 41 | rdfs:comment "You are free to use this information when referencing the above paper and creator."; 42 | rdfs:seeAlso . 43 | } 44 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/trusty1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix xsd: . 4 | @prefix dc: . 5 | @prefix pav: . 6 | @prefix prov: . 7 | @prefix np: . 8 | @prefix npx: . 9 | 10 | sub:Head { 11 | this: np:hasAssertion sub:assertion ; 12 | np:hasProvenance sub:provenance ; 13 | np:hasPublicationInfo sub:pubinfo ; 14 | a np:Nanopublication . 15 | } 16 | 17 | sub:assertion { 18 | sub:assertion npx:asSentence ; 19 | a npx:UnderspecifiedAssertion . 20 | } 21 | 22 | sub:provenance { 23 | sub:assertion prov:hadPrimarySource . 24 | } 25 | 26 | sub:pubinfo { 27 | this: dc:created "2014-07-29T10:13:35+01:00"^^xsd:dateTime ; 28 | pav:createdBy ; 29 | a npx:ExampleNanopub . 30 | } 31 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/wd-metabolite-species-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix wd: . 4 | @prefix np: . 5 | @prefix has-source: . 6 | @prefix has-inchikey: . 7 | @prefix orcid: . 8 | @prefix wdt: . 9 | @prefix owl: . 10 | @prefix pav: . 11 | @prefix rdfs: . 12 | @prefix skos: . 13 | 14 | sub:Head { 15 | this: np:hasAssertion sub:assertion; 16 | np:hasProvenance sub:provenance; 17 | np:hasPublicationInfo sub:pubinfo; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | wd:Q15978631 rdfs:label "Homo sapiens"@en; 23 | skos:exactMatch . 24 | 25 | wd:Q4596897 has-inchikey: "CQOQDQWUFQDJMK-SSTWWWIQSA-N"; 26 | rdfs:label "2-methoxyestradiol"@en; 27 | wdt:P703 wd:Q15978631 . 28 | } 29 | 30 | sub:provenance { 31 | sub:assertion has-source: wd:Q2013, wd:Q28601559 . 32 | 33 | wd:Q28601559 rdfs:label "Recon 2.2: from reconstruction to model of human metabolism"@en; 34 | owl:sameAs . 35 | } 36 | 37 | sub:pubinfo { 38 | this: "2019-01-13T09:51:45.687+01:00"^^; 39 | pav:createdBy orcid:0000-0001-7542-0286 . 40 | } 41 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/wikipathways-complexes-20170510-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix has-source: . 4 | @prefix wp: . 5 | @prefix xsd: . 6 | @prefix dcterms: . 7 | @prefix np: . 8 | @prefix prov: . 9 | @prefix dc: . 10 | @prefix pmid: . 11 | 12 | sub:head { 13 | this: np:hasAssertion sub:assertion ; 14 | np:hasProvenance sub:provenance ; 15 | np:hasPublicationInfo sub:publicationInfo ; 16 | a np:Nanopublication . 17 | } 18 | 19 | sub:assertion { 20 | a wp:Protein . 21 | 22 | a wp:GeneProduct , wp:Protein . 23 | 24 | a wp:GeneProduct , wp:Protein . 25 | 26 | a wp:GeneProduct , wp:Protein . 27 | 28 | a wp:GeneProduct , wp:Protein . 29 | 30 | wp:organismName "Homo sapiens" ; 31 | wp:participant , , , , ; 32 | a wp:Complex . 33 | } 34 | 35 | sub:provenance { 36 | dc:title "Folate Metabolism"@en . 37 | 38 | sub:assertion has-source: pmid:10569628 , pmid:17081103 , . 39 | } 40 | 41 | sub:publicationInfo { 42 | this: dcterms:created "2017-05-10T00:17:27.579+02:00"^^xsd:dateTime ; 43 | dcterms:rights ; 44 | prov:wasDerivedFrom . 45 | } 46 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/wikipathways-interactions-20170510-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix has-source: . 4 | @prefix wp: . 5 | @prefix xsd: . 6 | @prefix dcterms: . 7 | @prefix np: . 8 | @prefix wd: . 9 | @prefix prov: . 10 | @prefix dc: . 11 | @prefix pmid: . 12 | 13 | sub:head { 14 | this: np:hasAssertion sub:assertion ; 15 | np:hasProvenance sub:provenance ; 16 | np:hasPublicationInfo sub:publicationInfo ; 17 | a np:Nanopublication . 18 | } 19 | 20 | sub:assertion { 21 | a wp:Metabolite . 22 | 23 | a wp:Metabolite . 24 | 25 | wp:organismName "Homo sapiens" ; 26 | wp:source ; 27 | wp:target ; 28 | a wp:Interaction . 29 | } 30 | 31 | sub:provenance { 32 | dc:title "Metabolism of carbohydrates"@en . 33 | 34 | sub:assertion has-source: pmid:11371164 , pmid:13538944 , pmid:7989588 , . 35 | } 36 | 37 | sub:publicationInfo { 38 | sub:activity a prov:Activity ; 39 | prov:atLocation wd:Q1137652 ; 40 | prov:used . 41 | 42 | this: dcterms:created "2017-05-10T00:15:24.459+02:00"^^xsd:dateTime ; 43 | dcterms:rights ; 44 | prov:wasDerivedFrom ; 45 | prov:wasGeneratedBy sub:activity . 46 | } 47 | -------------------------------------------------------------------------------- /tests/testsuite/valid/trusty/wikipathways-pathwayParticipation-20170510-1.trig: -------------------------------------------------------------------------------- 1 | @prefix this: . 2 | @prefix sub: . 3 | @prefix has-source: . 4 | @prefix wp: . 5 | @prefix xsd: . 6 | @prefix dcterms: . 7 | @prefix np: . 8 | @prefix wd: . 9 | @prefix prov: . 10 | @prefix dc: . 11 | @prefix pmid: . 12 | @prefix obo: . 13 | 14 | sub:head { 15 | this: np:hasAssertion sub:assertion ; 16 | np:hasProvenance sub:provenance ; 17 | np:hasPublicationInfo sub:publicationInfo ; 18 | a np:Nanopublication . 19 | } 20 | 21 | sub:assertion { 22 | dcterms:isPartOf ; 23 | wp:organismName "Homo sapiens" ; 24 | a wp:Complex . 25 | 26 | wp:pathwayOntologyTag obo:PW_0000003 , obo:PW_0001162 . 27 | } 28 | 29 | sub:provenance { 30 | dc:title "Opioid Signalling"@en . 31 | 32 | sub:assertion has-source: pmid:7526403 , . 33 | } 34 | 35 | sub:publicationInfo { 36 | sub:activity a prov:Activity ; 37 | prov:atLocation wd:Q1137652 ; 38 | prov:used . 39 | 40 | this: dcterms:created "2017-05-10T00:18:36.600+02:00"^^xsd:dateTime ; 41 | dcterms:rights ; 42 | prov:wasDerivedFrom ; 43 | prov:wasGeneratedBy sub:activity . 44 | } 45 | --------------------------------------------------------------------------------